📄 parse.y
字号:
| '(' expr_or_declarator ')' { $$ = $2; } ;notype_template_declarator: IDENTIFIER '<' template_arg_list template_close_bracket { $$ = lookup_template_function ($1, $3); } | NSNAME '<' template_arg_list template_close_bracket { $$ = lookup_template_function ($1, $3); } ; direct_notype_declarator: complex_direct_notype_declarator | notype_unqualified_id | notype_template_declarator | '(' 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 (TREE_CODE ($$) != TEMPLATE_ID_EXPR) $$ = do_identifier ($$, 1); } | CONSTANT | boolean.literal | string { if (processing_template_decl) push_obstacks (&permanent_obstack, &permanent_obstack); $$ = combine_strings ($$); if (processing_template_decl) pop_obstacks (); } | '(' expr ')' { char class; $$ = $2; class = TREE_CODE_CLASS (TREE_CODE ($$)); if (class == 'e' || class == '1' || class == '2' || class == '<') /* This inhibits warnings in truthvalue_conversion. */ C_SET_EXP_ORIGINAL_CODE ($$, ERROR_MARK); } | '(' expr_or_declarator ')' { char class; $$ = reparse_decl_as_expr (NULL_TREE, $2); class = TREE_CODE_CLASS (TREE_CODE ($$)); if (class == 'e' || class == '1' || class == '2' || class == '<') /* This inhibits warnings in truthvalue_conversion. */ C_SET_EXP_ORIGINAL_CODE ($$, ERROR_MARK); } | '(' error ')' { $$ = error_mark_node; } | '(' { if (current_function_decl == 0) { error ("braced-group within expression allowed only inside a function"); YYERROR; } keep_next_level (); $<ttype>$ = expand_start_stmt_expr (); } compstmt ')' { tree rtl_exp; if (pedantic) pedwarn ("ANSI C++ forbids braced-groups within expressions"); rtl_exp = expand_end_stmt_expr ($<ttype>2); /* The statements have side effects, so the group does. */ TREE_SIDE_EFFECTS (rtl_exp) = 1; if (TREE_CODE ($3) == BLOCK) { /* Make a BIND_EXPR for the BLOCK already made. */ $$ = build (BIND_EXPR, TREE_TYPE (rtl_exp), NULL_TREE, rtl_exp, $3); /* Remove the block from the tree at this point. It gets put back at the proper place when the BIND_EXPR is expanded. */ delete_block ($3); } else $$ = $3; } | primary '(' nonnull_exprlist ')' { $$ = build_x_function_call ($1, $3, current_class_ref); if (TREE_CODE ($$) == CALL_EXPR && TREE_TYPE ($$) != void_type_node) $$ = require_complete_type ($$); } | primary LEFT_RIGHT { $$ = build_x_function_call ($$, NULL_TREE, current_class_ref); if (TREE_CODE ($$) == CALL_EXPR && TREE_TYPE ($$) != void_type_node) $$ = require_complete_type ($$); } | primary '[' expr ']' { $$ = grok_array_decl ($$, $3); } | primary PLUSPLUS { /* If we get an OFFSET_REF, turn it into what it really means (e.g., a COMPONENT_REF). This way if we've got, say, a reference to a static member that's being operated on, we don't end up trying to find a member operator for the class it's in. */ if (TREE_CODE ($$) == OFFSET_REF) $$ = resolve_offset_ref ($$); $$ = build_x_unary_op (POSTINCREMENT_EXPR, $$); } | primary MINUSMINUS { if (TREE_CODE ($$) == OFFSET_REF) $$ = resolve_offset_ref ($$); $$ = build_x_unary_op (POSTDECREMENT_EXPR, $$); } /* C++ extensions */ | THIS { if (current_class_ptr) {#ifdef WARNING_ABOUT_CCD TREE_USED (current_class_ptr) = 1;#endif $$ = current_class_ptr; } else if (current_function_decl && DECL_STATIC_FUNCTION_P (current_function_decl)) { error ("`this' is unavailable for static member functions"); $$ = error_mark_node; } else { if (current_function_decl) error ("invalid use of `this' in non-member function"); else error ("invalid use of `this' at top level"); $$ = error_mark_node; } } | CV_QUALIFIER '(' nonnull_exprlist ')' { tree type; tree id = $$; /* This is a C cast in C++'s `functional' notation. */ if ($3 == error_mark_node) { $$ = error_mark_node; break; }#if 0 if ($3 == NULL_TREE) { error ("cannot cast null list to type `%s'", IDENTIFIER_POINTER (TYPE_NAME (id))); $$ = error_mark_node; break; }#endif#if 0 /* type is not set! (mrs) */ if (type == error_mark_node) $$ = error_mark_node; else#endif { if (id == ridpointers[(int) RID_CONST]) type = build_type_variant (integer_type_node, 1, 0); else if (id == ridpointers[(int) RID_VOLATILE]) type = build_type_variant (integer_type_node, 0, 1);#if 0 /* should not be able to get here (mrs) */ else if (id == ridpointers[(int) RID_FRIEND]) { error ("cannot cast expression to `friend' type"); $$ = error_mark_node; break; }#endif else my_friendly_abort (79); $$ = build_c_cast (type, build_compound_expr ($3)); } } | functional_cast | DYNAMIC_CAST '<' type_id '>' '(' expr ')' { tree type = groktypename ($3.t); check_for_new_type ("dynamic_cast", $3); $$ = build_dynamic_cast (type, $6); } | STATIC_CAST '<' type_id '>' '(' expr ')' { tree type = groktypename ($3.t); check_for_new_type ("static_cast", $3); $$ = build_static_cast (type, $6); } | REINTERPRET_CAST '<' type_id '>' '(' expr ')' { tree type = groktypename ($3.t); check_for_new_type ("reinterpret_cast", $3); $$ = build_reinterpret_cast (type, $6); } | CONST_CAST '<' type_id '>' '(' expr ')' { tree type = groktypename ($3.t); check_for_new_type ("const_cast", $3); $$ = build_const_cast (type, $6); } | TYPEID '(' expr ')' { $$ = build_x_typeid ($3); } | TYPEID '(' type_id ')' { tree type = groktypename ($3.t); check_for_new_type ("typeid", $3); $$ = get_typeid (TYPE_MAIN_VARIANT (type)); } | global_scope IDENTIFIER { $$ = do_scoped_id ($2, 1); } | global_scope operator_name { got_scope = NULL_TREE; if (TREE_CODE ($2) == IDENTIFIER_NODE) $$ = do_scoped_id ($2, 1); else $$ = $2; } | overqualified_id %prec HYPERUNARY { $$ = build_offset_ref (OP0 ($$), OP1 ($$)); } | overqualified_id '(' nonnull_exprlist ')' { if (processing_template_decl) $$ = build_min_nt (CALL_EXPR, copy_to_permanent ($1), $3, NULL_TREE); else $$ = build_member_call (OP0 ($$), OP1 ($$), $3); } | overqualified_id LEFT_RIGHT { if (processing_template_decl) $$ = build_min_nt (CALL_EXPR, copy_to_permanent ($1), NULL_TREE, NULL_TREE); else $$ = build_member_call (OP0 ($$), OP1 ($$), NULL_TREE); } | object object_template_id %prec UNARY { $$ = build_x_component_ref ($$, $2, NULL_TREE, 1); } | object object_template_id '(' nonnull_exprlist ')' { $$ = build_method_call ($1, $2, $4, NULL_TREE, LOOKUP_NORMAL); } | object object_template_id LEFT_RIGHT { $$ = build_method_call ($1, $2, NULL_TREE, NULL_TREE, LOOKUP_NORMAL); } | object unqualified_id %prec UNARY { $$ = build_x_component_ref ($$, $2, NULL_TREE, 1); } | object overqualified_id %prec UNARY { if (processing_template_decl) $$ = build_min_nt (COMPONENT_REF, $1, copy_to_permanent ($2)); else $$ = build_object_ref ($$, OP0 ($2), OP1 ($2)); } | object unqualified_id '(' nonnull_exprlist ')' {#if 0 /* This is a future direction of this code, but because build_x_function_call cannot always undo what is done in build_component_ref entirely yet, we cannot do this. */ $$ = build_x_function_call (build_component_ref ($$, $2, NULL_TREE, 1), $4, current_class_ref); if (TREE_CODE ($$) == CALL_EXPR && TREE_TYPE ($$) != void_type_node) $$ = require_complete_type ($$);#else $$ = build_method_call ($$, $2, $4, NULL_TREE, LOOKUP_NORMAL);#endif } | object unqualified_id LEFT_RIGHT {#if 0 /* This is a future direction of this code, but because build_x_function_call cannot always undo what is done in build_component_ref entirely yet, we cannot do this. */ $$ = build_x_function_call (build_component_ref ($$, $2, NULL_TREE, 1), NULL_TREE, current_class_ref); if (TREE_CODE ($$) == CALL_EXPR && TREE_TYPE ($$) != void_type_node) $$ = require_complete_type ($$);#else $$ = build_method_call ($$, $2, NULL_TREE, NULL_TREE, LOOKUP_NORMAL);#endif } | object overqualified_id '(' nonnull_exprlist ')' { if (IS_SIGNATURE (OP0 ($2))) { warning ("signature name in scope resolution ignored"); $$ = build_method_call ($$, OP1 ($2), $4, NULL_TREE, LOOKUP_NORMAL); } else $$ = build_scoped_method_call ($$, OP0 ($2), OP1 ($2), $4); } | object overqualified_id LEFT_RIGHT { if (IS_SIGNATURE (OP0 ($2))) { warning ("signature name in scope resolution ignored"); $$ = build_method_call ($$, OP1 ($2), NULL_TREE, NULL_TREE, LOOKUP_NORMAL); } else $$ = build_scoped_method_call ($$, OP0 ($2), OP1 ($2), NULL_TREE); } /* p->int::~int() is valid -- 12.4 */ | object '~' TYPESPEC LEFT_RIGHT { if (IDENTIFIER_GLOBAL_VALUE ($3) && (TREE_CODE (TREE_TYPE ($1)) != TREE_CODE (TREE_TYPE (IDENTIFIER_GLOBAL_VALUE ($3))))) cp_error ("`%E' is not of type `%T'", $1, $3); $$ = cp_convert (void_type_node, $1); } | object TYPESPEC SCOPE '~' TYPESPEC LEFT_RIGHT { if ($2 != $5) cp_error ("destructor specifier `%T::~%T()' must have matching names", $2, $5); if (TREE_CODE (TREE_TYPE ($1)) != TREE_CODE (TREE_TYPE (IDENTIFIER_GLOBAL_VALUE ($2)))) cp_error ("`%E' is not of type `%T'", $1, $2); $$ = cp_convert (void_type_node, $1); } | object error { $$ = error_mark_node; } ;/* Not needed for now.primary_no_id: '(' expr ')' { $$ = $2; } | '(' error ')' { $$ = error_mark_node; } | '(' { if (current_function_decl == 0) { error ("braced-group within expression allowed only inside a function"); YYERROR; } $<ttype>$ = expand_start_stmt_expr (); } compstmt ')' { if (pedantic) pedwarn ("ANSI C++ forbids braced-groups within expressions"); $$ = expand_end_stmt_expr ($<ttype>2); } | primary_no_id '(' nonnull_exprlist ')' { $$ = build_x_function_call ($$, $3, current_class_ref); } | primary_no_id LEFT_RIGHT { $$ = build_x_function_call ($$, NULL_TREE, current_class_ref); } | primary_no_id '[' expr ']' { goto do_array; } | primary_no_id PLUSPLUS { $$ = build_x_unary_op (POSTINCREMENT_EXPR, $$); } | primary_no_id MINUSMINUS { $$ = build_x_unary_op (POSTDECREMENT_EXPR, $$); } | SCOPE IDENTIFIER { goto do_scoped_id; } | SCOPE operator_name { if (TREE_CODE ($2) == IDENTIFIER_NODE) goto do_scoped_id; goto do_scoped_operator; } ;*/new: NEW { $$ = 0; } | global_scope NEW { got_scope = NULL_TREE; $$ = 1; } ;delete: DELETE { $$ = 0; } | global_scope delete { got_scope = NULL_TREE; $$ = 1; } ;boolean.literal: CXX_TRUE { $$ = boolean_true_node; } | CXX_FALSE { $$ = boolean_false_node; } ;/* Produces a STRING_CST with perhaps more STRING_CSTs chained onto it. */string: STRING | string STRING { $$ = chainon ($$, $2); } ;nodecls: /* empty */ { if (! current_function_parms_stored) store_parm_decls (); setup_vtbl_ptr (); /* Always keep the BLOCK node associated with the outermost pair of curly braces of a function. These are needed for correct operation of dwarfout.c. */ keep_next_level (); } ;object: primary '.' { got_object = TREE_TYPE ($$); } | primary POINTSAT { $$ = build_x_arrow ($$); got_object = TREE_TYPE ($$); } ;decl: typespec initdecls ';' { resume_momentary ($2); if ($1.t && IS_AGGR_TYPE_CODE (TREE_CODE ($1.t))) note_got_semicolon ($1.t); } | typed_declspecs initdecls ';' { resume_momentary ($2); note_list_got_semicolon ($1.t); } | declmods notype_initdecls ';' { resume_momentary ($2); } | typed_declspecs ';' { shadow_tag ($1.t); note_list_got_semicolon ($1.t); } | declmods ';' { warning ("empty declaration"); } | extension decl { pedantic = $<itype>1; } ;/* Any kind of declarator (thus, all declarators allowed after an explicit typespec). */declarator: after_type_declarator %prec EMPTY
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -