home *** CD-ROM | disk | FTP | other *** search
/ cs.rhul.ac.uk / www.cs.rhul.ac.uk.zip / www.cs.rhul.ac.uk / pub / rdp / rdp_cs3460.tar / rdp.bnf < prev    next >
Text File  |  1998-05-07  |  21KB  |  416 lines

  1. (*****************************************************************************
  2. *
  3. * RDP release 1.50 by Adrian Johnstone (A.Johnstone@rhbnc.ac.uk) 20 December 1997
  4. *
  5. * rdp.bnf - decorated rdp grammar
  6. *
  7. * This file may be freely distributed. Please mail improvements to the author.
  8. *
  9. *****************************************************************************)
  10. TITLE("Recursive descent parser generator V1.50 (c) Adrian Johnstone 1997")
  11. SUFFIX("bnf")
  12. SHOW_SKIPS
  13. PASSES(2)
  14. TAB_WIDTH(8)
  15. TEXT_SIZE(34000)
  16. MAX_ERRORS(50)
  17. MAX_WARNINGS(120)
  18. OUTPUT_FILE("rdparser")
  19. (* TREE *)
  20. USES("rdp_aux.h")
  21. USES("rdp_gram.h")
  22. USES("rdp_prnt.h")
  23.  
  24. SYMBOL_TABLE(rdp 101 31
  25.              symbol_compare_string
  26.              symbol_hash_string
  27.              symbol_print_string
  28.              [* RDP_DATA *]
  29.             )
  30.  
  31. SYMBOL_TABLE(tokens 101 31
  32.              symbol_compare_string
  33.              symbol_hash_string
  34.              symbol_print_string
  35.              [* RDP_DATA *]
  36.             )
  37.  
  38. SYMBOL_TABLE(codes 101 31
  39.              symbol_compare_string
  40.              symbol_hash_string
  41.              symbol_print_string
  42.              [* RDP_DATA *]
  43.             )
  44.  
  45. SYMBOL_TABLE(locals 101 31
  46.              symbol_compare_string
  47.              symbol_hash_string
  48.              symbol_print_string
  49.              [* char* id; *]
  50.             )
  51.  
  52. ARG_BLANK("")
  53. ARG_BOOLEAN(e rdp_expanded "Write out expanded BNF along with first and follow sets")
  54. ARG_BOOLEAN(E rdp_error_production_name "Add rule name to error messages in generated parser")
  55. ARG_BOOLEAN(F rdp_force "Force creation of output files")
  56. ARG_BOOLEAN(p rdp_parser_only "Make parser only (omit semantic actions from generated code)")
  57. ARG_BOOLEAN(R rdp_trace "Add rule entry and exit messages")
  58.  
  59. ARG_BLANK("")
  60. ARG_BLANK("You can contact the author (Adrian Johnstone) at:")
  61. ARG_BLANK("")
  62. ARG_BLANK("Computer Science Department, Royal Holloway, University of London")
  63. ARG_BLANK("Egham, Surrey, TW20 0EX UK. Email: A.Johnstone@rhbnc.ac.uk")
  64.  
  65. PRE_PARSE([* rdp_pre_parse(); *])
  66. POST_PARSE([* rdp_post_parse(rdp_outputfilename, rdp_force); *])
  67.  
  68. PARSER(unit)
  69.  
  70. unit ::= { rule | dir}
  71.          [* if (rdp_rule_count == 0) text_message(TEXT_FATAL,"no rule definitions found\n"); *] .
  72.  
  73. dir ::= 'INCLUDE' '(' code: filename
  74.                      [* if (text_open(filename) == NULL)
  75.                            text_message(TEXT_ERROR_ECHO, "include file '%s' not found\n", filename);
  76.                         text_get_char();
  77.                         scan_();
  78.                       *]@2
  79.                  ')' |
  80.  
  81.        (* List directives *)
  82.  
  83.        'ARG_BOOLEAN' '(' ID:key ( ID:var | code:var ) String:desc ')' [* rdp_add_arg(ARG_BOOLEAN, key, var, desc); *]@2 |
  84.        'ARG_NUMERIC' '(' ID:key ( ID:var | code:var ) String:desc ')' [* rdp_add_arg(ARG_NUMERIC, key, var, desc); *]@2 |
  85.        'ARG_STRING'  '(' ID:key ( ID:var | code:var ) String:desc ')' [* rdp_add_arg(ARG_STRING,  key, var, desc); *]@2 |
  86.        'ARG_BLANK'   '(' String:desc ')'               [* rdp_add_arg(ARG_BLANK,   NULL, NULL, desc); *]@2 |
  87.  
  88.        [* rdp_table_list *temp; *]
  89.        'SYMBOL_TABLE' '(' ID: name INTEGER:size INTEGER:prime
  90.                           ID: compare ID:hash ID:print
  91.                           code: data_fields
  92.                           [*temp = (rdp_table_list*) mem_malloc(sizeof(rdp_table_list));
  93.                             temp->name = name;
  94.                             temp->size = (unsigned) size;
  95.                             temp->prime = (unsigned) prime;
  96.                             temp->compare = compare;
  97.                             temp->hash = hash;
  98.                             temp->print = print;
  99.                             temp->data_fields = data_fields;
  100.                             temp->next = rdp_dir_symbol_table;
  101.                             rdp_dir_symbol_table = temp;
  102.                           *]@2
  103.                 ')' |
  104.  
  105.        [* rdp_string_list *temp; *]
  106.        'USES' '(' String: s
  107.                   [*temp = (rdp_string_list*) mem_malloc(sizeof(rdp_string_list));
  108.                     temp->str1 = s;
  109.                     temp->next = rdp_dir_include;
  110.                     rdp_dir_include = temp;
  111.                   *]@2
  112.                ')' |
  113.  
  114.        (* String directives *)
  115.        'OUTPUT_FILE' '(' String:s [* rdp_dir_output_file = s; *] ')' |
  116.        'PARSER' '(' ID:name [* rdp_start_prod = rdp_find(name, K_PRIMARY, RDP_OLD); rdp_start_prod->call_count++; *]@2 ')' |
  117.        'POST_PARSE' '(' code:s [* rdp_dir_post_parse = s; *] ')' |
  118.        'PRE_PARSE' '(' code:s [* rdp_dir_pre_parse = s; *] ')' |
  119.        'SUFFIX' '(' String:s [* rdp_dir_suffix = s; *] ')' |
  120.        'TITLE' '(' String: s [* rdp_dir_title = s; *] ')' |
  121.  
  122.        (* Numeric directives *)
  123.        'MAX_ERRORS' '(' INTEGER:n [* rdp_dir_max_errors = (unsigned) n; *] ')' |
  124.        'MAX_WARNINGS' '(' INTEGER:n [* rdp_dir_max_warnings = (unsigned) n; *] ')' |
  125.        'PASSES' '(' INTEGER:n [* rdp_dir_passes = (unsigned) n; *] ')' |
  126.        'TAB_WIDTH' '(' INTEGER:n [* rdp_dir_tab_width = (unsigned) n; *] ')' |
  127.        'TEXT_SIZE' '(' INTEGER:n [* rdp_dir_text_size = (unsigned) n; *] ')' |
  128.  
  129.        (* Boolean directives *)
  130.        ('ANNOTATED_EPSILON_TREE' [* rdp_dir_annotated_epsilon_tree = 1; rdp_dir_epsilon_tree = 1; *] |
  131.         'EPSILON_TREE' [* rdp_dir_epsilon_tree = 1; *] |
  132.         'TREE'
  133.        )
  134.        [* rdp_dir_tree = 1; *]@1
  135.        [ '(' code: str [* rdp_dir_tree_fields = str; *]  ')' ] |
  136.        'CASE_INSENSITIVE' [* rdp_dir_case_insensitive = 1; *] |
  137.        'SHOW_SKIPS' [* rdp_dir_show_skips = 1; *] |
  138.  
  139.        (* Obsolete *)
  140.        'OPTION' [* text_message(TEXT_ERROR_ECHO, "Obsolete directive: OPTION replaced by ARG_* at version 1.5\n"); *]
  141.                  '(' String [ code ] ')' |
  142.  
  143.        'PRE_PROCESS' [* text_message(TEXT_ERROR_ECHO, "Obsolete directive: PRE_PROCESS renamed PRE_PARSE at version 1.3\n"); *]
  144.                  '(' code ')' |
  145.        'POST_PROCESS' [* text_message(TEXT_ERROR_ECHO, "Obsolete directive: POST_PROCESS renamed POST_PARSE at version 1.3\n"); *]
  146.                  '(' code ')' |
  147.        'SET_SIZE' [* text_message(TEXT_ERROR_ECHO, "Obsolete directive: SET_SIZE deleted at version 1.4\n"); *]
  148.                  '(' INTEGER ')' |
  149.        'HASH_SIZE' [* text_message(TEXT_ERROR_ECHO, "Obsolete directive: HASH_SIZE replaced by SYMBOL_TABLE at version 1.4\n"); *]
  150.                  '(' INTEGER ')' |
  151.        'HASH_PRIME' [* text_message(TEXT_ERROR_ECHO, "Obsolete directive: HASH_PRIME replaced by SYMBOL_TABLE at version 1.4\n"); *]
  152.                  '(' INTEGER ')' |
  153.        'INTERPRETER' [* text_message(TEXT_ERROR_ECHO, "Obsolete directive: INTERPRETER mode deleted at version 1.4\n"); *]
  154.                  '(' INTEGER ')'
  155.        .
  156.  
  157. rule:rdp_data* ::= [* unsigned stars; *]
  158.                    ID:name
  159.                    [* rdp_primary_id = name; rdp_component = 0;
  160.                       rdp_rule_count++;
  161.                       result = rdp_find(rdp_primary_id, K_PRIMARY, rdp_pass == 1 ? RDP_NEW : RDP_OLD);
  162.                       if (rdp_start_prod == NULL)
  163.                       {
  164.                         rdp_start_prod = result;
  165.                         result->call_count++;
  166.                       }
  167.                    *]
  168.  
  169.                    ['(' [* result->parameterised = 1; *]
  170.                         { [* rdp_param_list *param; type = "void"; *]
  171.                           ID:name [ ':' ID:type
  172.                           [* stars = 0; *]
  173.                           {'*' [* stars++; *] } ]
  174.                           [* param = (rdp_param_list* ) mem_calloc(sizeof(rdp_param_list), 1);
  175.                              param->id = name;
  176.                              param->type = type;
  177.                              param->stars = stars;
  178.                              param->next = result->params;
  179.                              result->params = param;
  180.                           *]@1
  181.                         }
  182.                     ')'
  183.                    ]
  184.  
  185.                    [* type = "void"; stars = 0; *]
  186.  
  187.                    [':' ID:type {'*' [* stars++; *] } ]
  188.  
  189.                    [* result->promote_default = PROMOTE_DONT; *]@2
  190.                    [ '^_' [* result->promote_default = PROMOTE_DONT; *]@2 |
  191.                      '^'  [* result->promote_default = PROMOTE; *]@2 |
  192.                      '^^' [* result->promote_default = PROMOTE_AND_COPY; *]@2 |
  193.                      '^^^' [* result->promote_default = PROMOTE_ABOVE; *]@2
  194.                    ]
  195.  
  196.                    [* rdp_comment_only = 1; /* set comments only flag */ *]
  197.                    '::='   prod:body [* rdp_rule_count++;
  198.                                      result->list = body;
  199.                                      result->been_defined = 1;
  200.                                      result->return_type = type;
  201.                                      result->return_type_stars = stars;
  202.                                      result->comment_only = rdp_comment_only;
  203.                                   *]@2
  204.                    '.' .
  205.  
  206. prod:rdp_list*  ::= [* rdp_list* end; *]
  207.                    [* end = result = (rdp_list*) mem_calloc(sizeof(rdp_list), 1); *]@2
  208.                    ( seq: body [* end->next = (rdp_list*) mem_calloc(sizeof(rdp_list), 1);
  209.                                   end = end->next;
  210.                                   end->production = rdp_find(text_insert_substring("rdp", rdp_primary_id, rdp_component++), K_SEQUENCE, RDP_NEW);
  211.                                   end->production->call_count++;
  212.                                   end->production->list = body;
  213.                                *]@2
  214.                    )1@0'|'  [* result = result->next; *]@2 . (* could dispose header here *)
  215.  
  216.  
  217. seq:rdp_list* ::= [* rdp_list* end; int promote_op; int promote_epsilon; *]
  218.                    [* end = result = (rdp_list*) mem_calloc(sizeof(rdp_list), 1); *]@2
  219.  
  220.                    < [* ret_name = NULL; promote_epsilon = PROMOTE_DONT; promote_op = PROMOTE_DEFAULT; *]@2
  221.                      ((item_ret:body [* rdp_comment_only = 0; *] | item_com:body)
  222.                       [':' ID:ret_name] [ '^_' [* promote_op = PROMOTE_DONT; *]@2 |
  223.                                           '^'  [* promote_op = PROMOTE; *]@2 |
  224.                                           '^^' [* promote_op = PROMOTE_AND_COPY; *]@2 |
  225.                                           '^^^'[* promote_op = PROMOTE_ABOVE; *]@2
  226.                                         ] |
  227.                       item_inl: body [* rdp_comment_only = 0; *]
  228.                                      [* promote_op=body->promote; default_action = NULL; *]@2
  229.                                      [ ':' [ ID [* text_message(TEXT_ERROR_ECHO,"Illegal grammar element: expressions may not retun a value"); *]@2 (* This is not allowed on pass 2 *) ]
  230.                                            [ code:default_action
  231.                                              ['^_' [* promote_epsilon = PROMOTE_DONT; *]@2 |
  232.                                               '^'  [* promote_epsilon = PROMOTE; *]@2 |
  233.                                               '^^' [* promote_epsilon = PROMOTE_AND_COPY; *]@2 |
  234.                                               '^^^' [* promote_epsilon = PROMOTE_ABOVE; *]@2
  235.                                               ]
  236.                                               |
  237.                                               (
  238.                                                 '^_' [* promote_epsilon = PROMOTE_DONT; *]@2 |
  239.                                                 '^'  [* promote_epsilon = PROMOTE; *]@2 |
  240.                                                 '^^' [* promote_epsilon = PROMOTE_AND_COPY; *]@2 |
  241.                                                 '^^^' [* promote_epsilon = PROMOTE_ABOVE; *]@2
  242.                                               )
  243.                                             ]
  244.                                      ]
  245.                      )
  246.                      [* end->next = (rdp_list*) mem_calloc(sizeof(rdp_list), 1);
  247.                         end = end->next;
  248.                         end->production = body;
  249.                         end->actuals = body->actuals;
  250.                         end->return_name = ret_name;
  251.                         end->promote = promote_op;
  252.                         end->promote_epsilon = promote_epsilon;
  253.                         end->default_action = default_action;
  254.                      *]@2
  255.                    > [* result = result->next; *]@2. (* could dispose header here *)
  256.  
  257.  
  258. item_ret:rdp_data* ::= ID:name [* result = rdp_find(name, K_PRIMARY, RDP_OLD);
  259.                                   rdp_check_eoln(name);
  260.                                   result->call_count++; /* increment call count */
  261.                                   result->actuals = NULL;
  262.                                *]@2
  263.  
  264.  
  265.                          [* if (rdp_pass == 2 && result->parameterised ) { *]
  266.                            '('
  267.                            { [* rdp_param_list *param; *]
  268.  
  269.                              ( INTEGER:n
  270.                                [* param = (rdp_param_list* ) mem_calloc(sizeof(rdp_param_list), 1);
  271.                                   param->n = n;
  272.                                   param->next = result->actuals;
  273.                                   result->actuals = param;
  274.                                   param->flavour = PARAM_INTEGER;
  275.                                *]@2 |
  276.  
  277.                                REAL:r
  278.                                [* param = (rdp_param_list* ) mem_calloc(sizeof(rdp_param_list), 1);
  279.                                   param->r = r;
  280.                                   param->next = result->actuals;
  281.                                   result->actuals = param;
  282.                                   param->flavour = PARAM_REAL;
  283.                                *]@2 |
  284.  
  285.                                String:str
  286.                                [* param = (rdp_param_list* ) mem_calloc(sizeof(rdp_param_list), 1);
  287.                                   param->id = str;
  288.                                   param->next = result->actuals;
  289.                                   result->actuals = param;
  290.                                   param->flavour = PARAM_STRING;
  291.                                *]@2 |
  292.  
  293.                                ID:name
  294.                                [* param = (rdp_param_list* ) mem_calloc(sizeof(rdp_param_list), 1);
  295.                                   param->id = name;
  296.                                   param->next = result->actuals;
  297.                                   result->actuals = param;
  298.                                   param->flavour = PARAM_ID;
  299.                                *]@2
  300.                              )
  301.                            }
  302.                            ')'
  303.                          [* } *]
  304.  
  305.                           |
  306.  
  307.                        token:name [* result = (rdp_data*) rdp_process_token(name); *]@2 |
  308.  
  309.                        'CHAR' '(' token:name ')' [* result = rdp_find_extended(name, NULL, SCAN_P_CHAR); *]@2 |
  310.                        'CHAR_ESC' '(' token:name token:quote ')' [* result = rdp_find_extended(name, quote, SCAN_P_CHAR_ESC); *]@2 |
  311.                        'STRING' '(' token:name ')' [* result = rdp_find_extended(name, NULL, SCAN_P_STRING); *]@2 |
  312.                        'STRING_ESC' '(' token:name token:quote ')' [* result = rdp_find_extended(name, quote, SCAN_P_STRING_ESC); *]@2 |
  313.                        'COMMENT_VISIBLE' '(' token:name token:close ')' [* result = rdp_find_extended(name, close, SCAN_P_COMMENT_VISIBLE); *]@2 |
  314.                        'COMMENT_NEST_VISIBLE' '(' token:name token:close ')' [* result = rdp_find_extended(name, close, SCAN_P_COMMENT_NEST_VISIBLE); *]@2 |
  315.                        'COMMENT_LINE_VISIBLE' '(' token:name ')' [* result = rdp_find_extended(name, NULL, SCAN_P_COMMENT_LINE_VISIBLE); *]@2 |
  316.  
  317.                        (* Obsolete scanner primitives *)
  318.                        'NUMBER' [* text_message(TEXT_ERROR_ECHO, "Obsolete scanner primitive: NUMBER renamed INTEGER at version 1.3\n"); *] |
  319.                        'NEW_ID' [* text_message(TEXT_ERROR_ECHO, "Obsolete scanner primitive: NEW_ID deleted at version 1.4\n"); *] |
  320.                        'ALT_ID' [* text_message(TEXT_ERROR_ECHO, "Obsolete scanner primitive: ALT_ID deleted at version 1.4\n"); *] |
  321.                        (* 'EOF'    [* text_message(TEXT_ERROR_ECHO, "Obsolete scanner primitive: EOF deleted at version 1.4\n"); *] *)
  322.  
  323.                        (* Now some wackyness to cope with strings, integers and
  324.                          reals during pass1 in paramaters... *)
  325.  
  326.                        String:str [* text_message(TEXT_ERROR_ECHO, "Illegal grammar element: perhaps you intended to write '%s'\n", str); *]@2 |
  327.                        INTEGER [* text_message(TEXT_ERROR_ECHO, "Illegal grammar element: an integer may not appear here\n"); *]@2 |
  328.                        REAL [* text_message(TEXT_ERROR_ECHO, "Illegal grammar element: a real may not appear here\n"); *]@2 .
  329.  
  330. item_com:rdp_data* ::= 'COMMENT' '(' token:name token:close ')' [* result = rdp_find_extended(name, close, SCAN_P_COMMENT); *]@2 |
  331.                        'COMMENT_LINE' '(' token:name ')' [* result = rdp_find_extended(name, NULL, SCAN_P_COMMENT_LINE); *]@2 |
  332.                        'COMMENT_NEST' '(' token:name token:close ')' [* result = rdp_find_extended(name, close, SCAN_P_COMMENT_NEST); *]@2 .
  333.  
  334.  
  335. item_inl:rdp_data* ::= [* int promote_op = PROMOTE_DEFAULT; *]
  336.                      (
  337.                      code:name
  338.                      [* result = rdp_find(name, K_CODE, RDP_ANY);
  339.                         result->contains_null = 1;
  340.                         result->call_count++; /* increment call count */
  341.                      *]@2
  342.                      [ '@' INTEGER:pass [* result->code_pass = (unsigned) pass; *]@2 ] |
  343.  
  344.                      '('prod:body')'
  345.                      [* result = rdp_find(text_insert_substring("rdp", rdp_primary_id, rdp_component++), K_LIST, RDP_ANY);
  346.                         result->promote = promote_op;
  347.                         result->list = body;
  348.                         result->call_count++;
  349.                         result->lo = 1;
  350.                         result->hi = 1;
  351.                      *]@2
  352.  
  353.                      (* Now do the version 1.5 iterator operator: watch out
  354.                         because this is not the full iteration operator!! *)
  355.  
  356.                      [ [ INTEGER:val [* result->lo = val; *]@2 ]
  357.                        '@'
  358.                        [* result->hi = 0; /* iterate for ever by default */ *]@2
  359.                        [ INTEGER:val [* result->hi = val; *]@2 ]
  360.                        [* if (result->lo == 0) result->contains_null = 1;
  361.                           if (result->hi != 0 && (result->hi < result->lo))
  362.                             text_message(TEXT_ERROR_ECHO,"Iterator high count must be greater than low count");
  363.                        *]@2
  364.                        [* result->delimiter_promote = PROMOTE_DONT; *]@2
  365.                        (
  366.                        token:delimiter
  367.                        [* result->supplementary_token = rdp_find(delimiter, K_TOKEN, RDP_ANY); *]@2 |
  368.                        '#'
  369.                        )
  370.                        [
  371.                          '^_' [* result->delimiter_promote = PROMOTE_DONT; *]@2 |
  372.                          '^'  [* result->delimiter_promote = PROMOTE; *]@2 |
  373.                          '^^' [* result->delimiter_promote = PROMOTE_AND_COPY; *]@2 |
  374.                          '^^^' [* result->delimiter_promote = PROMOTE_ABOVE; *]@2
  375.                        ]
  376.                      ]
  377.  
  378.                      |
  379.  
  380.                      '{'prod:body'}'  (* Kleene closure *)
  381.                      [* result = rdp_find(text_insert_substring("rdp", rdp_primary_id, rdp_component++), K_LIST, RDP_ANY);
  382.                         result->promote = promote_op;
  383.                         result->list = body; result->contains_null = 1;
  384.                         result->call_count++;
  385.                         result->lo = 0;
  386.                         result->hi = 0;
  387.                      *]@2 |
  388.  
  389.                      '['prod:body']'  (* Optional *)
  390.                      [* result = rdp_find(text_insert_substring("rdp", rdp_primary_id, rdp_component++), K_LIST, RDP_ANY);
  391.                         result->promote = promote_op;
  392.                         result->list = body; result->contains_null = 1;
  393.                         result->call_count++;
  394.                         result->lo = 0;
  395.                         result->hi = 1;
  396.                      *]@2 |
  397.  
  398.                      '<'prod:body'>'  (* Positive closure *)
  399.                      [* result = rdp_find(text_insert_substring("rdp", rdp_primary_id, rdp_component++), K_LIST, RDP_ANY);
  400.                         result->promote = promote_op;
  401.                         result->list = body;
  402.                         result->call_count++;
  403.                         result->lo = 1;
  404.                         result->hi = 0;
  405.                      *]@2
  406.                      ).
  407.  
  408.  
  409. token:char*  ::= STRING_ESC('\'' '\\'):result .
  410. String:char* ::= STRING_ESC('"' '\\'):result  .
  411. code:char*   ::= COMMENT_VISIBLE('[*' '*]'):result  .
  412. comment      ::= COMMENT('(*' '*)').
  413.  
  414. (* End of rdp.bnf *)
  415.  
  416.