home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume28 / cproto / part01 / grammar.y < prev    next >
Text File  |  1992-03-15  |  14KB  |  692 lines

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