?? c-parse.y
字號:
{ pedwarn ("empty declaration"); } | extension decl { pedantic = $<itype>1; } ;/* 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. Declspecs have a non-NULL TREE_VALUE, attributes do not. */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 { if (extra_warnings) warning ("`%s' is not at beginning of declaration", IDENTIFIER_POINTER ($2)); $$ = tree_cons (NULL_TREE, $2, $1); } | reserved_declspecs attributes { $$ = tree_cons ($2, NULL_TREE, $1); } ;typed_declspecs_no_prefix_attr: typespec reserved_declspecs_no_prefix_attr { $$ = tree_cons (NULL_TREE, $1, $2); } | declmods_no_prefix_attr typespec reserved_declspecs_no_prefix_attr { $$ = chainon ($3, tree_cons (NULL_TREE, $2, $1)); } ;reserved_declspecs_no_prefix_attr: /* empty */ { $$ = NULL_TREE; } | reserved_declspecs_no_prefix_attr typespecqual_reserved { $$ = tree_cons (NULL_TREE, $2, $1); } | reserved_declspecs_no_prefix_attr SCSPEC { if (extra_warnings) warning ("`%s' is not at beginning of declaration", IDENTIFIER_POINTER ($2)); $$ = tree_cons (NULL_TREE, $2, $1); } ;/* List of just storage classes, type modifiers, and prefix attributes. A declaration can start with just this, but then it cannot be used to redeclare a typedef-name. Declspecs have a non-NULL TREE_VALUE, attributes do not. */declmods: declmods_no_prefix_attr { $$ = $1; } | attributes { $$ = tree_cons ($1, NULL_TREE, NULL_TREE); } | declmods declmods_no_prefix_attr { $$ = chainon ($2, $1); } | declmods attributes { $$ = tree_cons ($2, NULL_TREE, $1); } ;declmods_no_prefix_attr: TYPE_QUAL { $$ = tree_cons (NULL_TREE, $1, NULL_TREE); TREE_STATIC ($$) = 1; } | SCSPEC { $$ = tree_cons (NULL_TREE, $1, NULL_TREE); } | declmods_no_prefix_attr TYPE_QUAL { $$ = tree_cons (NULL_TREE, $2, $1); TREE_STATIC ($$) = 1; } | declmods_no_prefix_attr SCSPEC { if (extra_warnings && TREE_STATIC ($1)) warning ("`%s' is not at beginning of declaration", IDENTIFIER_POINTER ($2)); $$ = tree_cons (NULL_TREE, $2, $1); TREE_STATIC ($$) = TREE_STATIC ($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); } | TYPEOF '(' typename ')' { $$ = groktypename ($3); } ;/* 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_KEYWORD '(' string ')' { if (TREE_CHAIN ($3)) $3 = combine_strings ($3); $$ = $3; } ;initdcl: declarator maybeasm maybe_attribute '=' { $<ttype>$ = start_decl ($1, current_declspecs, 1, $3, prefix_attributes); start_init ($<ttype>$, $2, global_bindings_p ()); } init/* Note how the declaration of the variable is in effect while its init is parsed! */ { finish_init (); finish_decl ($<ttype>5, $6, $2); } | declarator maybeasm maybe_attribute { tree d = start_decl ($1, current_declspecs, 0, $3, prefix_attributes); finish_decl (d, NULL_TREE, $2); } ;notype_initdcl: notype_declarator maybeasm maybe_attribute '=' { $<ttype>$ = start_decl ($1, current_declspecs, 1, $3, prefix_attributes); start_init ($<ttype>$, $2, global_bindings_p ()); } init/* Note how the declaration of the variable is in effect while its init is parsed! */ { finish_init (); decl_attributes ($<ttype>5, $3, prefix_attributes); finish_decl ($<ttype>5, $6, $2); } | notype_declarator maybeasm maybe_attribute { tree d = start_decl ($1, current_declspecs, 0, $3, prefix_attributes); 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; } | attributes { $$ = $1; } ; attributes: attribute { $$ = $1; } | attributes attribute { $$ = chainon ($1, $2); } ;attribute: ATTRIBUTE '(' '(' attribute_list ')' ')' { $$ = $4; } ;attribute_list: attrib { $$ = $1; } | attribute_list ',' attrib { $$ = chainon ($1, $3); } ; attrib: /* empty */ { $$ = NULL_TREE; } | any_word { $$ = build_tree_list ($1, NULL_TREE); } | any_word '(' IDENTIFIER ')' { $$ = build_tree_list ($1, build_tree_list (NULL_TREE, $3)); } | any_word '(' IDENTIFIER ',' nonnull_exprlist ')' { $$ = build_tree_list ($1, tree_cons (NULL_TREE, $3, $5)); } | any_word '(' exprlist ')' { $$ = build_tree_list ($1, $3); } ;/* This still leaves out most reserved keywords, shouldn't we include them? */any_word: identifier | SCSPEC | TYPESPEC | TYPE_QUAL ;/* Initializers. `init' is the entry point. */init: expr_no_commas | '{' { really_start_incremental_init (NULL_TREE); /* Note that the call to clear_momentary is in process_init_element. */ push_momentary (); } initlist_maybe_comma '}' { $$ = pop_init_level (0); if ($$ == error_mark_node && ! (yychar == STRING || yychar == CONSTANT)) pop_momentary (); else pop_momentary_nofree (); } | error { $$ = error_mark_node; } ;/* `initlist_maybe_comma' is the guts of an initializer in braces. */initlist_maybe_comma: /* empty */ { if (pedantic) pedwarn ("ANSI C forbids empty initializer braces"); } | initlist1 maybecomma ;initlist1: initelt | initlist1 ',' initelt ;/* `initelt' is a single element of an initializer. It may use braces. */initelt: expr_no_commas { process_init_element ($1); } | '{' { push_init_level (0); } initlist_maybe_comma '}' { process_init_element (pop_init_level (0)); } | error /* These are for labeled elements. The syntax for an array element initializer conflicts with the syntax for an Objective-C message, so don't include these productions in the Objective-C grammar. */ | '[' expr_no_commas ELLIPSIS expr_no_commas ']' '=' { set_init_index ($2, $4); } initelt | '[' expr_no_commas ']' '=' { set_init_index ($2, NULL_TREE); } initelt | '[' expr_no_commas ']' { set_init_index ($2, NULL_TREE); } initelt | identifier ':' { set_init_label ($1); } initelt | '.' identifier '=' { set_init_label ($2); } initelt ;nested_function: declarator { push_c_function_context (); if (! start_function (current_declspecs, $1, prefix_attributes, NULL_TREE, 1)) { pop_c_function_context (); YYERROR1; } reinit_parse_for_function (); } old_style_parm_decls { store_parm_decls (); }/* This used to use compstmt_or_error. That caused a bug with input `f(g) int g {}', where the use of YYERROR1 above caused an error which then was handled by compstmt_or_error. There followed a repeated execution of that same rule, which called YYERROR1 again, and so on. */ compstmt { finish_function (1); pop_c_function_context (); } ;notype_nested_function: notype_declarator { push_c_function_context (); if (! start_function (current_declspecs, $1, prefix_attributes, NULL_TREE, 1)) { pop_c_function_context (); YYERROR1; } reinit_parse_for_function (); } old_style_parm_decls { store_parm_decls (); }/* This used to use compstmt_or_error. That caused a bug with input `f(g) int g {}', where the use of YYERROR1 above caused an error which then was handled by compstmt_or_error. There followed a repeated execution of that same rule, which called YYERROR1 again, and so on. */ compstmt { finish_function (1); pop_c_function_context (); } ;/* Any kind of declarator (thus, all declarators allowed after an explicit typespec). */declarator: after_type_declarator | notype_declarator ;/* A declarator that is allowed only after an explicit typespec. */after_type_declarator: '(' after_type_declarator ')' { $$ = $2; } | after_type_declarator '(' parmlist_or_identifiers %prec '.' { $$ = build_nt (CALL_EXPR, $1, $3, NULL_TREE); }/* | after_type_declarator '(' error ')' %prec '.' { $$ = build_nt (CALL_EXPR, $1, NULL_TREE, NULL_TREE); poplevel (0, 0, 0); } */ | after_type_declarator '[' expr ']' %prec '.' { $$ = build_nt (ARRAY_REF, $1, $3); } | after_type_declarator '[' ']' %prec '.' { $$ = build_nt (ARRAY_REF, $1, NULL_TREE); } | '*' type_quals after_type_declarator %prec UNARY { $$ = make_pointer_declarator ($2, $3); } /* ??? Yuck. setattrs is a quick hack. We can't use prefix_attributes because $1 only applies to this declarator. We assume setspecs has already been done. setattrs also avoids 5 reduce/reduce conflicts (otherwise multiple attributes could be recognized here or in `attributes'). */ | attributes setattrs after_type_declarator { $$ = $3; } | TYPENAME ;/* Kinds of declarator that can appear in a parameter list in addition to notype_declarator. This is like after_type_declarator but does not allow a typedef name in parentheses as an identifier (because it would conflict with a function with that typedef as arg). */parm_declarator: parm_declarator '(' parmlist_or_identifiers %prec '.' { $$ = build_nt (CALL_EXPR, $1, $3, NULL_TREE); }/* | parm_declarator '(' error ')' %prec '.' { $$ = build_nt (CALL_EXPR, $1, NULL_TREE, NULL_TREE); poplevel (0, 0, 0); } */ | parm_declarator '[' expr ']' %prec '.' { $$ = build_nt (ARRAY_REF, $1, $3); } | parm_declarator '[' ']' %prec '.' { $$ = build_nt (ARRAY_REF, $1, NULL_TREE); } | '*' type_quals parm_declarator %prec UNARY { $$ = make_pointer_declarator ($2, $3); } /* ??? Yuck. setattrs is a quick hack. We can't use prefix_attributes because $1 only applies to this declarator. We assume setspecs has already been done. setattrs also avoids 5 reduce/reduce conflicts (otherwise multiple attributes could be recognized here or in `attributes'). */ | attributes setattrs parm_declarator { $$ = $3; } | TYPENAME ;/* A declarator allowed whether or not there has been an explicit typespec. These cannot redeclare a typedef-name. */notype_declarator: notype_declarator '(' parmlist_or_identifiers %prec '.' { $$ = build_nt (CALL_EXPR, $1, $3, NULL_TREE); }/* | notype_declarator '(' error ')' %prec '.' { $$ = build_nt (CALL_EXPR, $1, NULL_TREE, NULL_TREE); poplevel (0, 0, 0); } */ | '(' notype_declarator ')' { $$ = $2; } | '*' type_quals notype_declarator %prec UNARY { $$ = make_pointer_declarator ($2, $3); } | notype_declarator '[' expr ']' %prec '.' { $$ = build_nt (ARRAY_REF, $1, $3); } | notype_declarator '[' ']' %prec '.' { $$ = build_nt (ARRAY_REF, $1, NULL_TREE); } /* ??? Yuck. setattrs is a quick hack. We can't use prefix_attributes because $1 only applies to this declarator. We assume setspecs has already been done. setattrs also avoids 5 reduce/reduce conflicts (otherwise multiple attributes could be recognized here or in `attributes'). */ | attributes setattrs notype_declarator { $$ = $3; } | IDENTIFIER ;structsp: STRUCT identifier '{' { $$ = start_struct (RECORD_TYPE, $2); /* Start scope of tag before parsing components. */ } component_decl_list '}' maybe_attribute
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -