📄 cyacc.y
字号:
{ c_finish_if_stmt ($3, $5, $7, $9, false); add_stmt (c_end_compound_stmt ($2, flag_isoc99)); } | IF c99_block_start save_location '(' condition ')' if_statement_1 %prec IF { c_finish_if_stmt ($3, $5, $7, NULL, true); add_stmt (c_end_compound_stmt ($2, flag_isoc99)); } | IF c99_block_start save_location '(' condition ')' if_statement_2 %prec IF { c_finish_if_stmt ($3, $5, $7, NULL, false); add_stmt (c_end_compound_stmt ($2, flag_isoc99)); } ;start_break: /* empty */ { $$ = c_break_label; c_break_label = NULL; } ;start_continue: /* empty */ { $$ = c_cont_label; c_cont_label = NULL; } ;while_statement: WHILE c99_block_start save_location '(' condition ')' start_break start_continue c99_block_lineno_labeled_stmt { c_finish_loop ($3, $5, NULL, $9, c_break_label, c_cont_label, true); add_stmt (c_end_compound_stmt ($2, flag_isoc99)); c_break_label = $7; c_cont_label = $8; } ;do_statement: DO c99_block_start save_location start_break start_continue c99_block_lineno_labeled_stmt WHILE { $<ttype>$ = c_break_label; c_break_label = $4; } { $<ttype>$ = c_cont_label; c_cont_label = $5; } '(' condition ')' ';' { c_finish_loop ($3, $11, NULL, $6, $<ttype>8, $<ttype>9, false); add_stmt (c_end_compound_stmt ($2, flag_isoc99)); } ;xexpr: /* empty */ { $$ = NULL_TREE; } | expr { $$ = $1.value; } ;for_init_stmt: xexpr ';' { c_finish_expr_stmt ($1); } | decl { check_for_loop_decls (); } ;for_cond_expr: save_location xexpr { if ($2) { $$ = lang_hooks.truthvalue_conversion ($2); if (EXPR_P ($$)) SET_EXPR_LOCATION ($$, $1); } else $$ = NULL; } ;for_incr_expr: xexpr { $$ = c_process_expr_stmt ($1); } ;for_statement: FOR c99_block_start '(' for_init_stmt save_location for_cond_expr ';' for_incr_expr ')' start_break start_continue c99_block_lineno_labeled_stmt { c_finish_loop ($5, $6, $8, $12, c_break_label, c_cont_label, true); add_stmt (c_end_compound_stmt ($2, flag_isoc99)); c_break_label = $10; c_cont_label = $11; } ;switch_statement: SWITCH c99_block_start '(' expr ')' { $<ttype>$ = c_start_case ($4.value); } start_break c99_block_lineno_labeled_stmt { c_finish_case ($8); if (c_break_label) add_stmt (build (LABEL_EXPR, void_type_node, c_break_label)); c_break_label = $7; add_stmt (c_end_compound_stmt ($2, flag_isoc99)); } ;/* Parse a single real statement, not including any labels or compounds. */stmt_nocomp: expr ';' { $$ = c_finish_expr_stmt ($1.value); } | if_statement { $$ = NULL_TREE; } | while_statement { $$ = NULL_TREE; } | do_statement { $$ = NULL_TREE; } | for_statement { $$ = NULL_TREE; } | switch_statement { $$ = NULL_TREE; } | BREAK ';' { $$ = c_finish_bc_stmt (&c_break_label, true); } | CONTINUE ';' { $$ = c_finish_bc_stmt (&c_cont_label, false); } | RETURN ';' { $$ = c_finish_return (NULL_TREE); } | RETURN expr ';' { $$ = c_finish_return ($2.value); } | asm_stmt | GOTO identifier ';' { $$ = c_finish_goto_label ($2); } | GOTO '*' expr ';' { $$ = c_finish_goto_ptr ($3.value); } | ';' { $$ = NULL_TREE; } ;/* Parse a single or compound real statement, not including any labels. */stmt: compstmt { add_stmt ($1); $$ = NULL_TREE; } | stmt_nocomp ;/* Any kind of label, including jump labels and case labels. ANSI C accepts labels only before statements, but we allow them also at the end of a compound statement. */label: CASE expr_no_commas ':' { $$ = do_case ($2.value, NULL_TREE); } | CASE expr_no_commas ELLIPSIS expr_no_commas ':' { $$ = do_case ($2.value, $4.value); } | DEFAULT ':' { $$ = do_case (NULL_TREE, NULL_TREE); } | identifier save_location ':' maybe_attribute { tree label = define_label ($2, $1); if (label) { decl_attributes (&label, $4, 0); $$ = add_stmt (build_stmt (LABEL_EXPR, label)); } else $$ = NULL_TREE; } ;/* Asm expressions and statements *//* simple_asm_expr is used in restricted contexts, where a full expression with inputs and outputs does not make sense. */simple_asm_expr: ASM_KEYWORD stop_string_translation '(' asm_string ')' start_string_translation { $$ = $4; } ;/* maybeasm: used for assembly names for declarations */maybeasm: /* empty */ { $$ = NULL_TREE; } | simple_asm_expr ;/* asmdef: asm() outside a function body. */asmdef: simple_asm_expr ';' { assemble_asm ($1); } | ASM_KEYWORD error start_string_translation ';' {} ;/* Full-blown asm statement with inputs, outputs, clobbers, and volatile tag allowed. */asm_stmt: ASM_KEYWORD maybe_volatile stop_string_translation '(' asm_argument ')' start_string_translation ';' { $$ = build_asm_stmt ($2, $5); } ;asm_argument: /* no operands */ asm_string { $$ = build_asm_expr ($1, 0, 0, 0, true); } /* output operands */ | asm_string ':' asm_operands { $$ = build_asm_expr ($1, $3, 0, 0, false); } /* output and input operands */ | asm_string ':' asm_operands ':' asm_operands { $$ = build_asm_expr ($1, $3, $5, 0, false); } /* output and input operands and clobbers */ | asm_string ':' asm_operands ':' asm_operands ':' asm_clobbers { $$ = build_asm_expr ($1, $3, $5, $7, false); } ;/* Either 'volatile' or nothing. First thing in an `asm' statement. */maybe_volatile: /* empty */ { $$ = 0; } | TYPE_QUAL { if ($1 != ridpointers[RID_VOLATILE]) { warning ("%E qualifier ignored on asm", $1); $$ = 0; } else $$ = $1; } ;/* These are the operands other than the first string and colon in asm ("addextend %2,%1": "=dm" (x), "0" (y), "g" (*x)) */asm_operands: /* empty */ { $$ = NULL_TREE; } | nonnull_asm_operands ;nonnull_asm_operands: asm_operand | nonnull_asm_operands ',' asm_operand { $$ = chainon ($1, $3); } ;asm_operand: asm_string start_string_translation '(' expr ')' stop_string_translation { $$ = build_tree_list (build_tree_list (NULL_TREE, $1), $4.value); } | '[' identifier ']' asm_string start_string_translation '(' expr ')' stop_string_translation { $2 = build_string (IDENTIFIER_LENGTH ($2), IDENTIFIER_POINTER ($2)); $$ = build_tree_list (build_tree_list ($2, $4), $7.value); } ;asm_clobbers: asm_string { $$ = tree_cons (NULL_TREE, $1, NULL_TREE); } | asm_clobbers ',' asm_string { $$ = tree_cons (NULL_TREE, $3, $1); } ;/* Strings in 'asm' must be narrow strings. */asm_string: STRING { if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE ($1))) != char_type_node) { error ("wide string literal in %<asm%>"); $$ = build_string (1, ""); } else $$ = $1; } ;stop_string_translation: { c_lex_string_translate = 0; } ;start_string_translation: { c_lex_string_translate = 1; } ;/* This is what appears inside the parens in a function declarator. Its value is a list of ..._TYPE nodes. Attributes must appear here to avoid a conflict with their appearance after an open parenthesis in an abstract declarator, as in "void bar (int (__attribute__((__mode__(SI))) int foo));". */parmlist: maybe_attribute { push_scope (); declare_parm_level (); } parmlist_1 { $$ = $3; pop_scope (); } ;parmlist_1: parmlist_2 ')' | parms ';' { mark_forward_parm_decls (); } maybe_attribute { /* Dummy action so attributes are in known place on parser stack. */ } parmlist_1 { $$ = $6; } | error ')' { $$ = XOBNEW (&parser_obstack, struct c_arg_info); $$->parms = 0; $$->tags = 0; $$->types = 0; $$->others = 0; } ;/* This is what appears inside the parens in a function declarator. Its value is represented in the format that grokdeclarator expects. */parmlist_2: /* empty */ { $$ = XOBNEW (&parser_obstack, struct c_arg_info); $$->parms = 0; $$->tags = 0; $$->types = 0; $$->others = 0; } | ELLIPSIS { $$ = XOBNEW (&parser_obstack, struct c_arg_info); $$->parms = 0; $$->tags = 0; $$->others = 0; /* Suppress -Wold-style-definition for this case. */ $$->types = error_mark_node; error ("ISO C requires a named argument before %<...%>"); } | parms { $$ = get_parm_info (/*ellipsis=*/false); } | parms ',' ELLIPSIS { $$ = get_parm_info (/*ellipsis=*/true); } ;parms: firstparm { push_parm_decl ($1); } | parms ',' parm { push_parm_decl ($3); } ;/* A single parameter declaration or parameter type name, as found in a parmlist. */parm: declspecs_ts setspecs parm_declarator maybe_attribute { $$ = build_c_parm (current_declspecs, chainon ($4, all_prefix_attributes), $3); POP_DECLSPEC_STACK; } | declspecs_ts setspecs notype_declarator maybe_attribute { $$ = build_c_parm (current_declspecs, chainon ($4, all_prefix_attributes), $3); POP_DECLSPEC_STACK; } | declspecs_ts setspecs absdcl_maybe_attribute { $$ = $3; POP_DECLSPEC_STACK; } | declspecs_nots setspecs notype_declarator maybe_attribute { $$ = build_c_parm (current_declspecs, chainon ($4, all_prefix_attributes), $3); POP_DECLSPEC_STACK; } | declspecs_nots setspecs absdcl_maybe_attribute { $$ = $3; POP_DECLSPEC_STACK; } ;/* The first parm, which must suck attributes from off the top of the parser stack. */firstparm: declspecs_ts_nosa setspecs_fp parm_declarator maybe_attribute { $$ = build_c_parm (current_declspecs, chainon ($4, all_prefix_attributes), $3); POP_DECLSPEC_STACK; } | declspecs_ts_nosa setspecs_fp notype_declarator maybe_attribute { $$ = build_c_parm (current_declspecs, chainon ($4, all_prefix_attributes), $3); POP_DECLSPEC_STACK; } | declspecs_ts_nosa setspecs_fp absdcl_maybe_attribute { $$ = $3; POP_DECLSPEC_STACK; } | declspecs_nots_nosa setspecs_fp notype_declarator maybe_attribute { $$ = build_c_parm (current_declspecs, chainon ($4, all_prefix_attributes), $3); POP_DECLSPEC_STACK; } | declspecs_nots_nosa setspecs_fp absdcl_maybe_attribute { $$ = $3; POP_DECLSPEC_STACK; } ;setspecs_fp: setspecs { prefix_attributes = chainon (prefix_attributes, $<ttype>-2); all_prefix_attributes = prefix_attributes; } ;/* This is used in a function definition where either a parmlist or an identifier list is ok. Its value is a list of ..._TYPE nodes or a list of identifiers. */parmlist_or_identifiers: maybe_attribute { push_scope (); declare_parm_level (); } parmlist_or_identifiers_1 { $$ = $3; pop_scope (); } ;parmlist_or_identifiers_1: parmlist_1 | identifiers ')' { $$ = XOBNEW (&parser_obstack, struct c_arg_info); $$->parms = 0; $$->tags = 0; $$->types = $1; $$->others = 0; /* Make sure we have a parmlist after attributes. */ if ($<ttype>-1 != 0) YYERROR1; } ;/* A nonempty list of identifiers. */identifiers: IDENTIFIER { $$ = build_tree_list (NULL_TREE, $1); } | identifiers ',' IDENTIFIER { $$ = chainon ($1, build_tree_list (NULL_TREE, $3)); } ;/* A nonempty list of identifiers, including typenames. */identifiers_or_typenames: identifier { $$ = build_tree_list (NULL_TREE, $1); } | identifiers_or_typenames ',' identifier { $$ = chainon ($1, build_tree_list (NULL_TREE, $3)); } ;extension: EXTENSION { $$ = SAVE_EXT_FLAGS (); pedantic = 0; warn_pointer_arith = 0; warn_traditional = 0; flag_iso = 0; } ;%%/* yylex() is a thin wrapper around c_lex(), all it does is translate cpplib.h's token codes into yacc's token codes. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -