📄 cp-parse.y
字号:
d = start_decl ($3, current_declspecs, 0, $4); cplus_decl_attributes (d, $6); finish_decl (d, NULL_TREE, $5, 0); end_exception_decls (); end_template_decl ($1, d, 0); if ($7 != ';') { reinit_parse_for_template ($7, $1, d); yychar = YYEMPTY; } note_list_got_semicolon ($<ttype>2); resume_momentary (momentary); } | template_header declmods declarator fn_tmpl_end { tree d = start_decl ($3, $<ttype>2, 0, NULL_TREE); finish_decl (d, NULL_TREE, NULL_TREE, 0); end_template_decl ($1, d, 0); if ($4 != ';') reinit_parse_for_template ($4, $1, d); } /* Try to recover from syntax errors in templates. */ | template_header error '}' { end_template_decl ($1, 0, 0); } | template_header error ';' { end_template_decl ($1, 0, 0); } ;fn_tmpl_end: '{' { $$ = '{'; } | ':' { $$ = ':'; } | ';' { $$ = ';'; } | '=' { $$ = '='; } | RETURN { $$ = RETURN; } ;datadef: notype_initdecls ';' { if (pedantic) pedwarn ("ANSI C++ forbids data definition with no type or storage class"); else if (! flag_traditional && ! have_extern_spec) warning ("data definition has no type or storage class"); } | declmods notype_initdecls ';' {} /* Normal case to make fast: "int i;". */ | declmods declarator ';' { tree d; d = start_decl ($2, $<ttype>$, 0, NULL_TREE); finish_decl (d, NULL_TREE, NULL_TREE, 0); } | typed_declspecs initdecls ';' { end_exception_decls (); note_list_got_semicolon ($<ttype>$); } /* Normal case: make this fast. */ | typed_declspecs declarator ';' { tree d; d = start_decl ($2, $<ttype>$, 0, NULL_TREE); finish_decl (d, NULL_TREE, NULL_TREE, 0); end_exception_decls (); note_list_got_semicolon ($<ttype>$); } | declmods ';' { pedwarn ("empty declaration"); } | typed_declspecs ';' { tree t = $<ttype>$; shadow_tag (t); if (TREE_CODE (t) == TREE_LIST && TREE_PURPOSE (t) == NULL_TREE) { t = TREE_VALUE (t); if (TREE_CODE (t) == RECORD_TYPE) { if (CLASSTYPE_USE_TEMPLATE (t) == 0) CLASSTYPE_USE_TEMPLATE (t) = 2; else if (CLASSTYPE_USE_TEMPLATE (t) == 1) error ("override declaration for already-expanded template"); } } note_list_got_semicolon ($<ttype>$); } | error ';' | error '}' | ';' ;fndef: fn.def1 base_init compstmt_or_error { finish_function (lineno, 1); /* finish_function performs these three statements: expand_end_bindings (getdecls (), 1, 0); poplevel (1, 1, 0); expand_end_bindings (0, 0, 0); poplevel (0, 0, 1); */ if ($<ttype>$) process_next_inline ($<ttype>$); } | fn.def1 return_init base_init compstmt_or_error { finish_function (lineno, 1); /* finish_function performs these three statements: expand_end_bindings (getdecls (), 1, 0); poplevel (1, 1, 0); expand_end_bindings (0, 0, 0); poplevel (0, 0, 1); */ if ($<ttype>$) process_next_inline ($<ttype>$); } | fn.def1 nodecls compstmt_or_error { finish_function (lineno, 0); if ($<ttype>$) process_next_inline ($<ttype>$); } | fn.def1 return_init ';' nodecls compstmt_or_error { finish_function (lineno, 0); if ($<ttype>$) process_next_inline ($<ttype>$); } | fn.def1 return_init nodecls compstmt_or_error { finish_function (lineno, 0); if ($<ttype>$) process_next_inline ($<ttype>$); } | typed_declspecs declarator error {} | declmods notype_declarator error {} | notype_declarator error {} ;fn.def1: typed_declspecs declarator maybe_raises { if (! start_function ($$, $2, $3, 0)) YYERROR1; reinit_parse_for_function (); $$ = NULL_TREE; } | declmods notype_declarator maybe_raises { if (! start_function ($$, $2, $3, 0)) YYERROR1; reinit_parse_for_function (); $$ = NULL_TREE; } | notype_declarator maybe_raises { if (! start_function (NULL_TREE, $$, $2, 0)) YYERROR1; reinit_parse_for_function (); $$ = NULL_TREE; } | TYPENAME '(' parmlist ')' type_quals maybe_raises { if (! start_function (NULL_TREE, build_parse_node (CALL_EXPR, $$, $3, $5), $6, 0)) YYERROR1; reinit_parse_for_function (); $$ = NULL_TREE; } | scoped_typename '(' parmlist ')' type_quals maybe_raises { if (! start_function (NULL_TREE, build_parse_node (CALL_EXPR, $$, $3, $5), $6, 0)) YYERROR1; reinit_parse_for_function (); $$ = NULL_TREE; } | TYPENAME LEFT_RIGHT type_quals maybe_raises { if (! start_function (NULL_TREE, build_parse_node (CALL_EXPR, $$, empty_parms (), $3), $4, 0)) YYERROR1; reinit_parse_for_function (); $$ = NULL_TREE; } | scoped_typename LEFT_RIGHT type_quals maybe_raises { if (! start_function (NULL_TREE, build_parse_node (CALL_EXPR, $$, empty_parms (), $3), $4, 0)) YYERROR1; reinit_parse_for_function (); $$ = NULL_TREE; } | PRE_PARSED_FUNCTION_DECL { start_function (NULL_TREE, TREE_VALUE ($$), NULL_TREE, 1); reinit_parse_for_function (); } ;/* more C++ complexity */fn.def2: typed_declspecs '(' parmlist ')' type_quals maybe_raises { tree decl = build_parse_node (CALL_EXPR, TREE_VALUE ($$), $3, $5); $$ = start_method (TREE_CHAIN ($$), decl, $6); if (! $$) YYERROR1; if (yychar == YYEMPTY) yychar = YYLEX; reinit_parse_for_method (yychar, $$); } | typed_declspecs LEFT_RIGHT type_quals maybe_raises { tree decl = build_parse_node (CALL_EXPR, TREE_VALUE ($$), empty_parms (), $3); $$ = start_method (TREE_CHAIN ($$), decl, $4); if (! $$) YYERROR1; if (yychar == YYEMPTY) yychar = YYLEX; reinit_parse_for_method (yychar, $$); } | typed_declspecs declarator maybe_raises { $$ = start_method ($$, $2, $3); if (! $$) YYERROR1; if (yychar == YYEMPTY) yychar = YYLEX; reinit_parse_for_method (yychar, $$); } | declmods '(' parmlist ')' type_quals maybe_raises { tree decl = build_parse_node (CALL_EXPR, TREE_VALUE ($$), $3, $5); $$ = start_method (TREE_CHAIN ($$), decl, $6); if (! $$) YYERROR1; if (yychar == YYEMPTY) yychar = YYLEX; reinit_parse_for_method (yychar, $$); } | declmods LEFT_RIGHT type_quals maybe_raises { tree decl = build_parse_node (CALL_EXPR, TREE_VALUE ($$), empty_parms (), $3); $$ = start_method (TREE_CHAIN ($$), decl, $4); if (! $$) YYERROR1; if (yychar == YYEMPTY) yychar = YYLEX; reinit_parse_for_method (yychar, $$); } | declmods declarator maybe_raises { $$ = start_method ($$, $2, $3); if (! $$) YYERROR1; if (yychar == YYEMPTY) yychar = YYLEX; reinit_parse_for_method (yychar, $$); } | notype_declarator maybe_raises { $$ = start_method (NULL_TREE, $$, $2); if (! $$) YYERROR1; if (yychar == YYEMPTY) yychar = YYLEX; reinit_parse_for_method (yychar, $$); } ;return_id: RETURN IDENTIFIER { if (! current_function_parms_stored) store_parm_decls (); $$ = $2; } ;return_init: return_id { store_return_init ($<ttype>$, NULL_TREE); } | return_id '=' init { store_return_init ($<ttype>$, $3); } | return_id '(' nonnull_exprlist ')' { store_return_init ($<ttype>$, $3); } | return_id LEFT_RIGHT { store_return_init ($<ttype>$, NULL_TREE); } ;base_init: ':' .set_base_init member_init_list { if ($3 == 0) error ("no base initializers given following ':'"); setup_vtbl_ptr (); } ;.set_base_init: /* empty */ { if (! current_function_parms_stored) store_parm_decls (); /* Flag that we are processing base and member initializers. */ current_vtable_decl = error_mark_node; if (DECL_CONSTRUCTOR_P (current_function_decl)) { /* Make a contour for the initializer list. */ pushlevel (0); clear_last_expr (); expand_start_bindings (0); } else if (current_class_type == NULL_TREE) error ("base initializers not allowed for non-member functions"); else if (! DECL_CONSTRUCTOR_P (current_function_decl)) error ("only constructors take base initializers"); } ;member_init_list: /* empty */ { $$ = 0; } | member_init { $$ = 1; } | member_init_list ',' member_init | member_init_list error ;member_init: '(' nonnull_exprlist ')' { if (current_class_name && !flag_traditional) pedwarn ("ANSI C++ forbids old style base class initialization", IDENTIFIER_POINTER (current_class_name)); expand_member_init (C_C_D, NULL_TREE, $2); } | LEFT_RIGHT { if (current_class_name && !flag_traditional) pedwarn ("ANSI C++ forbids old style base class initialization", IDENTIFIER_POINTER (current_class_name)); expand_member_init (C_C_D, NULL_TREE, void_type_node); } | identifier '(' nonnull_exprlist ')' { expand_member_init (C_C_D, $<ttype>$, $3); } | identifier LEFT_RIGHT { expand_member_init (C_C_D, $<ttype>$, void_type_node); } | template_type_name '(' nonnull_exprlist ')' { expand_member_init (C_C_D, $<ttype>$, $3); } | template_type_name LEFT_RIGHT { expand_member_init (C_C_D, $<ttype>$, void_type_node); } | scoped_typename '(' nonnull_exprlist ')' { expand_member_init (C_C_D, $<ttype>$, $3); } | scoped_typename LEFT_RIGHT { expand_member_init (C_C_D, $<ttype>$, void_type_node); } | scoped_id identifier '(' nonnull_exprlist ')' { do_member_init ($<ttype>$, $2, $4); } | scoped_id identifier LEFT_RIGHT { do_member_init ($<ttype>$, $2, void_type_node); } ;identifier: IDENTIFIER | TYPENAME | PTYPENAME ;identifier_defn: IDENTIFIER_DEFN | TYPENAME_DEFN | PTYPENAME_DEFN ;identifier_or_opname: IDENTIFIER | TYPENAME | PTYPENAME/* | '~' TYPENAME { $$ = build_parse_node (BIT_NOT_EXPR, $2); }*/ /* get rid of the next line, replace it with the above */ | '~' identifier { $$ = build_parse_node (BIT_NOT_EXPR,$2);} | operator_name ;template_type: template_type_name tmpl.1 template_instantiation { extern tree template_type_seen_before_scope; if ($3) $$ = $3; else if ($$ != error_mark_node) $$ = IDENTIFIER_TYPE_VALUE ($$); /* This is a kludge: In order to detect nested types inside * template classes, we have to tell the lexer that it should * try to replace a following SCOPE token with the correct * SCOPED_TYPENAME for the nested type. This SCOPED_TYPENAME * token will be handled in the rule "scoped_typename". * - niklas@appli.se */ if (yychar == SCOPE) { template_type_seen_before_scope = TYPE_IDENTIFIER ($$); yychar = YYLEX; } } ;template_type_name: PTYPENAME '<' template_arg_list '>' { $$ = lookup_template_class ($$, $3); } | TYPENAME '<' template_arg_list '>' { $$ = lookup_template_class ($$, $3); } ;tmpl.1: /* Expansion of template may be required, unless we're followed by a class definition. */ '{' { yyungetc ('{', 1); $$ = 0; } | ':' { yyungetc (':', 1); $$ = 0; } | /* empty */ %prec EMPTY { $$ = instantiate_class_template ($<ttype>0, 1); } ;tmpl.2: /* Always do expansion if it hasn't been done already. */ { $$ = instantiate_class_template ($<ttype>0, 1); } ;template_arg_list: template_arg { $$ = build_tree_list (NULL_TREE, $$); } | template_arg_list ',' template_arg { $$ = chainon ($$, build_tree_list (NULL_TREE, $3)); } ;template_arg: typename { $$ = groktypename ($$); } | expr_no_commas %prec UNARY ;template_instantiate_once: PRE_PARSED_CLASS_DECL maybe_base_class_list { tree t, decl, id, tmpl; id = TREE_VALUE ($1); tmpl = TREE_PURPOSE (IDENTIFIER_TEMPLATE (id)); t = xref_tag (DECL_TEMPLATE_INFO (tmpl)->aggr, id, $2); set_current_level_tags_transparency (1); my_friendly_assert (TREE_CODE (t) == RECORD_TYPE, 257); $<ttype>$ = t; /* Now, put a copy of the decl in global scope, to avoid recursive expansion. */ decl = IDENTIFIER_LOCAL_VALUE (id); if (!decl) decl = IDENTIFIER_CLASS_VALUE (id); /* Now, put a copy of the decl in global scope, to avoid recursive expansion. */ if (decl) { /* Need to copy it to clear the chain pointer, and need to get it into permanent storage. */ my_friendly_assert (TREE_CODE (decl) == TYPE_DECL, 258); push_obstacks (&permanent_obstack, &permanent_obstack); decl = copy_node (decl); if (DECL_LANG_SPECIFIC (decl)) copy_lang_decl (decl); pop_obstacks (); pushdecl_top_level (decl); } } left_curly opt.component_decl_list '}' { extern void end_template_instantiation (); int old_interface = interface_unknown;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -