home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume29 / cproto / part01 / grammar.y < prev    next >
Encoding:
Text File  |  1992-04-06  |  13.8 KB  |  696 lines

  1. /* $Id: grammar.y 3.4 92/04/04 13:58:58 cthuang Exp $
  2.  *
  3.  * yacc grammar for C function prototype generator
  4.  * This was derived from the grammar in Appendix A of
  5.  * "The C Programming Language" by Kernighan and Ritchie.
  6.  */
  7.  
  8. %token
  9.     /* identifiers that are not reserved words */
  10.     T_IDENTIFIER T_TYPEDEF_NAME
  11.  
  12.     /* storage class */
  13.     T_AUTO T_EXTERN T_REGISTER T_STATIC T_TYPEDEF
  14.     /* This keyword included for compatibility with C++. */
  15.     T_INLINE
  16.  
  17.     /* type specifiers */
  18.     T_CHAR T_DOUBLE T_FLOAT T_INT T_VOID
  19.     T_LONG T_SHORT T_SIGNED T_UNSIGNED
  20.     T_ENUM T_STRUCT T_UNION
  21.  
  22.     /* type qualifiers */
  23.     T_TYPE_QUALIFIER
  24.  
  25.     /* left brace */
  26.     T_LBRACE
  27.     /* all input to the matching right brace */
  28.     T_MATCHRBRACE
  29.  
  30.     /* paired square brackets and everything between them: [ ... ] */
  31.     T_BRACKETS
  32.  
  33.     /* three periods */
  34.     T_ELLIPSIS
  35.  
  36.     /* constant expression or paired braces following an equal sign */
  37.     T_INITIALIZER
  38.  
  39.     /* string literal */
  40.     T_STRING_LITERAL
  41.  
  42.     /* asm */
  43.     T_ASM
  44.     /* ( "string literal" ) following asm keyword */
  45.     T_ASMARG
  46.  
  47. %type <decl_spec> decl_specifiers decl_specifier
  48. %type <decl_spec> storage_class type_specifier type_qualifier
  49. %type <decl_spec> struct_or_union_specifier enum_specifier
  50. %type <decl_list> init_declarator_list
  51. %type <declarator> init_declarator declarator direct_declarator
  52. %type <declarator> abs_declarator direct_abs_declarator
  53. %type <param_list> parameter_type_list parameter_list
  54. %type <parameter> parameter_declaration
  55. %type <param_list> opt_identifier_list identifier_list
  56. %type <text>
  57.     struct_or_union pointer opt_type_qualifiers type_qualifier_list any_id
  58.     T_BRACKETS
  59.     T_IDENTIFIER T_TYPEDEF_NAME
  60.     T_AUTO T_EXTERN T_REGISTER T_STATIC T_TYPEDEF T_INLINE
  61.     T_CHAR T_DOUBLE T_FLOAT T_INT T_VOID T_LONG T_SHORT T_SIGNED T_UNSIGNED
  62.     T_ENUM T_STRUCT T_UNION
  63.     T_TYPE_QUALIFIER
  64.     '(' '*'
  65.  
  66. %{
  67. #include <stdio.h>
  68. #include "cproto.h"
  69. #include "symbol.h"
  70. #include "semantic.h"
  71.  
  72. #define YYMAXDEPTH 150
  73.  
  74. /* Declaration specifier attributes for the typedef statement currently being
  75.  * scanned.
  76.  */
  77. static int cur_decl_spec_flags;
  78.  
  79. /* Pointer to parameter list for the current function definition. */
  80. static ParameterList *func_params;
  81.  
  82. /* Pointer to current declarator in function parameter declaration. */
  83. static Declarator *cur_declarator;
  84.  
  85. /* temporary string buffer */
  86. static char buf[MAX_TEXT_SIZE];
  87.  
  88. /* Table of typedef names */
  89. static SymbolTable *typedef_names;
  90.  
  91. /* Table of type qualifiers */
  92. static SymbolTable *type_qualifiers;
  93. %}
  94. %%
  95.  
  96. program
  97.     : /* empty */
  98.     | translation_unit
  99.     ;
  100.  
  101. translation_unit
  102.     : external_declaration
  103.     | translation_unit external_declaration
  104.     ;
  105.  
  106. external_declaration
  107.     : declaration
  108.     | function_definition
  109.     | function_definition ';'
  110.     | linkage_specification
  111.     | T_ASM T_ASMARG ';'
  112.     | error ';'
  113.     | error braces
  114.     ;
  115.  
  116. braces
  117.     : T_LBRACE T_MATCHRBRACE
  118.     ;
  119.  
  120. linkage_specification
  121.     : T_EXTERN T_STRING_LITERAL braces
  122.     | T_EXTERN T_STRING_LITERAL declaration
  123.     ;
  124.  
  125. declaration
  126.     : decl_specifiers ';'
  127.     {
  128.         free_decl_spec(&$1);
  129.     }
  130.     | decl_specifiers init_declarator_list ';'
  131.     {
  132.         check_untagged(&$1);
  133.         if (func_params != NULL) {
  134.         set_param_types(func_params, &$1, &$2);
  135.         } else {
  136.         gen_declarations(&$1, &$2);
  137.         free_decl_list(&$2);
  138.         }
  139.         free_decl_spec(&$1);
  140.     }
  141.     | T_TYPEDEF decl_specifiers
  142.     {
  143.         cur_decl_spec_flags = $2.flags;
  144.         free_decl_spec(&$2);
  145.     }
  146.       opt_declarator_list ';'
  147.     ;
  148.  
  149. opt_declarator_list
  150.     : /* empty */
  151.     | declarator_list
  152.     ;
  153.  
  154. declarator_list
  155.     : declarator
  156.     {
  157.         new_symbol(typedef_names, $1->name, cur_decl_spec_flags);
  158.         free_declarator($1);
  159.     }
  160.     | declarator_list ',' declarator
  161.     {
  162.         new_symbol(typedef_names, $3->name, cur_decl_spec_flags);
  163.         free_declarator($3);
  164.     }
  165.     ;
  166.  
  167. function_definition
  168.     : decl_specifiers declarator
  169.     {
  170.         check_untagged(&$1);
  171.         if ($2->func_def == FUNC_NONE) {
  172.         yyerror("syntax error");
  173.         YYERROR;
  174.         }
  175.         func_params = &($2->head->params);
  176.         func_params->begin_comment = cur_file->begin_comment;
  177.         func_params->end_comment = cur_file->end_comment;
  178.     }
  179.       opt_declaration_list T_LBRACE
  180.     {
  181.         func_params = NULL;
  182.  
  183.         if (cur_file->convert)
  184.         gen_func_definition(&$1, $2);
  185.         gen_prototype(&$1, $2);
  186.         free_decl_spec(&$1);
  187.         free_declarator($2);
  188.     }
  189.       T_MATCHRBRACE
  190.     | declarator
  191.     {
  192.         if ($1->func_def == FUNC_NONE) {
  193.         yyerror("syntax error");
  194.         YYERROR;
  195.         }
  196.         func_params = &($1->head->params);
  197.         func_params->begin_comment = cur_file->begin_comment;
  198.         func_params->end_comment = cur_file->end_comment;
  199.     }
  200.       opt_declaration_list T_LBRACE
  201.     {
  202.         DeclSpec decl_spec;
  203.  
  204.         func_params = NULL;
  205.  
  206.         new_decl_spec(&decl_spec, "int", $1->begin, DS_EXTERN);
  207.         if (cur_file->convert)
  208.         gen_func_definition(&decl_spec, $1);
  209.         gen_prototype(&decl_spec, $1);
  210.         free_decl_spec(&decl_spec);
  211.         free_declarator($1);
  212.     }
  213.       T_MATCHRBRACE
  214.     ;
  215.  
  216. opt_declaration_list
  217.     : /* empty */
  218.     | declaration_list
  219.     ;
  220.  
  221. declaration_list
  222.     : declaration
  223.     | declaration_list declaration
  224.     ;
  225.  
  226. decl_specifiers
  227.     : decl_specifier
  228.     | decl_specifiers decl_specifier
  229.     {
  230.         join_decl_specs(&$$, &$1, &$2);
  231.         free($1.text);
  232.         free($2.text);
  233.     }
  234.     ;
  235.  
  236. decl_specifier
  237.     : storage_class
  238.     | type_specifier
  239.     | type_qualifier
  240.     ;
  241.  
  242. storage_class
  243.     : T_AUTO
  244.     {
  245.         new_decl_spec(&$$, $1.text, $1.begin, DS_EXTERN);
  246.     }
  247.     | T_EXTERN
  248.     {
  249.         new_decl_spec(&$$, $1.text, $1.begin, DS_JUNK);
  250.     }
  251.     | T_REGISTER
  252.     {
  253.         new_decl_spec(&$$, $1.text, $1.begin, DS_EXTERN);
  254.     }
  255.     | T_STATIC
  256.     {
  257.         new_decl_spec(&$$, $1.text, $1.begin, DS_STATIC);
  258.     }
  259.     | T_INLINE
  260.     {
  261.         new_decl_spec(&$$, $1.text, $1.begin, DS_JUNK);
  262.     }
  263.     ;
  264.  
  265. type_specifier
  266.     : T_CHAR
  267.     {
  268.         new_decl_spec(&$$, $1.text, $1.begin, DS_EXTERN | DS_CHAR);
  269.     }
  270.     | T_DOUBLE
  271.     {
  272.         new_decl_spec(&$$, $1.text, $1.begin, DS_EXTERN);
  273.     }
  274.     | T_FLOAT
  275.     {
  276.         new_decl_spec(&$$, $1.text, $1.begin, DS_EXTERN | DS_FLOAT);
  277.     }
  278.     | T_INT
  279.     {
  280.         new_decl_spec(&$$, $1.text, $1.begin, DS_EXTERN);
  281.     }
  282.     | T_LONG
  283.     {
  284.         new_decl_spec(&$$, $1.text, $1.begin, DS_EXTERN);
  285.     }
  286.     | T_SHORT
  287.     {
  288.         new_decl_spec(&$$, $1.text, $1.begin, DS_EXTERN | DS_SHORT);
  289.     }
  290.     | T_SIGNED
  291.     {
  292.         new_decl_spec(&$$, $1.text, $1.begin, DS_EXTERN);
  293.     }
  294.     | T_UNSIGNED
  295.     {
  296.         new_decl_spec(&$$, $1.text, $1.begin, DS_EXTERN);
  297.     }
  298.     | T_VOID
  299.     {
  300.         new_decl_spec(&$$, $1.text, $1.begin, DS_EXTERN);
  301.     }
  302.     | struct_or_union_specifier
  303.     | enum_specifier
  304.     ;
  305.  
  306. type_qualifier
  307.     : T_TYPE_QUALIFIER
  308.     {
  309.         new_decl_spec(&$$, $1.text, $1.begin, DS_EXTERN);
  310.     }
  311.     | T_TYPEDEF_NAME
  312.     {
  313.         /* A typedef name is actually a type specifier, but since the
  314.          * typedef symbol table also stores #define names, this production
  315.          * is here so the <pointer> nonterminal will scan #define names.
  316.          */
  317.         Symbol *s;
  318.         s = find_symbol(typedef_names, $1.text);
  319.         new_decl_spec(&$$, $1.text, $1.begin, s->flags);
  320.     }
  321.     ;
  322.  
  323. struct_or_union_specifier
  324.     : struct_or_union any_id braces
  325.     {
  326.         sprintf(buf, "%s %s", $1.text, $2.text);
  327.         new_decl_spec(&$$, buf, $1.begin, DS_EXTERN);
  328.     }
  329.     | struct_or_union braces
  330.     {
  331.         sprintf(buf, "%s {}", $1.text);
  332.         new_decl_spec(&$$, buf, $1.begin, DS_EXTERN);
  333.     }
  334.     | struct_or_union any_id
  335.     {
  336.         sprintf(buf, "%s %s", $1.text, $2.text);
  337.         new_decl_spec(&$$, buf, $1.begin, DS_EXTERN);
  338.     }
  339.     ;
  340.  
  341. struct_or_union
  342.     : T_STRUCT
  343.     | T_UNION
  344.     ;
  345.  
  346. init_declarator_list
  347.     : init_declarator
  348.     {
  349.         new_decl_list(&$$, $1);
  350.     }
  351.     | init_declarator_list ',' init_declarator
  352.     {
  353.         add_decl_list(&$$, &$1, $3);
  354.     }
  355.     ;
  356.  
  357. init_declarator
  358.     : declarator
  359.     {
  360.         if ($1->func_def != FUNC_NONE && func_params == NULL &&
  361.         func_style == FUNC_TRADITIONAL && cur_file->convert) {
  362.         gen_func_declarator($1);
  363.         fputs(yytext, cur_file->tmp_file);
  364.         }
  365.         cur_declarator = $$;
  366.     }
  367.     | declarator '='
  368.     {
  369.         if ($1->func_def != FUNC_NONE && func_params == NULL &&
  370.         func_style == FUNC_TRADITIONAL && cur_file->convert) {
  371.         gen_func_declarator($1);
  372.         fputs(" =", cur_file->tmp_file);
  373.         }
  374.     }
  375.       T_INITIALIZER
  376.     ;
  377.  
  378. enum_specifier
  379.     : T_ENUM any_id braces
  380.     {
  381.         sprintf(buf, "enum %s", $2.text);
  382.         new_decl_spec(&$$, buf, $1.begin, DS_EXTERN);
  383.     }
  384.     | T_ENUM braces
  385.     {
  386.         new_decl_spec(&$$, "enum {}", $1.begin, DS_EXTERN);
  387.     }
  388.     | T_ENUM any_id
  389.     {
  390.         sprintf(buf, "enum %s", $2.text);
  391.         new_decl_spec(&$$, buf, $1.begin, DS_EXTERN);
  392.     }
  393.     ;
  394.  
  395. any_id
  396.     : T_IDENTIFIER
  397.     | T_TYPEDEF_NAME
  398.     ;
  399.  
  400. declarator
  401.     : pointer direct_declarator
  402.     {
  403.         $$ = $2;
  404.         sprintf(buf, "%s%s", $1.text, $$->text);
  405.         free($$->text);
  406.         $$->text = xstrdup(buf);
  407.         $$->begin = $1.begin;
  408.     }
  409.     | direct_declarator
  410.     ;
  411.  
  412. direct_declarator
  413.     : T_IDENTIFIER
  414.     {
  415.         $$ = new_declarator($1.text, $1.text, $1.begin);
  416.     }
  417.     | '(' declarator ')'
  418.     {
  419.         $$ = $2;
  420.         sprintf(buf, "(%s)", $$->text);
  421.         free($$->text);
  422.         $$->text = xstrdup(buf);
  423.         $$->begin = $1.begin;
  424.     }
  425.     | direct_declarator T_BRACKETS
  426.     {
  427.         $$ = $1;
  428.         sprintf(buf, "%s%s", $$->text, $2.text);
  429.         free($$->text);
  430.         $$->text = xstrdup(buf);
  431.     }
  432.     | direct_declarator '(' parameter_type_list ')'
  433.     {
  434.         $$ = new_declarator("%s()", $1->name, $1->begin);
  435.         $$->params = $3;
  436.         $$->func_stack = $1;
  437.         $$->head = ($1->func_stack == NULL) ? $$ : $1->head;
  438.         $$->func_def = FUNC_ANSI;
  439.     }
  440.     | direct_declarator '(' opt_identifier_list ')'
  441.     {
  442.         $$ = new_declarator("%s()", $1->name, $1->begin);
  443.         $$->params = $3;
  444.         $$->func_stack = $1;
  445.         $$->head = ($1->func_stack == NULL) ? $$ : $1->head;
  446.         $$->func_def = FUNC_TRADITIONAL;
  447.     }
  448.     ;
  449.  
  450. pointer
  451.     : '*' opt_type_qualifiers
  452.     {
  453.         sprintf($$.text, "*%s", $2.text);
  454.         $$.begin = $1.begin;
  455.     }
  456.     | '*' opt_type_qualifiers pointer
  457.     {
  458.         sprintf($$.text, "*%s%s", $2.text, $3.text);
  459.         $$.begin = $1.begin;
  460.     }
  461.     ;
  462.  
  463. opt_type_qualifiers
  464.     : /* empty */
  465.     {
  466.         strcpy($$.text, "");
  467.         $$.begin = 0L;
  468.     }
  469.     | type_qualifier_list
  470.     ;
  471.  
  472. type_qualifier_list
  473.     : type_qualifier
  474.     {
  475.         strcpy($$.text, $1.text);
  476.         $$.begin = $1.begin;
  477.         free($1.text);
  478.     }
  479.     | type_qualifier_list type_qualifier
  480.     {
  481.         sprintf($$.text, "%s %s ", $1.text, $2.text);
  482.         $$.begin = $1.begin;
  483.         free($2.text);
  484.     }
  485.     ;
  486.  
  487. parameter_type_list
  488.     : parameter_list
  489.     | parameter_list ',' T_ELLIPSIS
  490.     {
  491.         add_ident_list(&$$, &$1, "...");
  492.     }
  493.     ;
  494.  
  495. parameter_list
  496.     : parameter_declaration
  497.     {
  498.         new_param_list(&$$, &$1);
  499.     }
  500.     | parameter_list ',' parameter_declaration
  501.     {
  502.         add_param_list(&$$, &$1, &$3);
  503.     }
  504.     ;
  505.  
  506. parameter_declaration
  507.     : decl_specifiers declarator
  508.     {
  509.         check_untagged(&$1);
  510.         new_parameter(&$$, &$1, $2);
  511.     }
  512.     | decl_specifiers abs_declarator
  513.     {
  514.         check_untagged(&$1);
  515.         new_parameter(&$$, &$1, $2);
  516.     }
  517.     | decl_specifiers
  518.     {
  519.         check_untagged(&$1);
  520.         new_parameter(&$$, &$1, NULL);
  521.     }
  522.     ;
  523.  
  524. opt_identifier_list
  525.     : /* empty */
  526.     {
  527.         new_ident_list(&$$);
  528.     }
  529.     | identifier_list
  530.     ;
  531.  
  532. identifier_list
  533.     : T_IDENTIFIER
  534.     {
  535.         new_ident_list(&$$);
  536.         add_ident_list(&$$, &$$, $1.text);
  537.     }
  538.     | identifier_list ',' T_IDENTIFIER
  539.     {
  540.         add_ident_list(&$$, &$1, $3.text);
  541.     }
  542.     ;
  543.  
  544. abs_declarator
  545.     : pointer
  546.     {
  547.         $$ = new_declarator($1.text, "", $1.begin);
  548.     }
  549.     | pointer direct_abs_declarator
  550.     {
  551.         $$ = $2;
  552.         sprintf(buf, "%s%s", $1.text, $$->text);
  553.         free($$->text);
  554.         $$->text = xstrdup(buf);
  555.         $$->begin = $1.begin;
  556.     }
  557.     | direct_abs_declarator
  558.     ;
  559.  
  560. direct_abs_declarator
  561.     : '(' abs_declarator ')'
  562.     {
  563.         $$ = $2;
  564.         sprintf(buf, "(%s)", $$->text);
  565.         free($$->text);
  566.         $$->text = xstrdup(buf);
  567.         $$->begin = $1.begin;
  568.     }
  569.     | direct_abs_declarator T_BRACKETS
  570.     {
  571.         $$ = $1;
  572.         sprintf(buf, "%s%s", $$->text, $2.text);
  573.         free($$->text);
  574.         $$->text = xstrdup(buf);
  575.     }
  576.     | T_BRACKETS
  577.     {
  578.         $$ = new_declarator($1.text, "", $1.begin);
  579.     }
  580.     | direct_abs_declarator '(' parameter_type_list ')'
  581.     {
  582.         $$ = new_declarator("%s()", "", $1->begin);
  583.         $$->params = $3;
  584.         $$->func_stack = $1;
  585.         $$->head = ($1->func_stack == NULL) ? $$ : $1->head;
  586.         $$->func_def = FUNC_ANSI;
  587.     }
  588.     | direct_abs_declarator '(' ')'
  589.     {
  590.         $$ = new_declarator("%s()", "", $1->begin);
  591.         $$->func_stack = $1;
  592.         $$->head = ($1->func_stack == NULL) ? $$ : $1->head;
  593.         $$->func_def = FUNC_ANSI;
  594.     }
  595.     | '(' parameter_type_list ')'
  596.     {
  597.         Declarator *d;
  598.         
  599.         d = new_declarator("", "", $1.begin);
  600.         $$ = new_declarator("%s()", "", $1.begin);
  601.         $$->params = $2;
  602.         $$->func_stack = d;
  603.         $$->head = $$;
  604.         $$->func_def = FUNC_ANSI;
  605.     }
  606.     | '(' ')'
  607.     {
  608.         Declarator *d;
  609.         
  610.         d = new_declarator("", "", $1.begin);
  611.         $$ = new_declarator("%s()", "", $1.begin);
  612.         $$->func_stack = d;
  613.         $$->head = $$;
  614.         $$->func_def = FUNC_ANSI;
  615.     }
  616.     ;
  617.  
  618. %%
  619. #ifdef MSDOS
  620. #include "lex_yy.c"
  621. #else
  622. #include "lex.yy.c"
  623. #endif
  624.  
  625. void
  626. yyerror (msg)
  627. char *msg;
  628. {
  629.     func_params = NULL;
  630.     put_error();
  631.     fprintf(stderr, "%s\n", msg);
  632. }
  633.  
  634. /* Initialize the table of type qualifier keywords recognized by the lexical
  635.  * analyzer.
  636.  */
  637. void
  638. init_parser ()
  639. {
  640.     static char *keywords[] = {
  641.     "const", "volatile",
  642. #ifdef MSDOS
  643.     "_cdecl", "_export", "_far", "_fastcall", "_fortran", "_huge",
  644.     "_interrupt", "_loadds", "_near", "_pascal", "_saveregs", "_segment",
  645.     "_cs", "_ds", "_es", "_ss", "_seg",
  646.     "cdecl", "far", "huge", "interrupt", "near", "pascal",
  647. #endif
  648.     };
  649.     int i;
  650.  
  651.     /* Initialize type qualifier table. */
  652.     type_qualifiers = new_symbol_table();
  653.     for (i = 0; i < sizeof(keywords)/sizeof(keywords[0]); ++i) {
  654.     new_symbol(type_qualifiers, keywords[i], DS_EXTERN);
  655.     }
  656. }
  657.  
  658. /* Process the C source file.  Write function prototypes to the standard
  659.  * output.  Convert function definitions and write the converted source
  660.  * code to a temporary file.
  661.  */
  662. void
  663. process_file (infile, name)
  664. FILE *infile;
  665. char *name;
  666. {
  667.     char *s;
  668.  
  669.     if (strlen(name) > 2) {
  670.     s = name + strlen(name) - 2;
  671.     if (*s == '.') {
  672.         ++s;
  673.         if (*s == 'l' || *s == 'y')
  674.         BEGIN LEXYACC;
  675. #ifdef MSDOS
  676.         if (*s == 'L' || *s == 'Y')
  677.         BEGIN LEXYACC;
  678. #endif
  679.     }
  680.     }
  681.  
  682.     included_files = new_symbol_table();
  683.     typedef_names = new_symbol_table();
  684.     inc_depth = -1;
  685.     curly = 0;
  686.     ly_count = 0;
  687.     func_params = NULL;
  688.     yyin = infile;
  689.     include_file(name, func_style != FUNC_NONE);
  690.     if (proto_comments)
  691.     printf("/* %s */\n", cur_file_name());
  692.     yyparse();
  693.     free_symbol_table(typedef_names);
  694.     free_symbol_table(included_files);
  695. }
  696.