📄 c-parse.y
字号:
{ $$ = parser_build_binary_op ($2, $1, $3); } | expr_no_commas '|' expr_no_commas { $$ = parser_build_binary_op ($2, $1, $3); } | expr_no_commas '^' expr_no_commas { $$ = parser_build_binary_op ($2, $1, $3); } | expr_no_commas ANDAND expr_no_commas { $$ = parser_build_binary_op (TRUTH_ANDIF_EXPR, $1, $3); } | expr_no_commas OROR expr_no_commas { $$ = parser_build_binary_op (TRUTH_ORIF_EXPR, $1, $3); } | expr_no_commas '?' xexpr ':' expr_no_commas { $$ = build_conditional_expr ($1, $3, $5); } | expr_no_commas '=' expr_no_commas { $$ = build_modify_expr ($1, NOP_EXPR, $3); } | expr_no_commas ASSIGN expr_no_commas { $$ = build_modify_expr ($1, $2, $3); } ;primary: IDENTIFIER { tree context; $$ = lastiddecl; if (!$$ || $$ == error_mark_node) { if (yychar == YYEMPTY) yychar = YYLEX; if (yychar == '(') { $$ = implicitly_declare ($1); assemble_external ($$); TREE_USED ($$) = 1; } else if (current_function_decl == 0) { error ("`%s' undeclared, outside of functions", IDENTIFIER_POINTER ($1)); $$ = error_mark_node; } else { if (IDENTIFIER_GLOBAL_VALUE ($1) != error_mark_node || IDENTIFIER_ERROR_LOCUS ($1) != current_function_decl) { error ("`%s' undeclared (first use this function)", IDENTIFIER_POINTER ($1)); if (! undeclared_variable_notice) { error ("(Each undeclared identifier is reported only once"); error ("for each function it appears in.)"); undeclared_variable_notice = 1; } } $$ = error_mark_node; /* Prevent repeated error messages. */ IDENTIFIER_GLOBAL_VALUE ($1) = error_mark_node; IDENTIFIER_ERROR_LOCUS ($1) = current_function_decl; } } else if (TREE_TYPE ($$) == error_mark_node) $$ = error_mark_node; else if (! TREE_USED ($$)) { if (TREE_EXTERNAL ($$)) assemble_external ($$); TREE_USED ($$) = 1; } if (TREE_CODE ($$) == CONST_DECL) $$ = DECL_INITIAL ($$); } | CONSTANT | string { $$ = combine_strings ($1); } | '(' expr ')' { char class = TREE_CODE_CLASS (TREE_CODE ($2)); if (class == 'e' || class == '1' || class == '2' || class == '<') C_SET_EXP_ORIGINAL_CODE ($2, ERROR_MARK); $$ = $2; } | '(' error ')' { $$ = error_mark_node; } | '(' { if (current_function_decl == 0) { error ("braced-group within expression allowed only inside a function"); YYERROR; } /* We must force a BLOCK for this level so that, if it is not expanded later, there is a way to turn off the entire subtree of blocks that are contained in it. */ keep_next_level (); push_label_level (); $<ttype>$ = expand_start_stmt_expr (); } compstmt ')' { tree rtl_exp; if (pedantic) pedwarn ("ANSI C forbids braced-groups within expressions"); pop_label_level (); rtl_exp = expand_end_stmt_expr ($<ttype>2); /* The statements have side effects, so the group does. */ TREE_SIDE_EFFECTS (rtl_exp) = 1; /* Make a BIND_EXPR for the BLOCK already made. */ $$ = build (BIND_EXPR, TREE_TYPE (rtl_exp), NULL_TREE, rtl_exp, $3); } | primary '(' exprlist ')' %prec '.' { $$ = build_function_call ($1, $3); } | primary '[' expr ']' %prec '.' { $$ = build_array_ref ($1, $3); } | primary '.' identifier { $$ = build_component_ref ($1, $3); } | primary POINTSAT identifier { $$ = build_component_ref (build_indirect_ref ($1, "->"), $3); } | primary PLUSPLUS { $$ = build_unary_op (POSTINCREMENT_EXPR, $1, 0); } | primary MINUSMINUS { $$ = build_unary_op (POSTDECREMENT_EXPR, $1, 0); } ;/* Produces a STRING_CST with perhaps more STRING_CSTs chained onto it. */string: STRING | string STRING { $$ = chainon ($1, $2); } ;xdecls: /* empty */ | datadecls | datadecls ELLIPSIS /* ... is used here to indicate a varargs function. */ { c_mark_varargs (); if (pedantic) pedwarn ("ANSI C does not permit use of `varargs.h'"); } ;/* The following are analogous to lineno_decl, decls and decl except that they do not allow nested functions. They are used for old-style parm decls. */lineno_datadecl: save_filename save_lineno datadecl { } ;datadecls: lineno_datadecl | errstmt | datadecls lineno_datadecl | lineno_datadecl errstmt ;datadecl: typed_declspecs setspecs initdecls ';' { current_declspecs = TREE_VALUE (declspec_stack); declspec_stack = TREE_CHAIN (declspec_stack); resume_momentary ($2); } | declmods setspecs notype_initdecls ';' { current_declspecs = TREE_VALUE (declspec_stack); declspec_stack = TREE_CHAIN (declspec_stack); resume_momentary ($2); } | typed_declspecs ';' { shadow_tag ($1); } | declmods ';' { pedwarn ("empty declaration"); } ;/* This combination which saves a lineno before a decl is the normal thing to use, rather than decl itself. This is to avoid shift/reduce conflicts in contexts where statement labels are allowed. */lineno_decl: save_filename save_lineno decl { } ;decls: lineno_decl | errstmt | decls lineno_decl | lineno_decl errstmt ;/* records the type and storage class specs to use for processing the declarators that follow. Maintains a stack of outer-level values of current_declspecs, for the sake of parm declarations nested in function declarators. */setspecs: /* empty */ { $$ = suspend_momentary (); pending_xref_error (); declspec_stack = tree_cons (0, current_declspecs, declspec_stack); current_declspecs = $<ttype>0; } ;decl: typed_declspecs setspecs initdecls ';' { current_declspecs = TREE_VALUE (declspec_stack); declspec_stack = TREE_CHAIN (declspec_stack); resume_momentary ($2); } | declmods setspecs notype_initdecls ';' { current_declspecs = TREE_VALUE (declspec_stack); declspec_stack = TREE_CHAIN (declspec_stack); resume_momentary ($2); } | typed_declspecs setspecs nested_function { current_declspecs = TREE_VALUE (declspec_stack); declspec_stack = TREE_CHAIN (declspec_stack); resume_momentary ($2); } | declmods setspecs notype_nested_function { current_declspecs = TREE_VALUE (declspec_stack); declspec_stack = TREE_CHAIN (declspec_stack); resume_momentary ($2); } | typed_declspecs ';' { shadow_tag ($1); } | declmods ';' { pedwarn ("empty declaration"); } ;/* Declspecs which contain at least one type specifier or typedef name. (Just `const' or `volatile' is not enough.) A typedef'd name following these is taken as a name to be declared. */typed_declspecs: typespec reserved_declspecs { $$ = tree_cons (NULL_TREE, $1, $2); } | declmods typespec reserved_declspecs { $$ = chainon ($3, tree_cons (NULL_TREE, $2, $1)); } ;reserved_declspecs: /* empty */ { $$ = NULL_TREE; } | reserved_declspecs typespecqual_reserved { $$ = tree_cons (NULL_TREE, $2, $1); } | reserved_declspecs SCSPEC { $$ = tree_cons (NULL_TREE, $2, $1); } ;/* List of just storage classes and type modifiers. A declaration can start with just this, but then it cannot be used to redeclare a typedef-name. */declmods: TYPE_QUAL { $$ = tree_cons (NULL_TREE, $1, NULL_TREE); } | SCSPEC { $$ = tree_cons (NULL_TREE, $1, NULL_TREE); } | declmods TYPE_QUAL { $$ = tree_cons (NULL_TREE, $2, $1); } | declmods SCSPEC { $$ = tree_cons (NULL_TREE, $2, $1); } ;/* Used instead of declspecs where storage classes are not allowed (that is, for typenames and structure components). Don't accept a typedef-name if anything but a modifier precedes it. */typed_typespecs: typespec reserved_typespecquals { $$ = tree_cons (NULL_TREE, $1, $2); } | nonempty_type_quals typespec reserved_typespecquals { $$ = chainon ($3, tree_cons (NULL_TREE, $2, $1)); } ;reserved_typespecquals: /* empty */ { $$ = NULL_TREE; } | reserved_typespecquals typespecqual_reserved { $$ = tree_cons (NULL_TREE, $2, $1); } ;/* A typespec (but not a type qualifier). Once we have seen one of these in a declaration, if a typedef name appears then it is being redeclared. */typespec: TYPESPEC | structsp | TYPENAME { /* For a typedef name, record the meaning, not the name. In case of `foo foo, bar;'. */ $$ = lookup_name ($1); } | TYPEOF '(' expr ')' { $$ = TREE_TYPE ($3); if (pedantic) pedwarn ("ANSI C forbids `typeof'"); } | TYPEOF '(' typename ')' { $$ = groktypename ($3); if (pedantic) pedwarn ("ANSI C forbids `typeof'"); } ;/* A typespec that is a reserved word, or a type qualifier. */typespecqual_reserved: TYPESPEC | TYPE_QUAL | structsp ;initdecls: initdcl | initdecls ',' initdcl ;notype_initdecls: notype_initdcl | notype_initdecls ',' initdcl ;maybeasm: /* empty */ { $$ = NULL_TREE; } | ASM '(' string ')' { if (TREE_CHAIN ($3)) $3 = combine_strings ($3); $$ = $3; } ;initdcl: declarator maybeasm maybe_attribute '=' { $<ttype>$ = start_decl ($1, current_declspecs, 1); } init/* Note how the declaration of the variable is in effect while its init is parsed! */ { decl_attributes ($<ttype>5, $3); finish_decl ($<ttype>5, $6, $2); } | declarator maybeasm maybe_attribute { tree d = start_decl ($1, current_declspecs, 0); decl_attributes (d, $3); finish_decl (d, NULL_TREE, $2); } ;notype_initdcl: notype_declarator maybeasm maybe_attribute '=' { $<ttype>$ = start_decl ($1, current_declspecs, 1); } init/* Note how the declaration of the variable is in effect while its init is parsed! */ { decl_attributes ($<ttype>5, $3); finish_decl ($<ttype>5, $6, $2); } | notype_declarator maybeasm maybe_attribute { tree d = start_decl ($1, current_declspecs, 0); decl_attributes (d, $3); finish_decl (d, NULL_TREE, $2); } ;/* the * rules are dummies to accept the Apollo extended syntax so that the header files compile. */maybe_attribute: /* empty */ { $$ = NULL_TREE; } | ATTRIBUTE '(' '(' attribute_list ')' ')' { $$ = $4; } ;attribute_list : attrib { $$ = tree_cons (NULL_TREE, $1, NULL_TREE); } | attribute_list ',' attrib { $$ = tree_cons (NULL_TREE, $3, $1); } ;attrib : IDENTIFIER { if (strcmp (IDENTIFIER_POINTER ($1), "packed")) warning ("`%s' attribute directive ignored", IDENTIFIER_POINTER ($1)); $$ = $1; } | IDENTIFIER '(' CONSTANT ')' { /* if not "aligned(n)", then issue warning */ if (strcmp (IDENTIFIER_POINTER ($1), "aligned") != 0 || TREE_CODE ($3) != INTEGER_CST) { warning ("`%s' attribute directive ignored", IDENTIFIER_POINTER ($1)); $$ = $1; } else $$ = tree_cons ($1, $3); } | IDENTIFIER '(' IDENTIFIER ',' CONSTANT ',' CONSTANT ')' { /* if not "format(...)", then issue warning */ if (strcmp (IDENTIFIER_POINTER ($1), "format") != 0 || TREE_CODE ($5) != INTEGER_CST || TREE_CODE ($7) != INTEGER_CST) { warning ("`%s' attribute directive ignored", IDENTIFIER_POINTER ($1)); $$ = $1; } else $$ = tree_cons ($1, tree_cons ($3, tree_cons ($5, $7))); } ;init: expr_no_commas | '{' '}' { $$ = build_nt (CONSTRUCTOR, NULL_TREE, NULL_TREE); if (pedantic) pedwarn ("ANSI C forbids empty initializer braces"); } | '{' initlist '}' { $$ = build_nt (CONSTRUCTOR, NULL_TREE, nreverse ($2)); } | '{' initlist ',' '}' { $$ = build_nt (CONSTRUCTOR, NULL_TREE, nreverse ($2)); } | error { $$ = NULL_TREE; } ;/* This chain is built in reverse order, and put in forward order where initlist is used. */initlist: init { $$ = build_tree_list (NULL_TREE, $1); } | initlist ',' init { $$ = tree_cons (NULL_TREE, $3, $1); } /* These are for labeled elements. */ | '[' expr_no_commas ']' init { $$ = build_tree_list ($2, $4); } | initlist ',' '[' expr_no_commas ']' init
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -