📄 parse.y
字号:
| notype_declarator %prec EMPTY ;/* This is necessary to postpone reduction of `int()()()()'. */fcast_or_absdcl: LEFT_RIGHT %prec EMPTY { $$ = make_call_declarator (NULL_TREE, empty_parms (), NULL_TREE, NULL_TREE); } | fcast_or_absdcl LEFT_RIGHT %prec EMPTY { $$ = make_call_declarator ($$, empty_parms (), NULL_TREE, NULL_TREE); } ;/* ANSI type-id (8.1) */type_id: typed_typespecs absdcl { $$.t = build_decl_list ($1.t, $2); $$.new_type_flag = $1.new_type_flag; } | nonempty_cv_qualifiers absdcl { $$.t = build_decl_list ($1.t, $2); $$.new_type_flag = $1.new_type_flag; } | typespec absdcl { $$.t = build_decl_list (get_decl_list ($1.t), $2); $$.new_type_flag = $1.new_type_flag; } | typed_typespecs %prec EMPTY { $$.t = build_decl_list ($1.t, NULL_TREE); $$.new_type_flag = $1.new_type_flag; } | nonempty_cv_qualifiers %prec EMPTY { $$.t = build_decl_list ($1.t, NULL_TREE); $$.new_type_flag = $1.new_type_flag; } ;/* 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. In the result, declspecs have a non-NULL TREE_VALUE, attributes do not. */typed_declspecs: typed_typespecs %prec EMPTY | typed_declspecs1 ;typed_declspecs1: declmods typespec { $$.t = decl_tree_cons (NULL_TREE, $2.t, $1); $$.new_type_flag = $2.new_type_flag; } | typespec reserved_declspecs %prec HYPERUNARY { $$.t = decl_tree_cons (NULL_TREE, $1.t, $2); $$.new_type_flag = $1.new_type_flag; } | typespec reserved_typespecquals reserved_declspecs { $$.t = decl_tree_cons (NULL_TREE, $1.t, chainon ($2, $3)); $$.new_type_flag = $1.new_type_flag; } | declmods typespec reserved_declspecs { $$.t = decl_tree_cons (NULL_TREE, $2.t, chainon ($3, $1)); $$.new_type_flag = $2.new_type_flag; } | declmods typespec reserved_typespecquals { $$.t = decl_tree_cons (NULL_TREE, $2.t, chainon ($3, $1)); $$.new_type_flag = $2.new_type_flag; } | declmods typespec reserved_typespecquals reserved_declspecs { $$.t = decl_tree_cons (NULL_TREE, $2.t, chainon ($3, chainon ($4, $1))); $$.new_type_flag = $2.new_type_flag; } ;reserved_declspecs: SCSPEC { if (extra_warnings) warning ("`%s' is not at beginning of declaration", IDENTIFIER_POINTER ($$)); $$ = build_decl_list (NULL_TREE, $$); } | reserved_declspecs typespecqual_reserved { $$ = decl_tree_cons (NULL_TREE, $2.t, $$); } | reserved_declspecs SCSPEC { if (extra_warnings) warning ("`%s' is not at beginning of declaration", IDENTIFIER_POINTER ($2)); $$ = decl_tree_cons (NULL_TREE, $2, $$); } | reserved_declspecs attributes { $$ = decl_tree_cons ($2, NULL_TREE, $1); } | attributes { $$ = decl_tree_cons ($1, NULL_TREE, NULL_TREE); } ;/* 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. In the result, declspecs have a non-NULL TREE_VALUE, attributes do not. */declmods: nonempty_cv_qualifiers %prec EMPTY { $$ = $1.t; TREE_STATIC ($$) = 1; } | SCSPEC { $$ = IDENTIFIER_AS_LIST ($$); } | declmods CV_QUALIFIER { $$ = decl_tree_cons (NULL_TREE, $2, $$); TREE_STATIC ($$) = 1; } | declmods SCSPEC { if (extra_warnings && TREE_STATIC ($$)) warning ("`%s' is not at beginning of declaration", IDENTIFIER_POINTER ($2)); $$ = decl_tree_cons (NULL_TREE, $2, $$); TREE_STATIC ($$) = TREE_STATIC ($1); } | declmods attributes { $$ = decl_tree_cons ($2, NULL_TREE, $1); } | attributes { $$ = decl_tree_cons ($1, NULL_TREE, NULL_TREE); } ;/* Used instead of declspecs where storage classes are not allowed (that is, for typenames and structure components). C++ can takes storage classes for structure components. Don't accept a typedef-name if anything but a modifier precedes it. */typed_typespecs: typespec %prec EMPTY { $$.t = get_decl_list ($1.t); $$.new_type_flag = $1.new_type_flag; } | nonempty_cv_qualifiers typespec { $$.t = decl_tree_cons (NULL_TREE, $2.t, $1.t); $$.new_type_flag = $2.new_type_flag; } | typespec reserved_typespecquals { $$.t = decl_tree_cons (NULL_TREE, $1.t, $2); $$.new_type_flag = $1.new_type_flag; } | nonempty_cv_qualifiers typespec reserved_typespecquals { $$.t = decl_tree_cons (NULL_TREE, $2.t, chainon ($3, $1.t)); $$.new_type_flag = $1.new_type_flag; } ;reserved_typespecquals: typespecqual_reserved { $$ = build_decl_list (NULL_TREE, $1.t); } | reserved_typespecquals typespecqual_reserved { $$ = decl_tree_cons (NULL_TREE, $2.t, $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: structsp | TYPESPEC %prec EMPTY { $$.t = $1; $$.new_type_flag = 0; } | complete_type_name { $$.t = $1; $$.new_type_flag = 0; } | TYPEOF '(' expr ')' { $$.t = TREE_TYPE ($3); $$.new_type_flag = 0; } | TYPEOF '(' type_id ')' { $$.t = groktypename ($3.t); $$.new_type_flag = 0; } | SIGOF '(' expr ')' { tree type = TREE_TYPE ($3); $$.new_type_flag = 0; if (IS_AGGR_TYPE (type)) { sorry ("sigof type specifier"); $$.t = type; } else { error ("`sigof' applied to non-aggregate expression"); $$.t = error_mark_node; } } | SIGOF '(' type_id ')' { tree type = groktypename ($3.t); $$.new_type_flag = 0; if (IS_AGGR_TYPE (type)) { sorry ("sigof type specifier"); $$.t = type; } else { error("`sigof' applied to non-aggregate type"); $$.t = error_mark_node; } } ;/* A typespec that is a reserved word, or a type qualifier. */typespecqual_reserved: TYPESPEC { $$.t = $1; $$.new_type_flag = 0; } | CV_QUALIFIER { $$.t = $1; $$.new_type_flag = 0; } | structsp ;initdecls: initdcl0 | initdecls ',' initdcl ;notype_initdecls: notype_initdcl0 | notype_initdecls ',' initdcl ;nomods_initdecls: nomods_initdcl0 | nomods_initdecls ',' initdcl ;maybeasm: /* empty */ { $$ = NULL_TREE; } | asm_keyword '(' string ')' { if (TREE_CHAIN ($3)) $3 = combine_strings ($3); $$ = $3; } ;initdcl0: declarator maybeasm maybe_attribute '=' { split_specs_attrs ($<ttype>0, ¤t_declspecs, &prefix_attributes); if (current_declspecs && TREE_CODE (current_declspecs) != TREE_LIST) current_declspecs = get_decl_list (current_declspecs); if (have_extern_spec && !used_extern_spec) { current_declspecs = decl_tree_cons (NULL_TREE, get_identifier ("extern"), current_declspecs); used_extern_spec = 1; } $<itype>4 = suspend_momentary (); $<ttype>$ = start_decl ($<ttype>1, current_declspecs, 1); cplus_decl_attributes ($<ttype>$, $3, prefix_attributes); } init/* Note how the declaration of the variable is in effect while its init is parsed! */ { cp_finish_decl ($<ttype>5, $6, $2, 1, LOOKUP_ONLYCONVERTING); $$ = $<itype>4; } | declarator maybeasm maybe_attribute { tree d; split_specs_attrs ($<ttype>0, ¤t_declspecs, &prefix_attributes); if (current_declspecs && TREE_CODE (current_declspecs) != TREE_LIST) current_declspecs = get_decl_list (current_declspecs); if (have_extern_spec && !used_extern_spec) { current_declspecs = decl_tree_cons (NULL_TREE, get_identifier ("extern"), current_declspecs); used_extern_spec = 1; } $$ = suspend_momentary (); d = start_decl ($<ttype>1, current_declspecs, 0); cplus_decl_attributes (d, $3, prefix_attributes); cp_finish_decl (d, NULL_TREE, $2, 1, 0); } ;initdcl: declarator maybeasm maybe_attribute '=' { $<ttype>$ = start_decl ($<ttype>1, current_declspecs, 1); cplus_decl_attributes ($<ttype>$, $3, prefix_attributes); } init/* Note how the declaration of the variable is in effect while its init is parsed! */ { cp_finish_decl ($<ttype>5, $6, $2, 1, LOOKUP_ONLYCONVERTING); } | declarator maybeasm maybe_attribute { $<ttype>$ = start_decl ($<ttype>1, current_declspecs, 0); cplus_decl_attributes ($<ttype>$, $3, prefix_attributes); cp_finish_decl ($<ttype>$, NULL_TREE, $2, 1, 0); } ;notype_initdcl0: notype_declarator maybeasm maybe_attribute '=' { split_specs_attrs ($<ttype>0, ¤t_declspecs, &prefix_attributes); $<itype>4 = suspend_momentary (); $<ttype>$ = start_decl ($<ttype>1, current_declspecs, 1); cplus_decl_attributes ($<ttype>$, $3, prefix_attributes); } init/* Note how the declaration of the variable is in effect while its init is parsed! */ { cp_finish_decl ($<ttype>5, $6, $2, 1, LOOKUP_ONLYCONVERTING); $$ = $<itype>4; } | notype_declarator maybeasm maybe_attribute { tree d; split_specs_attrs ($<ttype>0, ¤t_declspecs, &prefix_attributes); $$ = suspend_momentary (); d = start_decl ($<ttype>1, current_declspecs, 0); cplus_decl_attributes (d, $3, prefix_attributes); cp_finish_decl (d, NULL_TREE, $2, 1, 0); } ;nomods_initdcl0: notype_declarator maybeasm maybe_attribute '=' { current_declspecs = NULL_TREE; prefix_attributes = NULL_TREE; $<itype>4 = suspend_momentary (); $<ttype>$ = start_decl ($1, current_declspecs, 1); cplus_decl_attributes ($<ttype>$, $3, prefix_attributes); } init/* Note how the declaration of the variable is in effect while its init is parsed! */ { cp_finish_decl ($<ttype>5, $6, $2, 1, LOOKUP_ONLYCONVERTING); $$ = $<itype>4; } | notype_declarator maybeasm maybe_attribute { tree d; current_declspecs = NULL_TREE; prefix_attributes = NULL_TREE; $$ = suspend_momentary (); d = start_decl ($1, current_declspecs, 0); cplus_decl_attributes (d, $3, prefix_attributes); cp_finish_decl (d, NULL_TREE, $2, 1, 0); } ;/* 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 '(' nonnull_exprlist ')' { $$ = build_tree_list ($1, $3); } ;/* This still leaves out most reserved keywords, shouldn't we include them? */any_word: identifier | SCSPEC | TYPESPEC | CV_QUALIFIER ;/* 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)); } ;maybe_init: /* empty */ %prec EMPTY { $$ = NULL_TREE; } | '=' init { $$ = $2; }/* If we are processing a template, we don't want to expand this initializer yet. */init: expr_no_commas %prec '=' | '{' '}' { $$ = build_nt (CONSTRUCTOR, NULL_TREE, NULL_TREE); TREE_HAS_CONSTRUCTOR ($$) = 1; } | '{' initlist '}' { $$ = build_nt (CONSTRUCTOR, NULL_TREE, nreverse ($2)); TREE_HAS_CONSTRUCTOR ($$) = 1; } | '{' initlist ',' '}' { $$ = build_nt (CONSTRUCTOR, NULL_TREE, nreverse ($2)); TREE_HAS_CONSTRUCTOR ($$) = 1; } | 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, $$); } | initlist ',' init { $$ = expr_tree_cons (NULL_TREE, $3, $$); } /* These are for labeled elements. */ | '[' expr_no_commas ']' init { $$ = build_expr_list ($2, $4); } | initlist ',' CASE expr_no_commas ':' init { $$ = expr_tree_cons ($4, $6, $$); } | identifier ':' init { $$ = build_expr_list ($$, $3); } | initlist ',' identifier ':' init { $$ = expr_tree_cons ($3, $5, $$); } ;fn.defpen: PRE_PARSED_FUNCTION_DECL { start_function (NULL_TREE, TREE_VALUE ($1), NULL_TREE, 1); reinit_parse_for_function (); }pending_inline: fn.defpen maybe_return_init ctor_initializer_opt compstmt_or_error { int nested = (hack_decl_function_context (current_function_decl) != NULL_TREE); finish_function (lineno, (int)$3, nested); process_next_inline ($1); } | fn.defpen maybe_return_init function_try_block { process_next_inline ($1); } | fn.defpen maybe_return_init error { process_next_inline ($1); } ;pending_inlines: /* empty */ | pending_inlines pending_inline eat_saved_input ;/* A regurgitated d
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -