⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 c-parse.y

📁 这是完整的gcc源代码
💻 Y
📖 第 1 页 / 共 5 页
字号:
	| primary '[' expr ']'   %prec '.'		{ $$ = build_array_ref ($1, $3); }	| primary '.' identifier		{ $$ = build_component_ref ($1, $3); }	| primary POINTSAT identifier		{ $$ = build_component_ref (build_indirect_ref ($1, "->"), $3); }	| primary PLUSPLUS		{ $$ = build_unary_op (POSTINCREMENT_EXPR, $1, 0); }	| primary MINUSMINUS		{ $$ = build_unary_op (POSTDECREMENT_EXPR, $1, 0); }	;/* Produces a STRING_CST with perhaps more STRING_CSTs chained onto it.  */string:	  STRING	| string STRING		{ $$ = chainon ($1, $2); }	;xdecls:	/* empty */	| decls	;decls:	decl	| errstmt	| decls decl	| decl errstmt	;/* records the type and storage class specs to use for processing   the declarators that follow.   Maintains a stack of outer-level values of current_declspecs,   for the sake of parm declarations nested in function declarators.  */setspecs: /* empty */		{ $$ = suspend_momentary ();		  declspec_stack = tree_cons (0, current_declspecs,					      declspec_stack);		  current_declspecs = $<ttype>0; }	;decl:	typed_declspecs setspecs initdecls ';'		{ current_declspecs = TREE_VALUE (declspec_stack);		  declspec_stack = TREE_CHAIN (declspec_stack);		  resume_momentary ($2); }	| declmods setspecs notype_initdecls ';'		{ current_declspecs = TREE_VALUE (declspec_stack);		  declspec_stack = TREE_CHAIN (declspec_stack);		  resume_momentary ($2); }	| typed_declspecs ';'		{ shadow_tag ($1); }	| declmods ';'		{ warning ("empty declaration"); }	;/* Declspecs which contain at least one type specifier or typedef name.   (Just `const' or `volatile' is not enough.)   A typedef'd name following these is taken as a name to be declared.  */typed_declspecs:	  typespec reserved_declspecs		{ $$ = tree_cons (NULL_TREE, $1, $2); }	| declmods typespec reserved_declspecs		{ $$ = chainon ($3, tree_cons (NULL_TREE, $2, $1)); }	;reserved_declspecs:  /* empty */		{ $$ = NULL_TREE; }	| reserved_declspecs typespecqual_reserved		{ $$ = tree_cons (NULL_TREE, $2, $1); }	| reserved_declspecs SCSPEC		{ $$ = tree_cons (NULL_TREE, $2, $1); }	;/* List of just storage classes and type modifiers.   A declaration can start with just this, but then it cannot be used   to redeclare a typedef-name.  */declmods:	  TYPE_QUAL		{ $$ = tree_cons (NULL_TREE, $1, NULL_TREE); }	| SCSPEC		{ $$ = tree_cons (NULL_TREE, $1, NULL_TREE); }	| declmods TYPE_QUAL		{ $$ = tree_cons (NULL_TREE, $2, $1); }	| declmods SCSPEC		{ $$ = tree_cons (NULL_TREE, $2, $1); }	;/* Used instead of declspecs where storage classes are not allowed   (that is, for typenames and structure components).   Don't accept a typedef-name if anything but a modifier precedes it.  */typed_typespecs:	  typespec reserved_typespecquals		{ $$ = tree_cons (NULL_TREE, $1, $2); }	| nonempty_type_quals typespec reserved_typespecquals		{ $$ = chainon ($3, tree_cons (NULL_TREE, $2, $1)); }	;reserved_typespecquals:  /* empty */		{ $$ = NULL_TREE; }	| reserved_typespecquals typespecqual_reserved		{ $$ = tree_cons (NULL_TREE, $2, $1); }	;/* A typespec (but not a type qualifier).   Once we have seen one of these in a declaration,   if a typedef name appears then it is being redeclared.  */typespec: TYPESPEC	| structsp	| TYPENAME	| TYPEOF '(' expr ')'		{ $$ = TREE_TYPE ($3); }	| TYPEOF '(' typename ')'		{ $$ = groktypename ($3); }	;/* A typespec that is a reserved word, or a type qualifier.  */typespecqual_reserved: TYPESPEC	| TYPE_QUAL	| structsp	;initdecls:	initdcl	| initdecls ',' initdcl	;notype_initdecls:	notype_initdcl	| notype_initdecls ',' initdcl	;maybeasm:	  /* empty */		{ $$ = NULL_TREE; }	| ASM '(' string ')'		{ if (TREE_CHAIN ($3)) $3 = combine_strings ($3);		  $$ = $3;		}	;initdcl:	  declarator maybeasm maybe_attribute '='		{ $<ttype>$ = start_decl ($1, current_declspecs, 1); }	  init/* Note how the declaration of the variable is in effect while its init is parsed! */		{ finish_decl ($<ttype>5, $6, $2); }	| declarator maybeasm maybe_attribute		{ tree d = start_decl ($1, current_declspecs, 0);		  finish_decl (d, NULL_TREE, $2); }	;notype_initdcl:	  notype_declarator maybeasm maybe_attribute '='		{ $<ttype>$ = start_decl ($1, current_declspecs, 1); }	  init/* Note how the declaration of the variable is in effect while its init is parsed! */		{ finish_decl ($<ttype>5, $6, $2); }	| notype_declarator maybeasm maybe_attribute		{ tree d = start_decl ($1, current_declspecs, 0);		  finish_decl (d, NULL_TREE, $2); }	;/* the * rules are dummies to accept the Apollo extended syntax   so that the header files compile. */maybe_attribute:    /* empty */	{ $$ = NULL_TREE; }    | ATTRIBUTE '(' '(' attribute_list ')' ')'        { $$ = $4; }    ;attribute_list    : attrib    | attribute_list ',' attrib    ;attrib    : IDENTIFIER	{ warning ("`%s' attribute directive ignored",		   IDENTIFIER_POINTER ($1));	  $$ = $1; }    | IDENTIFIER '(' CONSTANT ')'	{ /* if not "aligned(1)", then issue warning */	  if (strcmp (IDENTIFIER_POINTER ($1), "aligned") != 0	      || TREE_CODE ($3) != INTEGER_CST	      || TREE_INT_CST_LOW ($3) != 1)	    warning ("`%s' attribute directive ignored",		     IDENTIFIER_POINTER ($1));	  $$ = $1; }    | IDENTIFIER '(' identifiers ')'	{ warning ("`%s' attribute directive ignored",		   IDENTIFIER_POINTER ($1));	  $$ = $1; }    ;init:	expr_no_commas	| '{' '}'		{ $$ = build_nt (CONSTRUCTOR, NULL_TREE, NULL_TREE);		  if (pedantic)		    warning ("ANSI C forbids empty initializer braces"); }	| '{' initlist '}'		{ $$ = build_nt (CONSTRUCTOR, NULL_TREE, nreverse ($2)); }	| '{' initlist ',' '}'		{ $$ = build_nt (CONSTRUCTOR, NULL_TREE, nreverse ($2)); }	| error		{ $$ = NULL_TREE; }	;/* This chain is built in reverse order,   and put in forward order where initlist is used.  */initlist:	  init		{ $$ = build_tree_list (NULL_TREE, $1); }	| initlist ',' init		{ $$ = tree_cons (NULL_TREE, $3, $1); }	;/* Any kind of declarator (thus, all declarators allowed   after an explicit typespec).  */declarator:	  after_type_declarator	| notype_declarator	;/* A declarator that is allowed only after an explicit typespec.  */after_type_declarator:	  '(' after_type_declarator ')'		{ $$ = $2; }	| after_type_declarator '(' parmlist_or_identifiers  %prec '.'		{ $$ = build_nt (CALL_EXPR, $1, $3, NULL_TREE); }/*	| after_type_declarator '(' error ')'  %prec '.'		{ $$ = build_nt (CALL_EXPR, $1, NULL_TREE, NULL_TREE);		  poplevel (0, 0, 0); }  */	| after_type_declarator '[' expr ']'  %prec '.'		{ $$ = build_nt (ARRAY_REF, $1, $3); }	| after_type_declarator '[' ']'  %prec '.'		{ $$ = build_nt (ARRAY_REF, $1, NULL_TREE); }	| '*' type_quals after_type_declarator  %prec UNARY		{ $$ = make_pointer_declarator ($2, $3); }	| TYPENAME	;/* Kinds of declarator that can appear in a parameter list   in addition to notype_declarator.  This is like after_type_declarator   but does not allow a typedef name in parentheses as an identifier   (because it would conflict with a function with that typedef as arg).  */parm_declarator:	  parm_declarator '(' parmlist_or_identifiers  %prec '.'		{ $$ = build_nt (CALL_EXPR, $1, $3, NULL_TREE); }/*	| parm_declarator '(' error ')'  %prec '.'		{ $$ = build_nt (CALL_EXPR, $1, NULL_TREE, NULL_TREE);		  poplevel (0, 0, 0); }  */	| parm_declarator '[' expr ']'  %prec '.'		{ $$ = build_nt (ARRAY_REF, $1, $3); }	| parm_declarator '[' ']'  %prec '.'		{ $$ = build_nt (ARRAY_REF, $1, NULL_TREE); }	| '*' type_quals parm_declarator  %prec UNARY		{ $$ = make_pointer_declarator ($2, $3); }	| TYPENAME	;/* A declarator allowed whether or not there has been   an explicit typespec.  These cannot redeclare a typedef-name.  */notype_declarator:	  notype_declarator '(' parmlist_or_identifiers  %prec '.'		{ $$ = build_nt (CALL_EXPR, $1, $3, NULL_TREE); }/*	| notype_declarator '(' error ')'  %prec '.'		{ $$ = build_nt (CALL_EXPR, $1, NULL_TREE, NULL_TREE);		  poplevel (0, 0, 0); }  */	| '(' notype_declarator ')'		{ $$ = $2; }	| '*' type_quals notype_declarator  %prec UNARY		{ $$ = make_pointer_declarator ($2, $3); }	| notype_declarator '[' expr ']'  %prec '.'		{ $$ = build_nt (ARRAY_REF, $1, $3); }	| notype_declarator '[' ']'  %prec '.'		{ $$ = build_nt (ARRAY_REF, $1, NULL_TREE); }	| IDENTIFIER	;structsp:	  STRUCT identifier '{'		{ $$ = start_struct (RECORD_TYPE, $2);		  /* Start scope of tag before parsing components.  */		}	  component_decl_list '}'		{ $$ = finish_struct ($<ttype>4, $5);		  /* Really define the structure.  */		}	| STRUCT '{' component_decl_list '}'		{ $$ = finish_struct (start_struct (RECORD_TYPE, NULL_TREE),				      $3); }	| STRUCT identifier		{ $$ = xref_tag (RECORD_TYPE, $2); }	| UNION identifier '{'		{ $$ = start_struct (UNION_TYPE, $2); }	  component_decl_list '}'		{ $$ = finish_struct ($<ttype>4, $5); }	| UNION '{' component_decl_list '}'		{ $$ = finish_struct (start_struct (UNION_TYPE, NULL_TREE),				      $3); }	| UNION identifier		{ $$ = xref_tag (UNION_TYPE, $2); }	| ENUM identifier '{'		{ $<itype>3 = suspend_momentary ();		  $$ = start_enum ($2); }	  enumlist maybecomma_warn '}'		{ $$ = finish_enum ($<ttype>4, nreverse ($5));		  resume_momentary ($<itype>3); }	| ENUM '{'		{ $<itype>2 = suspend_momentary ();		  $$ = start_enum (NULL_TREE); }	  enumlist maybecomma_warn '}'		{ $$ = finish_enum ($<ttype>3, nreverse ($4));		  resume_momentary ($<itype>2); }	| ENUM identifier		{ $$ = xref_tag (ENUMERAL_TYPE, $2); }	;maybecomma:	  /* empty */	| ','	;maybecomma_warn:	  /* empty */	| ','		{ if (pedantic) warning ("comma at end of enumerator list"); }	;component_decl_list:	  component_decl_list2		{ $$ = $1; }	| component_decl_list2 component_decl		{ $$ = chainon ($1, $2);		  warning ("no semicolon at end of struct or union"); }	;component_decl_list2:	/* empty */		{ $$ = NULL_TREE; }	| component_decl_list2 component_decl ';'		{ $$ = chainon ($1, $2); }	| component_decl_list2 ';'		{ if (pedantic)		    warning ("extra semicolon in struct or union specified"); }	;/* There is a shift-reduce conflict here, because `components' may   start with a `typename'.  It happens that shifting (the default resolution)   does the right thing, because it treats the `typename' as part of   a `typed_typespecs'.   It is possible that this same technique would allow the distinction   between `notype_initdecls' and `initdecls' to be eliminated.   But I am being cautious and not trying it.  */component_decl:	typed_typespecs setspecs components		{ $$ = $3;		  current_declspecs = TREE_VALUE (declspec_stack);		  declspec_stack = TREE_CHAIN (declspec_stack);		  resume_momentary ($2); }	| nonempty_type_quals setspecs components		{ $$ = $3;		  current_declspecs = TREE_VALUE (declspec_stack);		  declspec_stack = TREE_CHAIN (declspec_stack);		  resume_momentary ($2); }	| error		{ $$ = NULL_TREE; }	;components:	  /* empty */		{ if (pedantic)		    warning ("ANSI C forbids member declarations with no members");		  $$ = NULL_TREE; }	| component_declarator	| components ',' component_declarator		{ $$ = chainon ($1, $3); }	;component_declarator:	declarator maybe_attribute		{ $$ = grokfield (input_filename, lineno, $1, current_declspecs, NULL_TREE); }	| declarator ':' expr_no_commas maybe_attribute		{ $$ = grokfield (input_filename, lineno, $1, current_declspecs, $3); }	| ':' expr_no_commas		{ $$ = grokfield (input_filename, lineno, NULL_TREE, current_declspecs, $2); }	;/* We chain the enumerators in reverse order.   They are put in forward order where enumlist is used.   (The order used to be significant, but no longer is so.   However, we still maintain the order, just to be clean.)  */enumlist:	  enumerator	| enumlist ',' enumerator		{ $$ = chainon ($3, $1); }	;enumerator:	  identifier		{ $$ = build_enumerator ($1, NULL_TREE); }	| identifier '=' expr_no_commas		{ $$ = build_enumerator ($1, $3); }	;typename:	typed_typespecs absdcl		{ $$ = build_tree_list ($1, $2); }	| nonempty_type_quals absdcl		{ $$ = build_tree_list ($1, $2); }	;absdcl:   /* an absolute declarator */	/* empty */		{ $$ = NULL_TREE; }	| absdcl1	;nonempty_type_quals:	  TYPE_QUAL		{ $$ = tree_cons (NULL_TREE, $1, NULL_TREE); }	| nonempty_type_quals TYPE_QUAL		{ $$ = tree_cons (NULL_TREE, $2, $1); }	;type_quals:	  /* empty */		{ $$ = NULL_TREE; }	| type_quals TYPE_QUAL		{ $$ = tree_cons (NULL_TREE, $2, $1); }	;absdcl1:  /* a nonempty absolute declarator */	  '(' absdcl1 ')'		{ $$ = $2; }	  /* `(typedef)1' is `int'.  */	| '*' type_quals absdcl1  %prec UNARY		{ $$ = make_pointer_declarator ($2, $3); }	| '*' type_quals  %prec UNARY		{ $$ = make_pointer_declarator ($2, NULL_TREE); }	| absdcl1 '(' parmlist  %prec '.'		{ $$ = build_nt (CALL_EXPR, $1, $3, NULL_TREE); }	| absdcl1 '[' expr ']'  %prec '.'		{ $$ = build_nt (ARRAY_REF, $1, $3); }	| absdcl1 '[' ']'  %prec '.'		{ $$ = build_nt (ARRAY_REF, $1, NULL_TREE); }	| '(' parmlist  %prec '.'		{ $$ = build_nt (CALL_EXPR, NULL_TREE, $2, NULL_TREE); }	| '[' expr ']'  %prec '.'		{ $$ = build_nt (ARRAY_REF, NULL_TREE, $2); }	| '[' ']'  %prec '.'		{ $$ = build_nt (ARRAY_REF, NULL_TREE, NULL_TREE); }	;/* at least one statement, the first of which parses without error.  *//* stmts is used only after decls, so an invalid first statement   is actually regarded as an invalid decl and part of the decls.  */stmts:	stmt	| stmts stmt	| stmts errstmt	;xstmts:	/* empty */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -