📄 cp-parse.y
字号:
;/* A typespec that is a reserved word, or a type qualifier. */typespecqual_reserved: TYPESPEC | TYPE_QUAL | structsp ;initdecls: initdcl0 | initdecls ',' initdcl ;notype_initdecls: notype_initdcl0 | notype_initdecls ',' initdcl ;maybeasm: /* empty */ { $$ = NULL_TREE; } | ASM_KEYWORD '(' string ')' { if (TREE_CHAIN ($3)) $3 = combine_strings ($3); $$ = $3; if (pedantic) pedwarn ("ANSI C++ forbids use of `asm' keyword"); } ;initdcl0: declarator maybe_raises maybeasm maybe_attribute '=' { current_declspecs = $<ttype>0; $<itype>5 = suspend_momentary (); $<ttype>$ = start_decl ($1, current_declspecs, 1, $2); cplus_decl_attributes ($<ttype>$, $4); } init/* Note how the declaration of the variable is in effect while its init is parsed! */ { finish_decl ($<ttype>6, $7, $3, 0); $$ = $<itype>5; } | declarator maybe_raises maybeasm maybe_attribute { tree d; current_declspecs = $<ttype>0; $$ = suspend_momentary (); d = start_decl ($1, current_declspecs, 0, $2); cplus_decl_attributes (d, $4); finish_decl (d, NULL_TREE, $3, 0); } ;initdcl: declarator maybe_raises maybeasm maybe_attribute '=' { $<ttype>$ = start_decl ($1, current_declspecs, 1, $2); cplus_decl_attributes ($<ttype>$, $4); } init/* Note how the declaration of the variable is in effect while its init is parsed! */ { finish_decl ($<ttype>6, $7, $3, 0); } | declarator maybe_raises maybeasm maybe_attribute { tree d = start_decl ($$, current_declspecs, 0, $2); cplus_decl_attributes ($<ttype>$, $4); finish_decl (d, NULL_TREE, $3, 0); } ;notype_initdcl0: notype_declarator maybe_raises maybeasm maybe_attribute '=' { current_declspecs = $<ttype>0; $<itype>5 = suspend_momentary (); $<ttype>$ = start_decl ($1, current_declspecs, 1, $2); cplus_decl_attributes ($<ttype>$, $4); } init/* Note how the declaration of the variable is in effect while its init is parsed! */ { finish_decl ($<ttype>6, $7, $3, 0); $$ = $<itype>5; } | notype_declarator maybe_raises maybeasm maybe_attribute { tree d; current_declspecs = $<ttype>0; $$ = suspend_momentary (); d = start_decl ($1, current_declspecs, 0, $2); cplus_decl_attributes (d, $4); finish_decl (d, NULL_TREE, $3, 0); } ;/* 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, NULL_TREE); } | 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, NULL_TREE), NULL_TREE), NULL_TREE); } ;/* 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)); } ;init: expr_no_commas %prec '=' | '{' '}' { $$ = build_nt (CONSTRUCTOR, NULL_TREE, NULL_TREE); TREE_HAS_CONSTRUCTOR ($$) = 1; if (pedantic) pedwarn ("ANSI C++ forbids empty initializer braces"); } | '{' 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 { $$ = tree_cons (NULL_TREE, $3, $$); } /* These are for labeled elements. */ | '[' expr_no_commas ']' init { $$ = build_tree_list ($2, $4); } | initlist ',' CASE expr_no_commas ':' init { $$ = tree_cons ($4, $6, $$); } | identifier ':' init { $$ = build_tree_list ($$, $3); } | initlist ',' identifier ':' init { $$ = tree_cons ($3, $5, $$); } ;structsp: ENUM identifier '{' { $<itype>3 = suspend_momentary (); $$ = start_enum ($2); } enumlist maybecomma_warn '}' { $$ = finish_enum ($<ttype>4, $5); resume_momentary ($<itype>3); check_for_missing_semicolon ($<ttype>4); } | ENUM identifier '{' '}' { $$ = finish_enum (start_enum ($2), NULL_TREE); check_for_missing_semicolon ($$); } | ENUM '{' { $<itype>2 = suspend_momentary (); $$ = start_enum (make_anon_name ()); } enumlist maybecomma_warn '}' { $$ = finish_enum ($<ttype>3, $4); resume_momentary ($<itype>1); check_for_missing_semicolon ($<ttype>3); } | ENUM '{' '}' { $$ = finish_enum (start_enum (make_anon_name()), NULL_TREE); check_for_missing_semicolon ($$); } | ENUM identifier { $$ = xref_tag (enum_type_node, $2, NULL_TREE); } /* C++ extensions, merged with C to avoid shift/reduce conflicts */ | class_head left_curly opt.component_decl_list '}' { int semi; tree id;#if 0 /* Need to rework class nesting in the presence of nested classes, etc. */ shadow_tag (CLASSTYPE_AS_LIST ($$)); */#endif if (yychar == YYEMPTY) yychar = YYLEX; semi = yychar == ';'; /* finish_struct nukes this anyway; if finish_exception does too, then it can go. */ if (semi) note_got_semicolon ($$); if (TREE_CODE ($$) == ENUMERAL_TYPE) /* $$ = $1 from default rule. */; else if (CLASSTYPE_DECLARED_EXCEPTION ($$)) { if (! semi) $$ = finish_exception ($$, $3); else warning ("empty exception declaration\n"); } else { $$ = finish_struct ($$, $3, semi, semi); if (semi) note_got_semicolon ($$); } pop_obstacks (); id = TYPE_IDENTIFIER ($$); if (IDENTIFIER_TEMPLATE (id)) { tree decl; /* I don't know if the copying of this TYPE_DECL is * really needed. However, it's such a small per- * formance penalty that the extra safety is a bargain. * - niklas@appli.se */ push_obstacks (&permanent_obstack, &permanent_obstack); decl = copy_node (lookup_name (id)); if (DECL_LANG_SPECIFIC (decl)) copy_lang_decl (decl); pop_obstacks (); undo_template_name_overload (id, 0); pushdecl_top_level (decl); } if (! semi) check_for_missing_semicolon ($$); } | class_head %prec EMPTY {#if 0 /* It's no longer clear what the following error is supposed to accomplish. If it turns out to be needed, add a comment why. */ if (TYPE_BINFO_BASETYPES ($$) && !TYPE_SIZE ($$)) { error ("incomplete definition of type `%s'", TYPE_NAME_STRING ($$)); $$ = error_mark_node; }#endif } ;maybecomma: /* empty */ | ',' ;maybecomma_warn: /* empty */ | ',' { if (pedantic) pedwarn ("ANSI C++ forbids comma at end of enumerator list"); } ;aggr: AGGR | DYNAMIC AGGR { $$ = build_tree_list (NULL_TREE, $2); } | DYNAMIC '(' string ')' AGGR { $$ = build_tree_list ($3, $5); } | aggr SCSPEC { error ("storage class specifier `%s' not allowed after struct or class", IDENTIFIER_POINTER ($2)); } | aggr TYPESPEC { error ("type specifier `%s' not allowed after struct or class", IDENTIFIER_POINTER ($2)); } | aggr TYPE_QUAL { error ("type qualifier `%s' not allowed after struct or class", IDENTIFIER_POINTER ($2)); } | aggr AGGR { error ("no body nor ';' separates two class, struct or union declarations"); } ;named_class_head_sans_basetype: aggr identifier { aggr1: current_aggr = $$; $$ = $2; } | aggr template_type_name %prec EMPTY { current_aggr = $$; $$ = $2; } | aggr TYPENAME_COLON { yyungetc (':', 1); goto aggr1; } | aggr template_type_name '{' { yyungetc ('{', 1); aggr2: current_aggr = $$; $$ = $2; overload_template_name ($$, 0); } | aggr template_type_name ':' { yyungetc (':', 1); goto aggr2; } ;named_class_head_sans_basetype_defn: aggr identifier_defn { current_aggr = $$; $$ = $2; } ;named_class_head: named_class_head_sans_basetype { $<ttype>$ = xref_tag (current_aggr, $1, NULL_TREE); } maybe_base_class_list %prec EMPTY { if ($3) $$ = xref_tag (current_aggr, $1, $3); else $$ = $<ttype>2; } | named_class_head_sans_basetype_defn { $<ttype>$ = xref_defn_tag (current_aggr, $1, NULL_TREE); } maybe_base_class_list %prec EMPTY { if ($3) $$ = xref_defn_tag (current_aggr, $1, $3); else $$ = $<ttype>2; } ;unnamed_class_head: aggr '{' { $$ = xref_tag ($$, make_anon_name (), NULL_TREE); yyungetc ('{', 1); } ;class_head: unnamed_class_head | named_class_head ;maybe_base_class_list: /* empty */ { $$ = NULL_TREE; } | ':' %prec EMPTY { yyungetc(':', 1); $$ = NULL_TREE; } | ':' base_class_list %prec EMPTY { $$ = $2; } ;base_class_list: base_class | base_class_list ',' base_class { $$ = chainon ($$, $3); } ;base_class: base_class.1 { if (! is_aggr_typedef ($$, 1)) $$ = NULL_TREE; else $$ = build_tree_list ((tree)visibility_default, $$); } | scoped_base_class { if (! is_aggr_typedef ($$, 1)) $$ = NULL_TREE; else $$ = build_tree_list ((tree)visibility_default, $$); } | base_class_visibility_list base_class.1 { if (! is_aggr_typedef ($2, 1)) $$ = NULL_TREE; else $$ = build_tree_list ((tree) $$, $2); } | base_class_visibility_list scoped_base_class { if (! is_aggr_typedef ($2, 1)) $$ = NULL_TREE; else $$ = build_tree_list ((tree) $$, $2); } ;scoped_base_class: base_class.1 SCOPED_TYPENAME { /* Kludge!!! See rule "template_type" and the code * dealing with "template_type_seen_before_scope" in * yylex(). */ $$ = $2; } ;base_class.1: template_type_name tmpl.2 template_instantiation { extern tree template_type_seen_before_scope; tree id = $3 ? TYPE_IDENTIFIER ($3) : $1; /* Check the rule template_type to get this... */ if (yychar == YYEMPTY) yychar = YYLEX; if (yychar == SCOPE) { template_type_seen_before_scope = id; yychar = YYLEX; } } | identifier ;base_class_visibility_list: VISSPEC | SCSPEC { if ($<ttype>$ != ridpointers[(int)RID_VIRTUAL]) sorry ("non-virtual visibility"); $$ = visibility_default_virtual; } | base_class_visibility_list VISSPEC { int err = 0; if ($2 == visibility_protected) { warning ("`protected' visibility not implemented"); $2 = visibility_public; err++; } else if ($2 == visibility_public) { if ($1 == visibility_private) { mixed: error ("base class cannot be public and private"); } else if ($1 == visibility_default_virtual) $$ = visibility_public_virtual; } else /* $2 == visibility_private */ { if ($1 == visibility_public) goto mixed;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -