📄 cp-parse.y
字号:
/* YACC parser for C++ syntax. Copyright (C) 1988, 1989 Free Software Foundation, Inc. Hacked by Michael Tiemann (tiemann@cygnus.com)This file is part of GNU CC.GNU CC is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2, or (at your option)any later version.GNU CC is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with GNU CC; see the file COPYING. If not, write tothe Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. *//* This grammar is based on the GNU CC grammar. *//* Note: Bison automatically applies a default action of "$$ = $1" for all derivations; this is applied before the explicit action, if one is given. Keep this in mind when reading the actions. *//* Also note: this version contains experimental exception handling features. They could break, change, disappear, or otherwise exhibit volatile behavior. Don't depend on me (Michael Tiemann) to protect you from any negative impact this may have on your professional, personal, or spiritual life. NEWS FLASH: This version now supports the exception handling syntax of Stroustrup's 2nd edition, if -fansi-exceptions is given. THIS IS WORK IN PROGRESS!!! The type of the 'throw' and the 'catch' much match EXACTLY (no inheritance support or coercions). Also, throw-specifications of functions don't work. Destructors aren't called correctly. Etc, etc. --Per Bothner. */%{#if defined(GATHER_STATISTICS) || defined(SPEW_DEBUG)#undef YYDEBUG#define YYDEBUG 1#endif#include "config.h"#include <stdio.h>#include <errno.h>#include "tree.h"#include "input.h"#include "flags.h"#include "cp-lex.h"#include "cp-tree.h"extern tree void_list_node;extern struct obstack permanent_obstack;#ifndef errnoextern int errno;#endifextern int end_of_file;void yyerror ();/* Like YYERROR but do call yyerror. */#define YYERROR1 { yyerror ("syntax error"); YYERROR; }static void position_after_white_space ();/* Contains error message to give if user tries to declare a variable where one does not belong. */static char *stmt_decl_msg = 0;/* Nonzero if we have an `extern "C"' acting as an extern specifier. */int have_extern_spec;int used_extern_spec;void yyhook ();/* Cons up an empty parameter list. */#ifdef __GNUC____inline#endifstatic treeempty_parms (){ tree parms; if (strict_prototype) parms = void_list_node; else parms = NULL_TREE; return parms;}%}%start program%union {long itype; tree ttype; char *strtype; enum tree_code code; }/* All identifiers that are not reserved words and are not declared typedefs in the current block */%token IDENTIFIER/* All identifiers that are declared typedefs in the current block. In some contexts, they are treated just like IDENTIFIER, but they can also serve as typespecs in declarations. */%token TYPENAME/* Qualified identifiers that end in a TYPENAME. */%token SCOPED_TYPENAME/* Reserved words that specify storage class. yylval contains an IDENTIFIER_NODE which indicates which one. */%token SCSPEC/* Reserved words that specify type. yylval contains an IDENTIFIER_NODE which indicates which one. */%token TYPESPEC/* Reserved words that qualify type: "const" or "volatile". yylval contains an IDENTIFIER_NODE which indicates which one. */%token TYPE_QUAL/* Character or numeric constants. yylval is the node for the constant. */%token CONSTANT/* String constants in raw form. yylval is a STRING_CST node. */%token STRING/* "...", used for functions with variable arglists. */%token ELLIPSIS/* the reserved words *//* SCO include files test "ASM", so use something else. */%token SIZEOF ENUM /* STRUCT UNION */ IF ELSE WHILE DO FOR SWITCH CASE DEFAULT%token BREAK CONTINUE RETURN GOTO ASM_KEYWORD TYPEOF ALIGNOF HEADOF CLASSOF%token ATTRIBUTE EXTENSION LABEL/* the reserved words... C++ extensions */%token <ttype> AGGR%token <itype> VISSPEC%token DELETE NEW OVERLOAD THIS OPERATOR%token DYNAMIC POINTSAT_LEFT_RIGHT LEFT_RIGHT TEMPLATE%token <itype> SCOPE/* Special token created by the lexer to separate TYPENAME from an ABSDCL. This allows us to parse `foo (*pf)()'. */%token START_DECLARATOR/* Define the operator tokens and their precedences. The value is an integer because, if used, it is the tree code to use in the expression made from the operator. */%left EMPTY /* used to resolve s/r with epsilon *//* Add precedence rules to solve dangling else s/r conflict */%nonassoc IF%nonassoc ELSE%left IDENTIFIER TYPENAME TYPENAME_COLON SCSPEC TYPESPEC TYPE_QUAL ENUM AGGR%left '{' ','%right <code> ASSIGN '='%right <code> '?' ':' RANGE%left <code> OROR%left <code> ANDAND%left <code> '|'%left <code> '^'%left <code> '&'%left <code> MIN_MAX%left <code> EQCOMPARE%left <code> ARITHCOMPARE '<' '>'%left <code> LSHIFT RSHIFT%left <code> '+' '-'%left <code> '*' '/' '%'%right <code> UNARY PLUSPLUS MINUSMINUS%left HYPERUNARY%left <ttype> PAREN_STAR_PAREN LEFT_RIGHT%left <code> POINTSAT POINTSAT_STAR '.' DOT_STAR '(' '['%right SCOPE /* C++ extension */%nonassoc NEW DELETE RAISE RAISES RERAISE TRY EXCEPT CATCH THROW%nonassoc ANSI_TRY ANSI_THROW%right DYNAMIC%type <code> unop%type <ttype> identifier IDENTIFIER TYPENAME CONSTANT expr nonnull_exprlist%type <ttype> optional_identifier%type <ttype> expr_no_commas cast_expr unary_expr primary string STRING%type <ttype> typed_declspecs reserved_declspecs%type <ttype> typed_typespecs reserved_typespecquals%type <ttype> declmods typespec typespecqual_reserved%type <ttype> SCSPEC TYPESPEC TYPE_QUAL nonempty_type_quals maybe_type_qual%type <itype> initdecls notype_initdecls initdcl /* C++ modification */%type <ttype> init initlist maybeasm%type <ttype> asm_operands nonnull_asm_operands asm_operand asm_clobbers%type <ttype> maybe_attribute attribute_list attrib%type <ttype> abs_member_declarator after_type_member_declarator%type <ttype> compstmt except_stmts ansi_except_stmts%type <ttype> declarator notype_declarator after_type_declarator%type <ttype> structsp opt.component_decl_list component_decl_list component_decl components component_declarator%type <ttype> enumlist enumerator%type <ttype> typename absdcl absdcl1 type_quals abs_or_notype_decl%type <ttype> xexpr see_typename parmlist parms parm bad_parm%type <ttype> identifiers_or_typenames/* C++ extensions */%type <ttype> typename_scope%token <ttype> TYPENAME_COLON TYPENAME_ELLIPSIS%token <ttype> PTYPENAME SCOPED_TYPENAME%token <ttype> PRE_PARSED_FUNCTION_DECL EXTERN_LANG_STRING ALL%token <ttype> PRE_PARSED_CLASS_DECL%type <ttype> fn.def1 /* Not really! */%type <ttype> fn.def2 return_id%type <ttype> named_class_head named_class_head_sans_basetype%type <ttype> unnamed_class_head%type <ttype> class_head base_class_list%type <itype> base_class_visibility_list%type <ttype> base_class maybe_base_class_list base_class.1%type <ttype> after_type_declarator_no_typename%type <ttype> maybe_raises raise_identifier raise_identifiers ansi_raise_identifier ansi_raise_identifiers%type <ttype> component_declarator0 scoped_id scoped_typename scoped_base_class%type <ttype> forhead.1 identifier_or_opname operator_name%type <ttype> new delete object object_star aggr/* %type <ttype> primary_no_id */%type <ttype> nonmomentary_expr%type <itype> forhead.2 initdcl0 notype_initdcl0 member_init_list%type <itype> .scope try ansi_try%type <ttype> template_header template_parm_list template_parm%type <ttype> template_type template_arg_list template_arg%type <ttype> template_instantiation template_type_name tmpl.1 tmpl.2%type <ttype> template_instantiate_once template_instantiate_some%type <itype> fn_tmpl_end/* %type <itype> try_for_typename *//* in order to recognize aggr tags as defining and thus shadowing. */%token TYPENAME_DEFN IDENTIFIER_DEFN PTYPENAME_DEFN%type <ttype> named_class_head_sans_basetype_defn %type <ttype> identifier_defn IDENTIFIER_DEFN TYPENAME_DEFN PTYPENAME_DEFN%type <strtype> .pushlevel/* cp-spew.c depends on this being the last token. Define any new tokens before this one! */%token END_OF_SAVED_INPUT%{/* List of types and structure classes of the current declaration. */static tree current_declspecs;/* When defining an aggregate, this is the most recent one being defined. */static tree current_aggr;/* 1 if we explained undeclared var errors. */int undeclared_variable_notice;/* Tell yyparse how to print a token's value, if yydebug is set. */#define YYPRINT(FILE,YYCHAR,YYLVAL) yyprint(FILE,YYCHAR,YYLVAL)extern void yyprint ();%}%%program: /* empty */ | extdefs { finish_file (); } ;/* the reason for the strange actions in this rule is so that notype_initdecls when reached via datadef can find a valid list of type and sc specs in $0. */extdefs: { $<ttype>$ = NULL_TREE; } extdef {$<ttype>$ = NULL_TREE; } | extdefs extdef {$<ttype>$ = NULL_TREE; } ;.hush_warning: { have_extern_spec = 1; used_extern_spec = 0; $<ttype>$ = NULL_TREE; } ;.warning_ok: { have_extern_spec = 0; } ;extdef: fndef { if (pending_inlines) do_pending_inlines (); } | datadef { if (pending_inlines) do_pending_inlines (); } | template_def { if (pending_inlines) do_pending_inlines (); } | overloaddef | ASM_KEYWORD '(' string ')' ';' { if (pedantic) pedwarn ("ANSI C++ forbids use of `asm' keyword"); if (TREE_CHAIN ($3)) $3 = combine_strings ($3); assemble_asm ($3); } | extern_lang_string '{' extdefs '}' { pop_lang_context (); } | extern_lang_string '{' '}' { pop_lang_context (); } | extern_lang_string .hush_warning fndef .warning_ok { if (pending_inlines) do_pending_inlines (); pop_lang_context (); } | extern_lang_string .hush_warning datadef .warning_ok { if (pending_inlines) do_pending_inlines (); pop_lang_context (); } ;extern_lang_string: EXTERN_LANG_STRING { push_lang_context ($1); } ;template_header: TEMPLATE '<' { begin_template_parm_list (); } template_parm_list '>' { $$ = end_template_parm_list ($4); } ;template_parm_list: template_parm { $$ = process_template_parm (0, $1); } | template_parm_list ',' template_parm { $$ = process_template_parm ($1, $3); } ;template_parm: /* The following rules introduce a new reduce/reduce conflict: they are valid prefixes for a `structsp', which means they could match a nameless parameter. By putting them before the `parm' rule, we get their match before considering them nameless parameter declarations. */ aggr identifier { if ($1 != class_type_node) error ("template type parameter must use keyword `class'"); $$ = build_tree_list ($2, NULL_TREE); } | aggr identifier_defn ':' base_class.1 { if ($1 != class_type_node) error ("template type parameter must use keyword `class'"); warning ("restricted template type parameters not yet implemented"); $$ = build_tree_list ($2, $4); } | aggr TYPENAME_COLON base_class.1 { if ($1 != class_type_node) error ("template type parameter must use keyword `class'"); warning ("restricted template type parameters not yet implemented"); $$ = build_tree_list ($2, $3); } | parm ;overloaddef: OVERLOAD ov_identifiers ';'ov_identifiers: IDENTIFIER { declare_overloaded ($1); } | ov_identifiers ',' IDENTIFIER { declare_overloaded ($3); } ; template_def: /* Class template declarations go here; they aren't normal class declarations, because we can't process the bodies yet. */ template_header named_class_head_sans_basetype '{' { yychar = '{'; goto template1; } ';' | template_header named_class_head_sans_basetype_defn '{' { yychar = '{'; goto template1; } ';' | template_header named_class_head_sans_basetype ':' { yychar = ':'; goto template1; } ';' | template_header named_class_head_sans_basetype_defn ':' { yychar = ':'; template1: if (current_aggr == exception_type_node) error ("template type must define an aggregate or union"); /* Maybe pedantic warning for union? How about an enum? :-) */ end_template_decl ($1, $2, current_aggr); reinit_parse_for_template (yychar, $1, $2); yychar = YYEMPTY; } ';' | template_header named_class_head_sans_basetype ';' { end_template_decl ($1, $2, current_aggr); /* declare $2 as template name with $1 parm list */ } | template_header named_class_head_sans_basetype_defn ';' { end_template_decl ($1, $2, current_aggr); /* declare $2 as template name with $1 parm list */ } | template_header /* notype_initdcl0 ';' */ notype_declarator maybe_raises maybeasm maybe_attribute fn_tmpl_end { tree d; int momentary; momentary = suspend_momentary (); d = start_decl ($2, /*current_declspecs*/0, 0, $3); cplus_decl_attributes (d, $5); finish_decl (d, NULL_TREE, $4, 0); end_template_decl ($1, d, 0); if ($6 != ';') reinit_parse_for_template ($6, $1, d); resume_momentary (momentary); } | template_header typed_declspecs /*initdcl0*/ declarator maybe_raises maybeasm maybe_attribute fn_tmpl_end { tree d; int momentary; current_declspecs = $2; momentary = suspend_momentary ();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -