📄 parse.y
字号:
decl = IDENTIFIER_LOCAL_VALUE ($1); if (!decl) decl = IDENTIFIER_CLASS_VALUE ($1); /* 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); } /* Kludge; see instantiate_class_template. */ TYPE_BEING_DEFINED (t) = 0; } left_curly opt.component_decl_list '}' { tree t = finish_struct ($<ttype>3, $5, 0); pop_obstacks (); end_template_instantiation ($1); repo_template_used (t); /* Now go after the methods & class data. */ instantiate_member_templates ($1); pop_tinst_level(); CLASSTYPE_GOT_SEMICOLON (t) = 1; } ;template_instantiation: /* empty */ { $$ = NULL_TREE; } | template_instantiate_once { $$ = $1; } ;template_instantiate_some: /* empty */ { $$ = NULL_TREE; /* never used from here... */} | template_instantiate_once template_instantiate_some { $$ = $1; /*???*/ } ;unop: '-' { $$ = NEGATE_EXPR; } | '+' { $$ = CONVERT_EXPR; } | PLUSPLUS { $$ = PREINCREMENT_EXPR; } | MINUSMINUS { $$ = PREDECREMENT_EXPR; } | '!' { $$ = TRUTH_NOT_EXPR; } ;expr: nontrivial_exprlist { $$ = build_x_compound_expr ($$); } | expr_no_commas ;paren_expr_or_null: LEFT_RIGHT { error ("ANSI C++ forbids an empty condition for `%s'", cond_stmt_keyword); $$ = integer_zero_node; } | '(' expr ')' { $$ = condition_conversion ($2); } ;paren_cond_or_null: LEFT_RIGHT { error ("ANSI C++ forbids an empty condition for `%s'", cond_stmt_keyword); $$ = integer_zero_node; } | '(' condition ')' { $$ = condition_conversion ($2); } ;xcond: /* empty */ { $$ = NULL_TREE; } | condition { $$ = condition_conversion ($$); } | error { $$ = NULL_TREE; } ;condition: type_specifier_seq declarator exception_specification_opt maybeasm maybe_attribute '=' { { tree d; for (d = getdecls (); d; d = TREE_CHAIN (d)) if (TREE_CODE (d) == TYPE_DECL) { tree s = TREE_TYPE (d); if (TREE_CODE (s) == RECORD_TYPE) cp_error ("definition of class `%T' in condition", s); else if (TREE_CODE (s) == ENUMERAL_TYPE) cp_error ("definition of enum `%T' in condition", s); } } current_declspecs = $1; $<itype>6 = suspend_momentary (); $<ttype>$ = start_decl ($<ttype>2, current_declspecs, 1, $3); cplus_decl_attributes ($<ttype>$, $5, /*prefix_attributes*/ NULL_TREE); } init { cp_finish_decl ($<ttype>7, $8, $5, 0, LOOKUP_ONLYCONVERTING); resume_momentary ($<itype>6); $$ = $<ttype>7; if (TREE_CODE (TREE_TYPE ($$)) == ARRAY_TYPE) cp_error ("definition of array `%#D' in condition", $$); } | expr ;compstmtend: '}' | maybe_label_decls stmts '}' | maybe_label_decls stmts error '}' | maybe_label_decls error '}' ;already_scoped_stmt: '{' compstmtend { finish_stmt (); } | simple_stmt ;nontrivial_exprlist: expr_no_commas ',' expr_no_commas { $$ = tree_cons (NULL_TREE, $$, build_tree_list (NULL_TREE, $3)); } | expr_no_commas ',' error { $$ = tree_cons (NULL_TREE, $$, build_tree_list (NULL_TREE, error_mark_node)); } | nontrivial_exprlist ',' expr_no_commas { chainon ($$, build_tree_list (NULL_TREE, $3)); } | nontrivial_exprlist ',' error { chainon ($$, build_tree_list (NULL_TREE, error_mark_node)); } ;nonnull_exprlist: expr_no_commas { $$ = build_tree_list (NULL_TREE, $$); } | nontrivial_exprlist ;unary_expr: primary %prec UNARY {#if 0 if (TREE_CODE ($$) == TYPE_EXPR) $$ = build_component_type_expr (C_C_D, $$, NULL_TREE, 1);#endif } /* __extension__ turns off -pedantic for following primary. */ | EXTENSION { $<itype>1 = pedantic; pedantic = 0; } cast_expr %prec UNARY { $$ = $3; pedantic = $<itype>1; } | '*' cast_expr %prec UNARY { $$ = build_x_indirect_ref ($2, "unary *"); } | '&' cast_expr %prec UNARY { $$ = build_x_unary_op (ADDR_EXPR, $2); } | '~' cast_expr { $$ = build_x_unary_op (BIT_NOT_EXPR, $2); } | unop cast_expr %prec UNARY { $$ = build_x_unary_op ($1, $2); if ($1 == NEGATE_EXPR && TREE_CODE ($2) == INTEGER_CST) TREE_NEGATED_INT ($$) = 1; overflow_warning ($$); } /* Refer to the address of a label as a pointer. */ | ANDAND identifier { tree label = lookup_label ($2); if (label == NULL_TREE) $$ = null_pointer_node; else { TREE_USED (label) = 1; $$ = build1 (ADDR_EXPR, ptr_type_node, label); TREE_CONSTANT ($$) = 1; } } | SIZEOF unary_expr %prec UNARY { if (TREE_CODE ($2) == COMPONENT_REF && DECL_BIT_FIELD (TREE_OPERAND ($2, 1))) error ("sizeof applied to a bit-field"); /* ANSI says arrays and functions are converted inside comma. But we can't really convert them in build_compound_expr because that would break commas in lvalues. So do the conversion here if operand was a comma. */ if (TREE_CODE ($2) == COMPOUND_EXPR && (TREE_CODE (TREE_TYPE ($2)) == ARRAY_TYPE || TREE_CODE (TREE_TYPE ($2)) == FUNCTION_TYPE)) $2 = default_conversion ($2); else if (TREE_CODE ($2) == TREE_LIST) { tree t = TREE_VALUE ($2); if (t != NULL_TREE && ((TREE_TYPE (t) && TREE_CODE (TREE_TYPE (t)) == FUNCTION_TYPE) || is_overloaded_fn (t))) pedwarn ("ANSI C++ forbids taking the sizeof a function type"); } $$ = c_sizeof (TREE_TYPE ($2)); } | SIZEOF '(' type_id ')' %prec HYPERUNARY { $$ = c_sizeof (groktypename ($3)); } | ALIGNOF unary_expr %prec UNARY { $$ = grok_alignof ($2); } | ALIGNOF '(' type_id ')' %prec HYPERUNARY { $$ = c_alignof (groktypename ($3)); } /* The %prec EMPTY's here are required by the = init initializer syntax extension; see below. */ | new new_type_id %prec EMPTY { $$ = build_new (NULL_TREE, $2, NULL_TREE, $1); } | new new_type_id new_initializer { $$ = build_new (NULL_TREE, $2, $3, $1); } | new new_placement new_type_id %prec EMPTY { $$ = build_new ($2, $3, NULL_TREE, $1); } | new new_placement new_type_id new_initializer { $$ = build_new ($2, $3, $4, $1); } | new '(' type_id ')' %prec EMPTY { $$ = build_new (NULL_TREE, groktypename($3), NULL_TREE, $1); } | new '(' type_id ')' new_initializer { $$ = build_new (NULL_TREE, groktypename($3), $5, $1); } | new new_placement '(' type_id ')' %prec EMPTY { $$ = build_new ($2, groktypename($4), NULL_TREE, $1); } | new new_placement '(' type_id ')' new_initializer { $$ = build_new ($2, groktypename($4), $6, $1); } | delete cast_expr %prec UNARY { $$ = delete_sanity ($2, NULL_TREE, 0, $1); } | delete '[' ']' cast_expr %prec UNARY { $$ = delete_sanity ($4, NULL_TREE, 1, $1); if (yychar == YYEMPTY) yychar = YYLEX; } | delete '[' expr ']' cast_expr %prec UNARY { $$ = delete_sanity ($5, $3, 2, $1); if (yychar == YYEMPTY) yychar = YYLEX; } ;new_placement: '(' nonnull_exprlist ')' { $$ = $2; } | '{' nonnull_exprlist '}' { $$ = $2; pedwarn ("old style placement syntax, use () instead"); } ;new_initializer: '(' nonnull_exprlist ')' { $$ = $2; } | LEFT_RIGHT { $$ = NULL_TREE; } | '(' typespec ')' { cp_error ("`%T' is not a valid expression", $2); $$ = error_mark_node; } /* GNU extension so people can use initializer lists. Note that this alters the meaning of `new int = 1', which was previously syntactically valid but semantically invalid. */ | '=' init { if (pedantic) pedwarn ("ANSI C++ forbids initialization of new expression with `='"); $$ = $2; } ;/* This is necessary to postpone reduction of `int ((int)(int)(int))'. */regcast_or_absdcl: '(' type_id ')' %prec EMPTY { $2 = tree_cons (NULL_TREE, $2, void_list_node); TREE_PARMLIST ($2) = 1; $$ = build_parse_node (CALL_EXPR, NULL_TREE, $2, NULL_TREE); } | regcast_or_absdcl '(' type_id ')' %prec EMPTY { $3 = tree_cons (NULL_TREE, $3, void_list_node); TREE_PARMLIST ($3) = 1; $$ = build_parse_node (CALL_EXPR, $$, $3, NULL_TREE); } ;cast_expr: unary_expr | regcast_or_absdcl unary_expr %prec UNARY { $$ = reparse_absdcl_as_casts ($$, $2); } | regcast_or_absdcl '{' initlist maybecomma '}' %prec UNARY { tree init = build_nt (CONSTRUCTOR, NULL_TREE, nreverse ($3)); if (pedantic) pedwarn ("ANSI C++ forbids constructor-expressions"); /* Indicate that this was a GNU C constructor expression. */ TREE_HAS_CONSTRUCTOR (init) = 1; $$ = reparse_absdcl_as_casts ($$, init); } ;expr_no_commas: cast_expr /* Handle general members. */ | expr_no_commas POINTSAT_STAR expr_no_commas { $$ = build_x_binary_op (MEMBER_REF, $$, $3); } | expr_no_commas DOT_STAR expr_no_commas { $$ = build_m_component_ref ($$, $3); } | expr_no_commas '+' expr_no_commas { $$ = build_x_binary_op ($2, $$, $3); } | expr_no_commas '-' expr_no_commas { $$ = build_x_binary_op ($2, $$, $3); } | expr_no_commas '*' expr_no_commas { $$ = build_x_binary_op ($2, $$, $3); } | expr_no_commas '/' expr_no_commas { $$ = build_x_binary_op ($2, $$, $3); } | expr_no_commas '%' expr_no_commas { $$ = build_x_binary_op ($2, $$, $3); } | expr_no_commas LSHIFT expr_no_commas { $$ = build_x_binary_op ($2, $$, $3); } | expr_no_commas RSHIFT expr_no_commas { $$ = build_x_binary_op ($2, $$, $3); } | expr_no_commas ARITHCOMPARE expr_no_commas { $$ = build_x_binary_op ($2, $$, $3); } | expr_no_commas '<' expr_no_commas { $$ = build_x_binary_op (LT_EXPR, $$, $3); } | expr_no_commas '>' expr_no_commas { $$ = build_x_binary_op (GT_EXPR, $$, $3); } | expr_no_commas EQCOMPARE expr_no_commas { $$ = build_x_binary_op ($2, $$, $3); } | expr_no_commas MIN_MAX expr_no_commas { $$ = build_x_binary_op ($2, $$, $3); } | expr_no_commas '&' expr_no_commas { $$ = build_x_binary_op ($2, $$, $3); } | expr_no_commas '|' expr_no_commas { $$ = build_x_binary_op ($2, $$, $3); } | expr_no_commas '^' expr_no_commas { $$ = build_x_binary_op ($2, $$, $3); } | expr_no_commas ANDAND expr_no_commas { $$ = build_x_binary_op (TRUTH_ANDIF_EXPR, $$, $3); } | expr_no_commas OROR expr_no_commas { $$ = build_x_binary_op (TRUTH_ORIF_EXPR, $$, $3); } | expr_no_commas '?' xexpr ':' expr_no_commas { $$ = build_x_conditional_expr ($$, $3, $5); } | expr_no_commas '=' expr_no_commas { $$ = build_modify_expr ($$, NOP_EXPR, $3); C_SET_EXP_ORIGINAL_CODE ($$, MODIFY_EXPR); } | expr_no_commas ASSIGN expr_no_commas { register tree rval; if ((rval = build_opfncall (MODIFY_EXPR, LOOKUP_NORMAL, $$, $3, make_node ($2)))) $$ = rval; else $$ = build_modify_expr ($$, $2, $3); } | THROW { $$ = build_throw (NULL_TREE); } | THROW expr_no_commas { $$ = build_throw ($2); }/* These extensions are not defined. The second arg to build_m_component_ref is old, build_m_component_ref now does an implicit build_indirect_ref (x, NULL_PTR) on the second argument. | object '&' expr_no_commas %prec UNARY { $$ = build_m_component_ref ($$, build_x_unary_op (ADDR_EXPR, $3)); } | object unop expr_no_commas %prec UNARY { $$ = build_m_component_ref ($$, build_x_unary_op ($2, $3)); } | object '(' type_id ')' expr_no_commas %prec UNARY { tree type = groktypename ($3); $$ = build_m_component_ref ($$, build_c_cast (type, $5, 0)); } | object primary_no_id %prec UNARY { $$ = build_m_component_ref ($$, $2); }*/ ;notype_unqualified_id: '~' see_typename identifier { $$ = build_parse_node (BIT_NOT_EXPR, $3); } | operator_name | IDENTIFIER | PTYPENAME | NSNAME %prec EMPTY ;unqualified_id: notype_unqualified_id | TYPENAME ;expr_or_declarator: notype_unqualified_id | '*' expr_or_declarator %prec UNARY { $$ = build_parse_node (INDIRECT_REF, $2); } | '&' expr_or_declarator %prec UNARY { $$ = build_parse_node (ADDR_EXPR, $2); } | '(' expr_or_declarator ')' { $$ = $2; } ;direct_notype_declarator: complex_direct_notype_declarator | notype_unqualified_id | '(' expr_or_declarator ')' { $$ = finish_decl_parsing ($2); } ;primary: notype_unqualified_id { if (TREE_CODE ($$) == BIT_NOT_EXPR) $$ = build_x_unary_op (BIT_NOT_EXPR, TREE_OPERAND ($$, 0)); else if (IDENTIFIER_OPNAME_P ($$)) { tree op = $$; $$ = lookup_name (op, 0); if ($$ == NULL_TREE) { if (op != ansi_opname[ERROR_MARK]) error ("operator %s not defined", operator_name_string (op)); $$ = error_mark_node; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -