📄 gram_old.y
字号:
/***** uno: gram.y *****/%{ /* ====================================================================== CTREE Version 0.09 Written by Shaun Flisakowski (1995) With small revisions for use in UNO by Gerard Holzmann, Bell Labs, Lucent Technologies (2000-2001) ====================================================================== This program is provided free of charge on an "as is" basis without warranty of any kind, either express or implied. Acceptance and use of this program constitutes the user's understanding that (s)he will have no recourse for any actual or consequential damages, including, but not limited to, lost profits or savings, arising out of the use of or inability to use this program. ====================================================================== this grammar is based on "C - A Reference Manual" (4th Ed.), by Samuel P Harbison, and Guy L Steele Jr. */#define alloca emalloc#define YYERROR_VERBOSE#include <stdio.h>#include <errno.h>#include <setjmp.h>#include "lexer.h"#include "tree.h"#include "symtab.h"#include "token.h"#include "globals.h"#define YYDEBUG 1static int debug = 0;#if 0int yydebug = 1;#endifint structfieldflag;extern int errno, err_cnt, Verbose;extern char *progname;extern int yylex(YYSTYPE *lvalp);extern void name_scope(context_t *, char *, int);static void insert_decl (leafnode *, treenode *, treenode *);static void insert_typedef (leafnode *, treenode *, treenode *);static void insert_component(leafnode *, treenode *, treenode *);extern void add_constant(char *);static void add_params_to_symtab(treenode *);void *emalloc(uint);%}/* The next line makes the parser re-entrant. */%pure_parser%start program%token <leaf> IDENT STRING FIELD_NAME TYPEDEF_NAME TAG%token <leaf> CHAR_CONST%token <leaf> INUM%token <leaf> RNUM%token <leaf> COMMENT%token <leaf> PP_LINE PP_INCLUDE PP_DEFINE PP_UNDEF PP_ERROR%token <leaf> PP_IF PP_IFDEF PP_IFNDEF PP_ELSE PP_ELIF PP_ENDIF%token <leaf> PP_IDENT PP_PRAGMA%token <tok> INVALID/* reserved words */%token <node> AUTO BREAK CASE CHAR CONST CONT DEFLT DO DOUBLE ELSE ENUM EXTRN%token <ifn> IF%token <forn> FOR%token <node> FLOAT GOTO INT LONG REGISTR RETURN SHORT SGNED%token <node> STATIC STRUCT SWITCH TYPEDEF UNION UNSGNED VOID VOLATILE WHILE%token <node> PLUS_EQ MINUS_EQ STAR_EQ DIV_EQ MOD_EQ%token <node> B_NOT_EQ B_AND_EQ B_OR_EQ B_XOR_EQ%token <node> L_SHIFT_EQ R_SHIFT_EQ%token <node> EQUAL LESS_EQ GRTR_EQ NOT_EQ %token <node> RPAREN RBRCKT LBRACE RBRACE%token <node> SEMICOLON COMMA ELLIPSIS %token <node> LB_SIGN DOUB_LB_SIGN%token <node> BACKQUOTE AT DOLLAR%token <node> CPP_INCLUDE CPP_DEFINE CPP_LINE/* precedence rules to solve dangling else s/r conflict */%nonassoc IF%nonassoc ELSE/* operator tokens and their precedences. */%left COMMA_OP%right <node> EQ ASSIGN%right <node> QUESTMARK COLON COMMA_SEP%left <node> OR%left <node> AND%left <node> B_OR%left <node> B_XOR%left <node> B_AND%left <node> COMP_EQ%left <node> COMP_ARITH LESS GRTR%left <node> L_SHIFT R_SHIFT%left <node> PLUS MINUS%left <node> STAR DIV MOD%right CAST%right <node> UNARY NOT B_NOT SIZEOF ALIGNOF INCR DECR %left HYPERUNARY%left <node> ARROW DOT LPAREN LBRCKT%type <node> declaration decl_specs opt_decl_specs%type <node> storage_class type_spec type_qual%type <node> opt_init_decl_list init_decl_list init_decl%type <node> declarator opt_declarator%type <node> direct_declarator opt_comma%type <node> pointer pointer_start%type <node> simple_decl type_qual_list opt_type_qual_list%type <node> decl_list opt_decl_list%type <leaf> constant strings%type <node> comp_decl_specs opt_comp_decl_specs%type <node> param_list param_decl%type <node> opt_param_type_list param_type_list%type <node> ident_list%type <leaf> ident%type <node> field_ident%type <node> abs_decl%type <node> direct_abs_decl%type <node> array_decl opt_const_expr const_expr expr%type <node> comma_expr assign_expr%type <node> prim_expr paren_expr postfix_expr%type <node> subscript_expr comp_select_expr postinc_expr postdec_expr%type <node> func_call opt_expr opt_expr_list expr_list%type <node> top_level_decl func_def func_spec cmpnd_stemnt%type <node> stemnt_list opt_stemnt_list stemnt%type <node> expr_stemnt labeled_stemnt cond_stemnt%type <node> opt_comment%type <node> iter_stemnt switch_stemnt break_stemnt continue_stemnt%type <node> return_stemnt goto_stemnt null_stemnt%type <node> do_stemnt while_stemnt for_stemnt%type <node> cond_expr if_stemnt if_else_stemnt%type <node> log_or_expr log_and_expr log_neg_expr%type <node> bitwise_or_expr bitwise_and_expr bitwise_neg_expr%type <node> bitwise_xor_expr cast_expr equality_expr%type <node> relational_expr shift_expr additive_expr mult_expr%type <node> unary_expr unary_minus_expr unary_plus_expr%type <node> sizeof_expr alignof_expr addr_expr indirection_expr%type <node> preinc_expr predec_expr %type <node> direct_comp_select indirect_comp_select%type <node> add_op mult_op equality_op relation_op shift_op assign_op%type <node> label named_label case_label deflt_label%type <node> type_name typedef_name typename_as_ident%type <node> enum_type_spec struct_type_spec union_type_spec%type <node> tag opt_tag%type <node> opt_trailing_comma%type <node> enum_type_define enum_type_ref enum_def_list%type <node> enum_const_def enum_constant%type <node> struct_type_define struct_type_ref field_list%type <node> union_type_define union_type_ref%type <node> comp_decl comp_decl_list comp_declarator%type <node> simple_comp bit_field width%type <node> initializer_list initializer%type <node> program trans_unit%%program: /* empty */ { if (err_cnt == 0) fputs("Empty source file\n", stderr); Parse_TOS->parse_tree= (treenode *) NULL; $$ = (treenode *) NULL; } | trans_unit { if (err_cnt) fprintf(stderr,"%d errors\n",err_cnt); Parse_TOS->parse_tree = $$; } | error { fputs("Aborting\n",stderr); Parse_TOS->parse_tree= (treenode *) NULL; YYABORT; }trans_unit: top_level_decl | trans_unit top_level_decl { if ($2) { treenode *tmp_node = make_node(TN_TRANS_LIST); tmp_node->lnode = $1; tmp_node->rnode = $2; $$ = tmp_node; } else $$ = $1; } ;top_level_decl: declaration { exit_scopes(ParseStack->contxt, FILE_SCOPE); } | func_def { exit_scopes(ParseStack->contxt, FILE_SCOPE); } | SEMICOLON /* gjh *//* | error SEMICOLON { free_tree($2); $$ = (treenode *) NULL; }*/ | error RBRACE { free_tree($2); $$ = (treenode *) NULL; }func_def: func_spec cmpnd_stemnt { leafnode *lm, *rm = (leafnode *) 0; for_node *tmpnode = (for_node *) $1; symentry_t *nmtbl; int scoped = EXTERN_SCOPE; tmpnode->stemnt = $2; if (ParseStack->contxt) { rm = find_func_name($$); if (rm) /* if null, an error msg was printed */ { lm = leftmost($$); if (lm && (lm->hdr.tok == STATIC)) scoped = FILE_SCOPE; nmtbl = mk_funcdef(rm->data.sval, $$); nmtbl = symtab_insert_at(ParseStack->contxt->syms, nmtbl, scoped); rm->syment = nmtbl; /* can replace prototype entry for real one */ rm->syment->nes = ParseStack->contxt->syms->current; rm->syment->decl_level = ParseStack->contxt->syms->clevel; if (!nmtbl) yyerr("Duplicate function"); name_scope(ParseStack->contxt, rm->data.sval->str, /* fct name */ TN_FUNC_DEF); } } exit_scope(ParseStack->contxt); }func_spec: decl_specs declarator opt_decl_list { for_node *tmp_node = make_for(TN_FUNC_DEF); tmp_node->init = $1; tmp_node->test = $2; tmp_node->incr = $3; add_params_to_symtab($2); $$ = (treenode *) tmp_node; } | declarator opt_decl_list { /* return type defaults to int */ for_node *tmp_node = make_for(TN_FUNC_DEF); tmp_node->init = (treenode *) NULL; tmp_node->test = $1; tmp_node->incr = $2; add_params_to_symtab($1); $$ = (treenode *) tmp_node; }opt_decl_list: /* Nothing */ { $$ = (treenode *) NULL; } | decl_list ;decl_list: declaration | decl_list declaration { treenode *tmp_node = make_node(TN_DECL_LIST); tmp_node->lnode = $1; tmp_node->rnode = $2; $$ = tmp_node; }cmpnd_stemnt: LBRACE { enter_scope(ParseStack->contxt); } opt_decl_list opt_stemnt_list RBRACE { $1->hdr.type = TN_BLOCK; $1->lnode = $3; $1->rnode = $4; free_tree($5); exit_scope(ParseStack->contxt); } | error RBRACE { $$ = (treenode *) NULL; free_tree($2); }opt_stemnt_list: /* Nothing */ { $$ = (treenode *) NULL; } | stemnt_list ;stemnt_list: stemnt { treenode *tmp_node = make_node(TN_STEMNT_LIST); tmp_node->lnode = $1; tmp_node->rnode = NULL; $$ = tmp_node; } | stemnt_list stemnt { treenode *tmp_node = make_node(TN_STEMNT_LIST); tmp_node->lnode = $1; tmp_node->rnode = $2; $$ = tmp_node; }stemnt: expr_stemnt { treenode *tmp_node = make_node(TN_STEMNT); tmp_node->rnode = $1; $$ = tmp_node; } | labeled_stemnt { treenode *tmp_node = make_node(TN_STEMNT); tmp_node->rnode = $1; $$ = tmp_node; } | cmpnd_stemnt { treenode *tmp_node = make_node(TN_STEMNT); tmp_node->rnode = $1; $$ = tmp_node; } | cond_stemnt { treenode *tmp_node = make_node(TN_STEMNT); tmp_node->rnode = $1; $$ = tmp_node; } | iter_stemnt { treenode *tmp_node = make_node(TN_STEMNT); tmp_node->rnode = $1; $$ = tmp_node; } | switch_stemnt { treenode *tmp_node = make_node(TN_STEMNT); tmp_node->rnode = $1; $$ = tmp_node; } | break_stemnt { treenode *tmp_node = make_node(TN_STEMNT); tmp_node->rnode = $1; $$ = tmp_node; } | continue_stemnt { treenode *tmp_node = make_node(TN_STEMNT); tmp_node->rnode = $1; $$ = tmp_node; } | return_stemnt { treenode *tmp_node = make_node(TN_STEMNT); tmp_node->rnode = $1; $$ = tmp_node; } | goto_stemnt { treenode *tmp_node = make_node(TN_STEMNT); tmp_node->rnode = $1; $$ = tmp_node; } | null_stemnt { treenode *tmp_node = make_node(TN_STEMNT); tmp_node->rnode = $1; $$ = tmp_node; } | error SEMICOLON { $$ = (treenode *) NULL; free_tree($2); }expr_stemnt: expr SEMICOLON opt_comment { free_tree($2); }labeled_stemnt: label COLON stemnt { $2->hdr.type = TN_LABEL; $2->lnode = (treenode *) $1; $2->rnode = $3; $$ = $2; } ;cond_stemnt: if_stemnt | if_else_stemnt ;iter_stemnt: do_stemnt | while_stemnt | for_stemnt ;switch_stemnt: SWITCH LPAREN expr RPAREN stemnt { $1->hdr.type = TN_SWITCH; $1->lnode = (treenode *) $3; $1->rnode = (treenode *) $5; free_tree($2); free_tree($4); }break_stemnt: BREAK SEMICOLON { $1->hdr.type = TN_JUMP; free_tree($2); }continue_stemnt: CONT SEMICOLON { $1->hdr.type = TN_JUMP; free_tree($2); }return_stemnt: RETURN opt_expr SEMICOLON { $1->hdr.type = TN_JUMP; $1->lnode = $2; free_tree($3); }goto_stemnt: GOTO ident SEMICOLON { if (ParseStack->contxt) { symentry_t *nmtbl, *y; nmtbl = mk_label($2->data.sval, $$); y = symtab_insert_at(ParseStack->contxt->labels, nmtbl, FUNCTION_SCOPE); if (!y) printf("not really a Duplicate label\n"); $2->syment = y; } if (0) printf("goto %s, $2=%s (%u)\n", $2->data.sval->str, name_of_node($2->hdr.type), $2->syment); $1->hdr.type = TN_JUMP; $1->lnode = (treenode *) $2; free_tree($3); }null_stemnt: SEMICOLON { $$ = (treenode *) NULL; free_tree($1); }if_stemnt: IF LPAREN expr RPAREN stemnt %prec IF { $1->hdr.type = TN_IF; $1->cond = $3; $1->then_n = $5; $$ = (treenode *) $1; free_tree($2); free_tree($4); }if_else_stemnt: IF LPAREN expr RPAREN stemnt ELSE stemnt { $1->hdr.type = TN_IF; $1->cond = $3; $1->then_n = $5; $1->else_n = $7; $$ = (treenode *) $1; free_tree($2); free_tree($4); free_tree($6); }do_stemnt: DO stemnt WHILE LPAREN expr RPAREN SEMICOLON { $1->hdr.type = TN_DOWHILE; $1->lnode = $5; $1->rnode = $2; free_tree($3); free_tree($4); free_tree($6); free_tree($7); }while_stemnt: WHILE LPAREN expr RPAREN stemnt { $1->hdr.type = TN_WHILE; $1->lnode = $3; $1->rnode = $5; free_tree($2); free_tree($4); }for_stemnt: FOR LPAREN opt_expr SEMICOLON opt_expr SEMICOLON opt_expr RPAREN stemnt { $1->hdr.type = TN_FOR; $1->init = $3; $1->test = $5; $1->incr = $7; $1->stemnt = $9; free_tree($2); free_tree($4); free_tree($6); free_tree($8); }label: named_label | case_label | deflt_label ;cond_expr: log_or_expr | log_or_expr QUESTMARK expr COLON cond_expr { if_node *tmpnode = make_if(TN_COND_EXPR); tmpnode->hdr.tok = QUESTMARK; tmpnode->cond = $1; tmpnode->then_n = $3; tmpnode->else_n = $5; $$ = (treenode *) tmpnode; free_tree($2); free_tree($4); }log_or_expr: log_and_expr | log_or_expr OR log_and_expr { $2->hdr.type = TN_EXPR; $2->lnode = $1; $2->rnode = $3; $$ = $2; }log_and_expr: bitwise_or_expr | log_and_expr AND bitwise_or_expr { $2->hdr.type = TN_EXPR; $2->lnode = $1; $2->rnode = $3; $$ = $2; }log_neg_expr: NOT cast_expr { $1->hdr.type = TN_EXPR; $1->rnode = $2; }bitwise_or_expr: bitwise_xor_expr | bitwise_or_expr B_OR bitwise_xor_expr
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -