📄 grammar.y
字号:
/* $Id: grammar.y,v 1.1 2004/03/24 21:29:23 tom Exp $ * * yacc grammar for C function prototype generator * This was derived from the grammar in Appendix A of * "The C Programming Language" by Kernighan and Ritchie. */%token <text> '(' '*' '&' /* identifiers that are not reserved words */ T_IDENTIFIER T_TYPEDEF_NAME T_DEFINE_NAME /* storage class */ T_AUTO T_EXTERN T_REGISTER T_STATIC T_TYPEDEF /* This keyword included for compatibility with C++. */ T_INLINE /* This keyword included for compatibility with GCC */ T_EXTENSION /* type specifiers */ T_CHAR T_DOUBLE T_FLOAT T_INT T_VOID T_LONG T_SHORT T_SIGNED T_UNSIGNED T_ENUM T_STRUCT T_UNION /* C9X new types */ T_Bool T_Complex T_Imaginary /* type qualifiers */ T_TYPE_QUALIFIER /* paired square brackets and everything between them: [ ... ] */ T_BRACKETS%token /* left brace */ T_LBRACE /* all input to the matching right brace */ T_MATCHRBRACE /* three periods */ T_ELLIPSIS /* constant expression or paired braces following an equal sign */ T_INITIALIZER /* string literal */ T_STRING_LITERAL /* asm */ T_ASM /* ( "string literal" ) following asm keyword */ T_ASMARG /* va_dcl from <varargs.h> */ T_VA_DCL%type <decl_spec> decl_specifiers decl_specifier%type <decl_spec> storage_class type_specifier type_qualifier%type <decl_spec> struct_or_union_specifier enum_specifier%type <decl_list> init_declarator_list%type <declarator> init_declarator declarator direct_declarator%type <declarator> abs_declarator direct_abs_declarator%type <param_list> parameter_type_list parameter_list%type <parameter> parameter_declaration%type <param_list> opt_identifier_list identifier_list%type <text> struct_or_union pointer opt_type_qualifiers type_qualifier_list any_id identifier_or_ref%type <text> enumeration%{#include <stdio.h>#include <ctype.h>#include "cproto.h"#include "symbol.h"#include "semantic.h"#define YYMAXDEPTH 150extern int yylex (void);/* declaration specifier attributes for the typedef statement currently being * scanned */static int cur_decl_spec_flags;/* pointer to parameter list for the current function definition */static ParameterList *func_params;/* A parser semantic action sets this pointer to the current declarator in * a function parameter declaration in order to catch any comments following * the parameter declaration on the same line. If the lexer scans a comment * and <cur_declarator> is not NULL, then the comment is attached to the * declarator. To ignore subsequent comments, the lexer sets this to NULL * after scanning a comment or end of line. */static Declarator *cur_declarator;/* temporary string buffer */static char buf[MAX_TEXT_SIZE];/* table of typedef names */static SymbolTable *typedef_names;/* table of define names */static SymbolTable *define_names;/* table of type qualifiers */static SymbolTable *type_qualifiers;/* information about the current input file */typedef struct { char *base_name; /* base input file name */ char *file_name; /* current file name */ FILE *file; /* input file */ unsigned line_num; /* current line number in input file */ FILE *tmp_file; /* temporary file */ long begin_comment; /* tmp file offset after last written ) or ; */ long end_comment; /* tmp file offset after last comment */ boolean convert; /* if TRUE, convert function definitions */ boolean changed; /* TRUE if conversion done in this file */} IncludeStack;static IncludeStack *cur_file; /* current input file */#include "yyerror.c"static int haveAnsiParam (void);/* Flags to enable us to find if a procedure returns a value. */static int return_val, /* nonzero on BRACES iff return-expression found */ returned_at; /* marker for token-number to set 'return_val' */#if OPT_LINTLIBRARYstatic char *dft_decl_spec (void);static char *dft_decl_spec (void){ return (lintLibrary() && !return_val) ? "void" : "int";}#else#define dft_decl_spec() "int"#endifstatic inthaveAnsiParam (void){ Parameter *p; if (func_params != 0) { for (p = func_params->first; p != 0; p = p->next) { if (p->declarator->func_def == FUNC_ANSI) { return TRUE; } } } return FALSE;}%}%%program : /* empty */ | translation_unit ;translation_unit : external_declaration | translation_unit external_declaration ;external_declaration : declaration | function_definition | ';' | linkage_specification | T_ASM T_ASMARG ';' | error T_MATCHRBRACE { yyerrok; } | error ';' { yyerrok; } ;braces : T_LBRACE T_MATCHRBRACE ;linkage_specification : T_EXTERN T_STRING_LITERAL braces { /* Provide an empty action here so bison will not complain about * incompatible types in the default action it normally would * have generated. */ } | T_EXTERN T_STRING_LITERAL declaration { /* empty */ } ;declaration : decl_specifiers ';' {#if OPT_LINTLIBRARY if (types_out && want_typedef()) { gen_declarations(&$1, (DeclaratorList *)0); flush_varargs(); }#endif free_decl_spec(&$1); end_typedef(); } | decl_specifiers init_declarator_list ';' { if (func_params != NULL) { set_param_types(func_params, &$1, &$2); } else { gen_declarations(&$1, &$2);#if OPT_LINTLIBRARY flush_varargs();#endif free_decl_list(&$2); } free_decl_spec(&$1); end_typedef(); } | any_typedef decl_specifiers { cur_decl_spec_flags = $2.flags; free_decl_spec(&$2); } opt_declarator_list ';' { end_typedef(); } ;any_typedef : T_EXTENSION T_TYPEDEF { begin_typedef(); } | T_TYPEDEF { begin_typedef(); } ;opt_declarator_list : /* empty */ | declarator_list ;declarator_list : declarator { int flags = cur_decl_spec_flags; /* If the typedef is a pointer type, then reset the short type * flags so it does not get promoted. */ if (strcmp($1->text, $1->name) != 0) flags &= ~(DS_CHAR | DS_SHORT | DS_FLOAT); new_symbol(typedef_names, $1->name, NULL, flags); free_declarator($1); } | declarator_list ',' declarator { int flags = cur_decl_spec_flags; if (strcmp($3->text, $3->name) != 0) flags &= ~(DS_CHAR | DS_SHORT | DS_FLOAT); new_symbol(typedef_names, $3->name, NULL, flags); free_declarator($3); } ;function_definition : decl_specifiers declarator { check_untagged(&$1); if ($2->func_def == FUNC_NONE) { yyerror("syntax error"); YYERROR; } func_params = &($2->head->params); func_params->begin_comment = cur_file->begin_comment; func_params->end_comment = cur_file->end_comment; } opt_declaration_list T_LBRACE { /* If we're converting to K&R and we've got a nominally K&R * function which has a parameter which is ANSI (i.e., a prototyped * function pointer), then we must override the deciphered value of * 'func_def' so that the parameter will be converted. */ if (func_style == FUNC_TRADITIONAL && haveAnsiParam() && $2->head->func_def == func_style) { $2->head->func_def = FUNC_BOTH; } func_params = NULL; if (cur_file->convert) gen_func_definition(&$1, $2); gen_prototype(&$1, $2);#if OPT_LINTLIBRARY flush_varargs();#endif free_decl_spec(&$1); free_declarator($2); } T_MATCHRBRACE | declarator { if ($1->func_def == FUNC_NONE) { yyerror("syntax error"); YYERROR; } func_params = &($1->head->params); func_params->begin_comment = cur_file->begin_comment; func_params->end_comment = cur_file->end_comment; } opt_declaration_list T_LBRACE T_MATCHRBRACE { DeclSpec decl_spec; func_params = NULL; new_decl_spec(&decl_spec, dft_decl_spec(), $1->begin, DS_NONE); if (cur_file->convert) gen_func_definition(&decl_spec, $1); gen_prototype(&decl_spec, $1);#if OPT_LINTLIBRARY flush_varargs();#endif free_decl_spec(&decl_spec); free_declarator($1); } ;opt_declaration_list : /* empty */ | T_VA_DCL | declaration_list ;declaration_list : declaration | declaration_list declaration ;decl_specifiers : decl_specifier | decl_specifiers decl_specifier { join_decl_specs(&$$, &$1, &$2); free($1.text); free($2.text); } ;decl_specifier : storage_class | type_specifier | type_qualifier ;storage_class : T_AUTO { new_decl_spec(&$$, $1.text, $1.begin, DS_NONE); } | T_EXTERN { new_decl_spec(&$$, $1.text, $1.begin, DS_EXTERN); } | T_REGISTER { new_decl_spec(&$$, $1.text, $1.begin, DS_NONE); } | T_STATIC { new_decl_spec(&$$, $1.text, $1.begin, DS_STATIC); } | T_INLINE { new_decl_spec(&$$, $1.text, $1.begin, DS_INLINE); } | T_EXTENSION { new_decl_spec(&$$, $1.text, $1.begin, DS_JUNK); } ;type_specifier : T_CHAR { new_decl_spec(&$$, $1.text, $1.begin, DS_CHAR); } | T_DOUBLE { new_decl_spec(&$$, $1.text, $1.begin, DS_NONE); } | T_FLOAT { new_decl_spec(&$$, $1.text, $1.begin, DS_FLOAT); } | T_INT { new_decl_spec(&$$, $1.text, $1.begin, DS_NONE); } | T_LONG { new_decl_spec(&$$, $1.text, $1.begin, DS_NONE); } | T_SHORT { new_decl_spec(&$$, $1.text, $1.begin, DS_SHORT); } | T_SIGNED { new_decl_spec(&$$, $1.text, $1.begin, DS_NONE); } | T_UNSIGNED { new_decl_spec(&$$, $1.text, $1.begin, DS_NONE); } | T_VOID { new_decl_spec(&$$, $1.text, $1.begin, DS_NONE); } | T_Bool { new_decl_spec(&$$, $1.text, $1.begin, DS_CHAR); } | T_Complex { new_decl_spec(&$$, $1.text, $1.begin, DS_NONE); } | T_Imaginary { new_decl_spec(&$$, $1.text, $1.begin, DS_NONE); } | T_TYPEDEF_NAME { Symbol *s; s = find_symbol(typedef_names, $1.text); if (s != NULL) new_decl_spec(&$$, $1.text, $1.begin, s->flags); } | struct_or_union_specifier | enum_specifier ;type_qualifier : T_TYPE_QUALIFIER { new_decl_spec(&$$, $1.text, $1.begin, DS_NONE); } | T_DEFINE_NAME { /* This rule allows the <pointer> nonterminal to scan #define * names as if they were type modifiers. */ Symbol *s; s = find_symbol(define_names, $1.text); if (s != NULL) new_decl_spec(&$$, $1.text, $1.begin, s->flags); } ;struct_or_union_specifier : struct_or_union any_id braces { char *s; if ((s = implied_typedef()) == 0) (void)sprintf(s = buf, "%s %s", $1.text, $2.text); new_decl_spec(&$$, s, $1.begin, DS_NONE); } | struct_or_union braces
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -