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

📄 c-parse.y

📁 这是完整的gcc源代码
💻 Y
📖 第 1 页 / 共 5 页
字号:
/* YACC parser for C syntax.   Copyright (C) 1987, 1988, 1989 Free Software Foundation, Inc.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 1, 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.  *//* To whomever it may concern: I have heard that such a thing was oncewritten by AT&T, but I have never seen it.  */%expect 8/* These are the 8 conflicts you should get in parse.output;   the state numbers may vary if minor changes in the grammar are made.State 41 contains 1 shift/reduce conflict.  (Two ways to recover from error.)State 92 contains 1 shift/reduce conflict.  (Two ways to recover from error.)State 99 contains 1 shift/reduce conflict.  (Two ways to recover from error.)State 103 contains 1 shift/reduce conflict.  (Two ways to recover from error.)State 119 contains 1 shift/reduce conflict.  (See comment at component_decl.)State 183 contains 1 shift/reduce conflict.  (Two ways to recover from error.)State 193 contains 1 shift/reduce conflict.  (Two ways to recover from error.)State 199 contains 1 shift/reduce conflict.  (Two ways to recover from error.)*/%{#include "config.h"#include "tree.h"#include "input.h"#include "c-parse.h"#include "c-tree.h"#include <stdio.h>#include <errno.h>#ifndef errnoextern int errno;#endifvoid yyerror ();/* Cause the `yydebug' variable to be defined.  */#define YYDEBUG 1%}%start program%union {long itype; tree ttype; 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/* 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 */%token SIZEOF ENUM STRUCT UNION IF ELSE WHILE DO FOR SWITCH CASE DEFAULT%token BREAK CONTINUE RETURN GOTO ASM TYPEOF ALIGNOF%token ATTRIBUTE/* Add precedence rules to solve dangling else s/r conflict */%nonassoc IF%nonassoc ELSE/* 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.  */%right <code> ASSIGN '='%right <code> '?' ':'%left <code> OROR%left <code> ANDAND%left <code> '|'%left <code> '^'%left <code> '&'%left <code> EQCOMPARE%left <code> ARITHCOMPARE%left <code> LSHIFT RSHIFT%left <code> '+' '-'%left <code> '*' '/' '%'%right <code> UNARY PLUSPLUS MINUSMINUS%left HYPERUNARY%left <code> POINTSAT '.' '(' '['%type <code> unop%type <ttype> identifier IDENTIFIER TYPENAME CONSTANT expr nonnull_exprlist exprlist%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 <ttype> initdecls notype_initdecls initdcl notype_initdcl%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> compstmt%type <ttype> declarator%type <ttype> notype_declarator after_type_declarator%type <ttype> parm_declarator%type <ttype> structsp component_decl_list component_decl_list2%type <ttype> component_decl components component_declarator%type <ttype> enumlist enumerator%type <ttype> typename absdcl absdcl1 type_quals%type <ttype> xexpr parms parm identifiers%type <ttype> parmlist parmlist_1 parmlist_2%type <ttype> parmlist_or_identifiers parmlist_or_identifiers_1%type <itype> setspecs%{/* the declaration found for the last IDENTIFIER token read in.   yylex must look this up to detect typedefs, which get token type TYPENAME,   so it is left around in case the identifier is not a typedef but is   used in a context which makes it a reference to a variable.  */static tree lastiddecl;static tree make_pointer_declarator ();static tree combine_strings ();static void reinit_parse_for_function ();/* List of types and structure classes of the current declaration.  */tree current_declspecs;/* Stack of saved values of current_declspecs.  */tree declspec_stack;int undeclared_variable_notice;	/* 1 if we explained undeclared var errors.  */static int yylex ();%}%%program: /* empty */	| extdefs	;/* 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	| extdefs {$<ttype>$ = NULL_TREE; } extdef	;extdef:	fndef	| datadef	| ASM '(' string ')' ';'		{ if (TREE_CHAIN ($3)) $3 = combine_strings ($3);		  assemble_asm ($3); }	;datadef:	  setspecs notype_initdecls ';'		{ if (pedantic)		    error ("ANSI C forbids data definition lacking type or storage class");		  else if (!flag_traditional)		    warning ("data definition lacks type or storage class"); }        | declmods setspecs notype_initdecls ';'	  {}	| typed_declspecs setspecs initdecls ';'	  {}        | declmods ';'	  { error ("empty declaration"); }	| typed_declspecs ';'	  { shadow_tag ($1); }	| error ';'	| error '}'	| ';'		{ if (pedantic)		    warning ("ANSI C does not allow extra `;' outside of a function"); }	;fndef:	  typed_declspecs setspecs declarator		{ if (! start_function ($1, $3))		    YYFAIL;		  reinit_parse_for_function (); }	  xdecls		{ store_parm_decls (); }	  compstmt_or_error		{ finish_function (lineno); }	| typed_declspecs setspecs declarator error		{ }	| declmods setspecs notype_declarator		{ if (! start_function ($1, $3))		    YYFAIL;		  reinit_parse_for_function (); }	  xdecls		{ store_parm_decls (); }	  compstmt_or_error		{ finish_function (lineno); }	| declmods setspecs notype_declarator error		{ }	| setspecs notype_declarator		{ if (! start_function (0, $2))		    YYFAIL;		  reinit_parse_for_function (); }	  xdecls		{ store_parm_decls (); }	  compstmt_or_error		{ finish_function (lineno); }	| setspecs notype_declarator error		{ }	;identifier:	IDENTIFIER	| TYPENAME	;unop:     '&'		{ $$ = ADDR_EXPR; }	| '-'		{ $$ = NEGATE_EXPR; }	| '+'		{ $$ = CONVERT_EXPR; }	| PLUSPLUS		{ $$ = PREINCREMENT_EXPR; }	| MINUSMINUS		{ $$ = PREDECREMENT_EXPR; }	| '~'		{ $$ = BIT_NOT_EXPR; }	| '!'		{ $$ = TRUTH_NOT_EXPR; }	;expr:	nonnull_exprlist		{ $$ = build_compound_expr ($1); }	;exprlist:	  /* empty */		{ $$ = NULL_TREE; }	| nonnull_exprlist	;nonnull_exprlist:	expr_no_commas		{ $$ = build_tree_list (NULL_TREE, $1); }	| nonnull_exprlist ',' expr_no_commas		{ chainon ($1, build_tree_list (NULL_TREE, $3)); }	;unary_expr:	primary	| '*' cast_expr   %prec UNARY		{ $$ = build_indirect_ref ($2, "unary *"); }	| unop cast_expr  %prec UNARY		{ $$ = build_unary_op ($1, $2, 0); }	| SIZEOF unary_expr  %prec UNARY		{ if (TREE_CODE ($2) == COMPONENT_REF		      && TREE_PACKED (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);		  $$ = c_sizeof (TREE_TYPE ($2)); }	| SIZEOF '(' typename ')'  %prec HYPERUNARY		{ $$ = c_sizeof (groktypename ($3)); }	| ALIGNOF unary_expr  %prec UNARY		{ if (TREE_CODE ($2) == COMPONENT_REF		      && TREE_PACKED (TREE_OPERAND ($2, 1)))		    error ("`__alignof' applied to a bit-field");		  if (TREE_CODE ($2) == INDIRECT_REF)		    {		      tree t = TREE_OPERAND ($2, 0);		      tree best = t;		      int bestalign = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (t)));		      while (TREE_CODE (t) == NOP_EXPR			     && TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0))) == POINTER_TYPE)			{			  int thisalign;			  t = TREE_OPERAND (t, 0);			  thisalign = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (t)));			  if (thisalign > bestalign)			    best = t, bestalign = thisalign;			}		      $$ = c_alignof (TREE_TYPE (TREE_TYPE (best)));		    }		  else		    {		      /* ANSI says arrays and fns are converted inside comma.			 But we can't 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);		      $$ = c_alignof (TREE_TYPE ($2));		    }		}	| ALIGNOF '(' typename ')'  %prec HYPERUNARY		{ $$ = c_alignof (groktypename ($3)); }	;cast_expr:	unary_expr	| '(' typename ')' cast_expr  %prec UNARY		{ tree type = groktypename ($2);		  $$ = build_c_cast (type, $4); }	| '(' typename ')' '{' initlist maybecomma '}'  %prec UNARY		{ tree type = groktypename ($2);		  if (pedantic)		    warning ("ANSI C forbids constructor expressions");		  $$ = digest_init (type, build_nt (CONSTRUCTOR, NULL_TREE, nreverse ($5)), 0);		  if (TREE_CODE (type) == ARRAY_TYPE && TYPE_SIZE (type) == 0)		    {		      int failure = complete_array_type (type, $$, 1);		      if (failure)			abort ();		    }		}	;expr_no_commas:	  cast_expr	| expr_no_commas '+' expr_no_commas		{ $$ = build_binary_op ($2, $1, $3); }	| expr_no_commas '-' expr_no_commas		{ $$ = build_binary_op ($2, $1, $3); }	| expr_no_commas '*' expr_no_commas		{ $$ = build_binary_op ($2, $1, $3); }	| expr_no_commas '/' expr_no_commas		{ $$ = build_binary_op ($2, $1, $3); }	| expr_no_commas '%' expr_no_commas		{ $$ = build_binary_op ($2, $1, $3); }	| expr_no_commas LSHIFT expr_no_commas		{ $$ = build_binary_op ($2, $1, $3); }	| expr_no_commas RSHIFT expr_no_commas		{ $$ = build_binary_op ($2, $1, $3); }	| expr_no_commas ARITHCOMPARE expr_no_commas		{ $$ = build_binary_op ($2, $1, $3); }	| expr_no_commas EQCOMPARE expr_no_commas		{ $$ = build_binary_op ($2, $1, $3); }	| expr_no_commas '&' expr_no_commas		{ $$ = build_binary_op ($2, $1, $3); }	| expr_no_commas '|' expr_no_commas		{ $$ = build_binary_op ($2, $1, $3); }	| expr_no_commas '^' expr_no_commas		{ $$ = build_binary_op ($2, $1, $3); }	| expr_no_commas ANDAND expr_no_commas		{ $$ = build_binary_op (TRUTH_ANDIF_EXPR, $1, $3); }	| expr_no_commas OROR expr_no_commas		{ $$ = build_binary_op (TRUTH_ORIF_EXPR, $1, $3); }	| expr_no_commas '?' xexpr ':' expr_no_commas		{ $$ = build_conditional_expr ($1, $3, $5); }	| expr_no_commas '=' expr_no_commas		{ $$ = build_modify_expr ($1, NOP_EXPR, $3); }	| expr_no_commas ASSIGN expr_no_commas		{ $$ = build_modify_expr ($1, $2, $3); }	;primary:	IDENTIFIER		{ $$ = lastiddecl;		  if (!$$ || $$ == error_mark_node)		    {		      if (yychar == YYEMPTY)			yychar = YYLEX;		      if (yychar == '(')			{			  $$ = implicitly_declare ($1);			  assemble_external ($$);			  TREE_USED ($$) = 1;			}		      else if (current_function_decl == 0)			{			  error ("`%s' undeclared, outside of functions",				 IDENTIFIER_POINTER ($1));			  $$ = error_mark_node;			}		      else			{			  if (IDENTIFIER_GLOBAL_VALUE ($1) != error_mark_node			      || IDENTIFIER_ERROR_LOCUS ($1) != current_function_decl)			    {			      error ("`%s' undeclared (first use this function)",				     IDENTIFIER_POINTER ($1));			      if (! undeclared_variable_notice)				{				  error ("(Each undeclared identifier is reported only once");				  error ("for each function it appears in.)");				  undeclared_variable_notice = 1;				}			    }			  $$ = error_mark_node;			  /* Prevent repeated error messages.  */			  IDENTIFIER_GLOBAL_VALUE ($1) = error_mark_node;			  IDENTIFIER_ERROR_LOCUS ($1) = current_function_decl;			}		    }		  else if (! TREE_USED ($$))		    {		      if (TREE_EXTERNAL ($$))			assemble_external ($$);		      TREE_USED ($$) = 1;		    }		  if (TREE_CODE ($$) == CONST_DECL)		    $$ = DECL_INITIAL ($$);		}	| CONSTANT	| string		{ $$ = combine_strings ($1); }	| '(' expr ')'		{ $$ = $2; }	| '(' error ')'		{ $$ = error_mark_node; }	| '('		{ if (current_function_decl == 0)		    {		      error ("braced-group within expression allowed only inside a function");		      YYFAIL;		    }		  keep_next_level ();		  $<ttype>$ = expand_start_stmt_expr (); }	  compstmt ')'		{ tree rtl_exp;		  if (pedantic)		    warning ("ANSI C forbids braced-groups within expressions");		  rtl_exp = expand_end_stmt_expr ($<ttype>2);		  $$ = $3;		  TREE_USED ($$) = 0;		  /* Since the statements have side effects,		     consider this volatile.  */		  TREE_VOLATILE ($$) = 1;		  TREE_TYPE ($$) = TREE_TYPE (rtl_exp);		  STMT_BODY ($$) = rtl_exp; }	| primary '(' exprlist ')'   %prec '.'		{ $$ = build_function_call ($1, $3); }

⌨️ 快捷键说明

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