📄 parse.y
字号:
if ($$ != error_mark_node) $$ = TYPE_STUB_DECL ($$); } | TYPENAME '<' template_arg_list template_close_bracket { $$ = lookup_template_class ($1, $3, NULL_TREE); if ($$ != error_mark_node) $$ = TYPE_STUB_DECL ($$); } | TYPENAME '<' template_close_bracket { $$ = lookup_template_class ($1, NULL_TREE, NULL_TREE); if ($$ != error_mark_node) $$ = TYPE_STUB_DECL ($$); } | self_template_type ;self_template_type: SELFNAME '<' template_arg_list template_close_bracket { $$ = lookup_template_class ($1, $3, NULL_TREE); if ($$ != error_mark_node) $$ = TYPE_STUB_DECL ($$); } | SELFNAME '<' template_close_bracket { $$ = lookup_template_class ($1, NULL_TREE, NULL_TREE); if ($$ != error_mark_node) $$ = TYPE_STUB_DECL ($$); } ;template_close_bracket: '>' | RSHIFT { /* Handle `Class<Class<Type>>' without space in the `>>' */ pedwarn ("`>>' should be `> >' in template class name"); yyungetc ('>', 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: type_id { $$ = groktypename ($1.t); } | expr_no_commas %prec ARITHCOMPARE ;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 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.t; $<itype>5 = suspend_momentary (); $<ttype>$ = start_decl ($<ttype>2, current_declspecs, 1); cplus_decl_attributes ($<ttype>$, $4, /*prefix_attributes*/ NULL_TREE); } init { cp_finish_decl ($<ttype>6, $7, $4, 1, LOOKUP_ONLYCONVERTING); resume_momentary ($<itype>5); $$ = $<ttype>6; 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: '{' { if (processing_template_decl) { $<ttype>$ = build_min_nt (COMPOUND_STMT, NULL_TREE); COMPOUND_STMT_NO_SCOPE ($<ttype>$) = 1; add_tree ($<ttype>$); } } compstmtend { if (processing_template_decl) { TREE_OPERAND ($<ttype>2, 0) = TREE_CHAIN ($<ttype>2); TREE_CHAIN ($<ttype>2) = NULL_TREE; last_tree = $<ttype>2; } finish_stmt (); } | simple_stmt ;nontrivial_exprlist: expr_no_commas ',' expr_no_commas { $$ = expr_tree_cons (NULL_TREE, $$, build_expr_list (NULL_TREE, $3)); } | expr_no_commas ',' error { $$ = expr_tree_cons (NULL_TREE, $$, build_expr_list (NULL_TREE, error_mark_node)); } | nontrivial_exprlist ',' expr_no_commas { chainon ($$, build_expr_list (NULL_TREE, $3)); } | nontrivial_exprlist ',' error { chainon ($$, build_expr_list (NULL_TREE, error_mark_node)); } ;nonnull_exprlist: expr_no_commas { $$ = build_expr_list (NULL_TREE, $$); } | nontrivial_exprlist ;unary_expr: primary %prec UNARY { $$ = $1; } /* __extension__ turns off -pedantic for following primary. */ | extension cast_expr %prec UNARY { $$ = $2; 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 (pedantic) pedwarn ("ANSI C++ forbids `&&'"); 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 { $$ = expr_sizeof ($2); } | SIZEOF '(' type_id ')' %prec HYPERUNARY { $$ = c_sizeof (groktypename ($3.t)); } | ALIGNOF unary_expr %prec UNARY { $$ = grok_alignof ($2); } | ALIGNOF '(' type_id ')' %prec HYPERUNARY { $$ = c_alignof (groktypename ($3.t)); check_for_new_type ("alignof", $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.t, NULL_TREE, $1); check_for_new_type ("new", $2); } | new new_type_id new_initializer { $$ = build_new (NULL_TREE, $2.t, $3, $1); check_for_new_type ("new", $2); } | new new_placement new_type_id %prec EMPTY { $$ = build_new ($2, $3.t, NULL_TREE, $1); check_for_new_type ("new", $3); } | new new_placement new_type_id new_initializer { $$ = build_new ($2, $3.t, $4, $1); check_for_new_type ("new", $3); } | new '(' type_id ')' %prec EMPTY { $$ = build_new (NULL_TREE, groktypename($3.t), NULL_TREE, $1); check_for_new_type ("new", $3); } | new '(' type_id ')' new_initializer { $$ = build_new (NULL_TREE, groktypename($3.t), $5, $1); check_for_new_type ("new", $3); } | new new_placement '(' type_id ')' %prec EMPTY { $$ = build_new ($2, groktypename($4.t), NULL_TREE, $1); check_for_new_type ("new", $4); } | new new_placement '(' type_id ')' new_initializer { $$ = build_new ($2, groktypename($4.t), $6, $1); check_for_new_type ("new", $4); } | 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; } | REALPART cast_expr %prec UNARY { $$ = build_x_unary_op (REALPART_EXPR, $2); } | IMAGPART cast_expr %prec UNARY { $$ = build_x_unary_op (IMAGPART_EXPR, $2); } ;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.t); $$ = 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.t = tree_cons (NULL_TREE, $2.t, void_list_node); TREE_PARMLIST ($2.t) = 1; $$ = make_call_declarator (NULL_TREE, $2.t, NULL_TREE, NULL_TREE); check_for_new_type ("cast", $2); } | regcast_or_absdcl '(' type_id ')' %prec EMPTY { $3.t = tree_cons (NULL_TREE, $3.t, void_list_node); TREE_PARMLIST ($3.t) = 1; $$ = make_call_declarator ($$, $3.t, NULL_TREE, NULL_TREE); check_for_new_type ("cast", $3); } ;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_x_modify_expr ($$, NOP_EXPR, $3); if ($$ != error_mark_node) C_SET_EXP_ORIGINAL_CODE ($$, MODIFY_EXPR); } | expr_no_commas ASSIGN expr_no_commas { $$ = build_x_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.t); $$ = build_m_component_ref ($$, build_c_cast (type, $5)); } | object primary_no_id %prec UNARY { $$ = build_m_component_ref ($$, $2); }*/ ;notype_unqualified_id: '~' see_typename identifier { $$ = build_parse_node (BIT_NOT_EXPR, $3); } | template_id | operator_name | IDENTIFIER | PTYPENAME | NSNAME %prec EMPTY ;template_id: PFUNCNAME '<' template_arg_list template_close_bracket { $$ = lookup_template_function ($1, $3); } | PFUNCNAME '<' template_close_bracket { $$ = lookup_template_function ($1, NULL_TREE); } | operator_name '<' template_arg_list template_close_bracket { $$ = lookup_template_function (do_identifier ($1, 1), $3); } | operator_name '<' template_close_bracket { $$ = lookup_template_function (do_identifier ($1, 1), NULL_TREE); } ;object_template_id: TEMPLATE identifier '<' template_arg_list template_close_bracket { $$ = lookup_template_function ($2, $4); } | TEMPLATE PFUNCNAME '<' template_arg_list template_close_bracket { $$ = lookup_template_function (DECL_NAME ($2), $4); } | TEMPLATE operator_name '<' template_arg_list template_close_bracket { $$ = lookup_template_function (DECL_NAME ($2), $4); } ;unqualified_id: notype_unqualified_id | TYPENAME | SELFNAME ;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); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -