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

📄 c-parse.y

📁 这是完整的gcc源代码
💻 Y
📖 第 1 页 / 共 5 页
字号:
	| stmts	;errstmt:  error ';'	;pushlevel:  /* empty */		{ pushlevel (0);		  clear_last_expr ();		  push_momentary ();		  expand_start_bindings (0); }	;/* This is the body of a function definition.   It causes syntax errors to ignore to the next openbrace.  */compstmt_or_error:	  compstmt		{}	| error compstmt	;compstmt: '{' '}'		{ $$ = 0; }	| '{' pushlevel decls xstmts '}'		{ expand_end_bindings (getdecls (), 1, 0);		  $$ = poplevel (1, 1, 0);		  pop_momentary (); }	| '{' pushlevel error '}'		{ expand_end_bindings (getdecls (), kept_level_p (), 0);		  $$ = poplevel (kept_level_p (), 0, 0);		  pop_momentary (); }	| '{' pushlevel stmts '}'		{ expand_end_bindings (getdecls (), kept_level_p (), 0);		  $$ = poplevel (kept_level_p (), 0, 0);		  pop_momentary (); }	;simple_if:	  IF '(' expr ')'		{ emit_line_note (input_filename, lineno);		  expand_start_cond (truthvalue_conversion ($3), 0); }	  stmt	;stmt:	  compstmt	{}	| expr ';'		{ emit_line_note (input_filename, lineno);		  /* Do default conversion if safe and possibly important,		     in case within ({...}).  */		  if ((TREE_CODE (TREE_TYPE ($1)) == ARRAY_TYPE		       && lvalue_p ($1))		      || TREE_CODE (TREE_TYPE ($1)) == FUNCTION_TYPE)		    $1 = default_conversion ($1);		  expand_expr_stmt ($1);		  clear_momentary (); }	| simple_if ELSE		{ expand_start_else (); }	  stmt		{ expand_end_else (); }	| simple_if %prec IF		{ expand_end_cond (); }	| WHILE		{ emit_nop ();		  emit_line_note (input_filename, lineno);		  expand_start_loop (1); }	  '(' expr ')'		{ emit_line_note (input_filename, lineno);		  expand_exit_loop_if_false (truthvalue_conversion ($4)); }	  stmt		{ expand_end_loop (); }	| DO		{ emit_nop ();		  emit_line_note (input_filename, lineno);		  expand_start_loop_continue_elsewhere (1); }	  stmt WHILE		{ expand_loop_continue_here (); }	  '(' expr ')' ';'		{ emit_line_note (input_filename, lineno);		  expand_exit_loop_if_false (truthvalue_conversion ($7));		  expand_end_loop ();		  clear_momentary (); }	| FOR	  '(' xexpr ';'		{ emit_nop ();		  emit_line_note (input_filename, lineno);		  if ($3) expand_expr_stmt ($3);		  expand_start_loop_continue_elsewhere (1); }	  xexpr ';'		{ emit_line_note (input_filename, lineno);		  if ($6)		    expand_exit_loop_if_false (truthvalue_conversion ($6)); }	  xexpr ')'		/* Don't let the tree nodes for $9 be discarded		   by clear_momentary during the parsing of the next stmt.  */		{ push_momentary ();		  $<itype>10 = lineno; }	  stmt		{ emit_line_note (input_filename, $<itype>10);		  expand_loop_continue_here ();		  if ($9)		    expand_expr_stmt ($9);		  pop_momentary ();		  expand_end_loop (); }	| SWITCH '(' expr ')'		{ emit_line_note (input_filename, lineno);		  c_expand_start_case ($3);		  /* Don't let the tree nodes for $3 be discarded by		     clear_momentary during the parsing of the next stmt.  */		  push_momentary (); }	  stmt		{ expand_end_case ($3);		  pop_momentary (); }	| CASE expr ':'		{ register tree value = fold ($2);		  register tree label		    = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);		  /* build_c_cast puts on a NOP_EXPR to make a non-lvalue.		     Strip such NOP_EXPRs.  */		  if (TREE_CODE (value) == NOP_EXPR		      && TREE_TYPE (value) == TREE_TYPE (TREE_OPERAND (value, 0)))		    value = TREE_OPERAND (value, 0);		  if (TREE_CODE (value) != INTEGER_CST		      && value != error_mark_node)		    {		      error ("case label does not reduce to an integer constant");		      value = error_mark_node;		    }		  else		    /* Promote char or short to int.  */		    value = default_conversion (value);		  if (value != error_mark_node)		    {		      int success = pushcase (value, label);		      if (success == 1)			error ("case label not within a switch statement");		      else if (success == 2)			error ("duplicate case value");		      else if (success == 3)			warning ("case value out of range");		    }		}	  stmt	| DEFAULT ':'		{		  register tree label		    = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);		  int success = pushcase (NULL_TREE, label);		  if (success == 1)		    error ("default label not within a switch statement");		  else if (success == 2)		    error ("multiple default labels in one switch");		}	  stmt	| BREAK ';'		{ emit_line_note (input_filename, lineno);		  if ( ! expand_exit_something ())		    error ("break statement not within loop or switch"); }	| CONTINUE ';'		{ emit_line_note (input_filename, lineno);		  if (! expand_continue_loop ())		    error ("continue statement not within a loop"); }	| RETURN ';'		{ emit_line_note (input_filename, lineno);		  c_expand_return (NULL_TREE); }	| RETURN expr ';'		{ emit_line_note (input_filename, lineno);		  c_expand_return ($2); }	| ASM maybe_type_qual '(' string ')' ';'		{ if (TREE_CHAIN ($4)) $4 = combine_strings ($4);		  emit_line_note (input_filename, lineno);		  expand_asm ($4); }	/* This is the case with just output operands.  */	| ASM maybe_type_qual '(' string ':' asm_operands ')' ';'		{ if (TREE_CHAIN ($4)) $4 = combine_strings ($4);		  emit_line_note (input_filename, lineno);		  c_expand_asm_operands ($4, $6, NULL_TREE, NULL_TREE,					 $2 == ridpointers[(int)RID_VOLATILE],					 input_filename, lineno); }	/* This is the case with input operands as well.  */	| ASM maybe_type_qual '(' string ':' asm_operands ':' asm_operands ')' ';'		{ if (TREE_CHAIN ($4)) $4 = combine_strings ($4);		  emit_line_note (input_filename, lineno);		  c_expand_asm_operands ($4, $6, $8, NULL_TREE,					 $2 == ridpointers[(int)RID_VOLATILE],					 input_filename, lineno); }	/* This is the case with clobbered registers as well.  */	| ASM maybe_type_qual '(' string ':' asm_operands ':'  	  asm_operands ':' asm_clobbers ')' ';'		{ if (TREE_CHAIN ($4)) $4 = combine_strings ($4);		  emit_line_note (input_filename, lineno);		  c_expand_asm_operands ($4, $6, $8, $10,					 $2 == ridpointers[(int)RID_VOLATILE],					 input_filename, lineno); }	| GOTO identifier ';'		{ tree decl;		  emit_line_note (input_filename, lineno);		  decl = lookup_label ($2);		  TREE_USED (decl) = 1;		  expand_goto (decl); }	| identifier ':'		{ tree label = define_label (input_filename, lineno, $1);		  emit_nop ();		  if (label)		    expand_label (label); }	  stmt	| ';'	;/* Either a type-qualifier or nothing.  First thing in an `asm' statement.  */maybe_type_qual:	/* empty */		{ emit_line_note (input_filename, lineno); }	| TYPE_QUAL		{ emit_line_note (input_filename, lineno); }	;xexpr:	/* empty */		{ $$ = NULL_TREE; }	| expr	;/* These are the operands other than the first string and colon   in  asm ("addextend %2,%1": "=dm" (x), "0" (y), "g" (*x))  */asm_operands: /* empty */		{ $$ = NULL_TREE; }	| nonnull_asm_operands	;nonnull_asm_operands:	  asm_operand	| nonnull_asm_operands ',' asm_operand		{ $$ = chainon ($1, $3); }	;asm_operand:	  STRING '(' expr ')'		{ $$ = build_tree_list ($1, $3); }	;asm_clobbers:	  string		{ $$ = tree_cons (NULL_TREE, combine_strings ($1), NULL_TREE); }	| asm_clobbers ',' string		{ $$ = tree_cons (NULL_TREE, combine_strings ($3), $1); }	;/* This is what appears inside the parens in a function declarator.   Its value is a list of ..._TYPE nodes.  */parmlist:		{ pushlevel (0);		  declare_parm_level (); }	  parmlist_1		{ $$ = $2;		  parmlist_tags_warning ();		  poplevel (0, 0, 0); }	;/* This is referred to where either a parmlist or an identifier list is ok.   Its value is a list of ..._TYPE nodes or a list of identifiers.  */parmlist_or_identifiers:		{ pushlevel (0);		  declare_parm_level (); }	  parmlist_or_identifiers_1		{ $$ = $2;		  parmlist_tags_warning ();		  poplevel (0, 0, 0); }	;parmlist_or_identifiers_1:	  parmlist_2 ')'	| identifiers ')'		{ $$ = tree_cons (NULL_TREE, NULL_TREE, $1); }	| error ')'		{ $$ = tree_cons (NULL_TREE, NULL_TREE, NULL_TREE); }	;parmlist_1:	  parmlist_2 ')'	| error ')'		{ $$ = tree_cons (NULL_TREE, NULL_TREE, NULL_TREE); }	;/* This is what appears inside the parens in a function declarator.   Is value is represented in the format that grokdeclarator expects.  */parmlist_2:  /* empty */		{ $$ = get_parm_info (0); }	| parms		{ $$ = get_parm_info (1); }	| parms ',' ELLIPSIS		{ $$ = get_parm_info (0); }	;parms:	parm		{ push_parm_decl ($1); }	| parms ',' parm		{ push_parm_decl ($3); }	;/* A single parameter declaration or parameter type name,   as found in a parmlist.  */parm:	  typed_declspecs parm_declarator		{ $$ = build_tree_list ($1, $2)	; }	| typed_declspecs notype_declarator		{ $$ = build_tree_list ($1, $2)	; }	| typed_declspecs absdcl		{ $$ = build_tree_list ($1, $2); }	| declmods notype_declarator		{ $$ = build_tree_list ($1, $2)	; }	| declmods absdcl		{ $$ = build_tree_list ($1, $2); }	;/* A nonempty list of identifiers.  */identifiers:	IDENTIFIER		{ $$ = build_tree_list (NULL_TREE, $1); }	| identifiers ',' IDENTIFIER		{ $$ = chainon ($1, build_tree_list (NULL_TREE, $3)); }	;%%/* Return something to represent absolute declarators containing a *.   TARGET is the absolute declarator that the * contains.   TYPE_QUALS is a list of modifiers such as const or volatile   to apply to the pointer type, represented as identifiers.   We return an INDIRECT_REF whose "contents" are TARGET   and whose type is the modifier list.  */static treemake_pointer_declarator (type_quals, target)     tree type_quals, target;{  return build (INDIRECT_REF, type_quals, target);}/* Given a chain of STRING_CST nodes,   concatenate them into one STRING_CST   and give it a suitable array-of-chars data type.  */static treecombine_strings (strings)     tree strings;{  register tree value, t;  register int length = 1;  int wide_length = 0;  int wide_flag = 0;  int nchars;  if (TREE_CHAIN (strings))    {      /* More than one in the chain, so concatenate.  */      register char *p, *q;      /* Don't include the \0 at the end of each substring,	 except for the last one.	 Count wide strings and ordinary strings separately.  */      for (t = strings; t; t = TREE_CHAIN (t))	{	  if (TREE_TYPE (t) == int_array_type_node)	    {	      wide_length += (TREE_STRING_LENGTH (t) - UNITS_PER_WORD);	      wide_flag = 1;	    }	  else	    length += (TREE_STRING_LENGTH (t) - 1);	}      /* If anything is wide, the non-wides will be converted,	 which makes them take more space.  */      if (wide_flag)	length = length * UNITS_PER_WORD + wide_length;      p = (char *) savealloc (length);      /* Copy the individual strings into the new combined string.	 If the combined string is wide, convert the chars to ints	 for any individual strings that are not wide.  */      q = p;      for (t = strings; t; t = TREE_CHAIN (t))	{	  int len = (TREE_STRING_LENGTH (t) 		     - ((TREE_TYPE (t) == int_array_type_node)			? UNITS_PER_WORD : 1));	  if ((TREE_TYPE (t) == int_array_type_node) == wide_flag)	    {	      bcopy (TREE_STRING_POINTER (t), q, len);	      q += len;	    }	  else	    {	      int i;	      for (i = 0; i < len; i++)		((int *) q)[i] = TREE_STRING_POINTER (t)[i];	      q += len * UNITS_PER_WORD;	    }	}      if (wide_flag)	{	  int i;	  for (i = 0; i < UNITS_PER_WORD; i++)	    *q++ = 0;	}      else	*q = 0;      value = make_node (STRING_CST);      TREE_STRING_POINTER (value) = p;      TREE_STRING_LENGTH (value) = length;      TREE_LITERAL (value) = 1;    }  else    {      value = strings;      length = TREE_STRING_LENGTH (value);      if (TREE_TYPE (value) == int_array_type_node)	wide_flag = 1;    }  /* Compute the number of elements, for the array type.  */   nchars = wide_flag ? length / UNITS_PER_WORD : length;  /* Create the array type for the string constant.     -Wwrite-strings says make the string constant an array of const char     so that copying it to a non-const pointer will get a warning.  */  if (warn_write_strings)    {      tree elements	= build_type_variant (wide_flag ? integer_type_node : char_type_node,			      1, 0);      TREE_TYPE (value)	= build_array_type (elements,			    build_index_type (build_int_2 (nchars - 1, 0)));    }  else    TREE_TYPE (value)      = build_array_type (wide_flag ? integer_type_node : char_type_node,			  build_index_type (build_int_2 (nchars - 1, 0)));  TREE_LITERAL (value) = 1;  TREE_STATIC (value) = 1;  return value;}FILE *finput;			/* input file.				   Normally a pipe from the preprocessor.  *//* lexical analyzer */static int maxtoken;		/* Current nominal length of token buffer.  */static char *token_buffer;	/* Pointer to token buffer.				   Actual allocated length is maxtoken + 2.  */static int max_wide;		/* Current nominal length of wide_buffer.  */static int *wide_buffer;	/* Pointer to wide-string buffer.				   Actual allocated length is max_wide + 1.  *//* Nonzero if end-of-file has been seen on input.  */static int end_of_file;/* Buffered character to reread.   I'm not sure why ungetc is not used.  */static int nextchar = -1;/* Data type that represents the GNU C reserved words. */struct resword { char *name; short token; enum rid rid; };#define MIN_WORD_LENGTH     2      /* minimum size for C keyword */#define MAX_WORD_LENGTH     13     /* maximum size for C keyword */#define MIN_HASH_VALUE      7      /* range of the hash keys values  */#define MAX_HASH_VALUE      91     /* for the perfect hash generator */#define NORID RID_UNUSED/* This function performs the minimum-perfect hash mapping from input   string to reswords table index.  It only looks at the first and

⌨️ 快捷键说明

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