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

📄 c.y

📁 一个c语言写做的编译器的源码
💻 Y
📖 第 1 页 / 共 3 页
字号:
	| abstract_decl		{ discard_symbol  ($1); $$ = NULL ; }
	| ELLIPSIS		{			$$ = NULL ; }
	;


abstract_decl
	: type 	abs_decl   {    add_spec_to_decl   ( $1, $$ = $2 ); }
	| TTYPE	abs_decl   {
				$$ = $2;
				add_spec_to_decl( $1->type, $2 );
			   }
	;

abs_decl
	: /* epsilon */		    { $$ = new_symbol("",0); 		   }
	| LP abs_decl RP LP RP	    { add_declarator( $$ = $2, FUNCTION ); }
	| STAR abs_decl		    { add_declarator( $$ = $2, POINTER  ); }
	| abs_decl LB            RB { add_declarator( $$,      POINTER  ); }
	| abs_decl LB const_expr RB { add_declarator( $$,      ARRAY 	);
				      $$->etype->NUM_ELE = $3;
				    }
	| LP abs_decl RP 	    { $$ = $2; }
	;

struct_specifier
	: STRUCT opt_tag LC def_list RC
	  {
		if( !$2->fields )
		{
		    $2->fields = reverse_links( $4 );

		    if( !illegal_struct_def( $2, $4 ) )
			$2->size = figure_struct_offsets( $2->fields, $1=='s' );
		}
		else
		{
		    yyerror("Ignoring redefinition of %s", $2->tag );
		    discard_symbol_chain( $4 );
		}

		$$ = $2;
	  }
	| STRUCT tag		 { $$ = $2; }
	;

opt_tag : tag
	| /* empty */	{
			    static unsigned label = 0;
			    static char     tag[16];
			    sprintf( tag, "%03d", label++ );

			    $$ = new_structdef( tag );
			    addsym( Struct_tab, $$ );
	  		}
	;

tag	: NAME		{
			    if( !($$=(structdef *) findsym(Struct_tab,yytext)))
			    {
				$$        = new_structdef( yytext );
				$$->level = Nest_lev;
				addsym( Struct_tab, $$ );
			    }
			}
	;


def_list
	: def_list def		{   symbol *p;
				    if( p = $2 )
				    {
					for(; p->next; p = p->next )
					    ;
					p->next = $1;
					$$      = $2;
				    }
				}
	| /* epsilon */		{   $$ = NULL; }   /* Initialize end-of-list */
	;					   /* pointer.		     */

def
	: specifiers decl_list	{ add_spec_to_decl( $1, $2 );	}
	  		  SEMI	{ $$ = $2;			}

	| specifiers SEMI 	{ $$ = NULL; }
	;

decl_list
	: decl 			{ $$->next = NULL;}
	| decl_list COMMA decl
	  {
		$3->next = $1;
		$$       = $3;
	  }
	;

decl
	: funct_decl
	| var_decl
	| var_decl EQUAL initializer {	yyerror( "Ignoring initializer.\n");
					discard_value( $3 );
				     }
	| var_decl COLON const_expr   		%prec COMMA
	| COLON const_expr		    	%prec COMMA
	;

enum_specifier
	: enum name opt_enum_list    {	if( $2->type )
					   yyerror("%s: redefinition",$2->name);
					else
					   discard_symbol($2);
				     }
	| enum LC enumerator_list RC
	;

opt_enum_list
	: LC enumerator_list RC
	| /* empty */
	;


enum	: ENUM   { Enum_val = 0; }

	;

enumerator_list
	: enumerator
	| enumerator_list COMMA enumerator
	;

enumerator
	: name			{   do_enum( $1, Enum_val++ );  }
	| name EQUAL const_expr {   Enum_val = $3;
				    do_enum( $1, Enum_val++ );  }
	;


compound_stmt
	: LC			   {   if( ++Nest_lev == 1 )
					   loc_reset();
				   }
	  local_defs stmt_list RC  {   --Nest_lev;
				       remove_symbols_from_table ( $3 );
				       discard_symbol_chain      ( $3 );
				   }
	;

local_defs
	: def_list	{   add_symbols_to_table ( $$ = reverse_links( $1 ));
			    figure_local_offsets ( $$, Funct_name	    );
			    create_static_locals ( $$, Funct_name	    );
			    print_offset_comment ( $$, "variable"	    );
			}
	;



ext_def : opt_specifiers ext_decl_list
	  {
		add_spec_to_decl( $1, $2 );

		if( !$1->tdef )
		    discard_link_chain( $1 );

		add_symbols_to_table 		( $2 = reverse_links( $2 ) );
		figure_osclass			( $2	 );
		generate_defs_and_free_args     ( $2	 );
		remove_duplicates		( $2     );
	  }
	  SEMI





	| opt_specifiers
	  {
		if( !($1->class == SPECIFIER && $1->NOUN == STRUCTURE) )
		    yyerror("Useless definition (no identifier)\n");
		if( !$1->tdef )
		    discard_link_chain( $1 );
	  }
	  SEMI


	| opt_specifiers funct_decl
	  {
		static unsigned link_val = 0;	 /* Labels used for link args.*/

		add_spec_to_decl( $1, $2 );	 /* Merge the specifier and   */
						 /*  		  declarator. */
		if( !$1->tdef )
		    discard_link_chain( $1 );    /* Discard extra specifier.  */

		figure_osclass	     ( $2 );	      /* Update symbol table. */
		add_symbols_to_table ( $2 ); 	      /* Add function itself. */
		add_symbols_to_table ( $2->args );    /* Add the arguments.   */

		strcpy ( Funct_name, $2->name		    );
		sprintf( Vspace, "%s%d", L_LINK, link_val++ );
		sprintf( Tspace, "%s%d", L_LINK, link_val++ );

		yycode( "\n#undef   T\n" );
		yycode(   "#define  T(n) (fp-(%s*%d)-(n*%d))\n\n",
						       Vspace, SWIDTH, SWIDTH );
		gen( "PROC", $2->rname, $2->etype->STATIC ? "private":"public");
		gen( "link", Vspace, Tspace );

		++Nest_lev;	  /* Make nesting level of definition_list
				   * match nesting level in the funct_decl
				   */
	  }
	  def_list
	  {
		fix_types_and_discard_syms ( $4			  );
		figure_param_offsets	   ( $2->args		  );
		print_offset_comment	   ( $2->args, "argument" );

		--Nest_lev;    /* It's incremented again in the compound_stmt */
	  }
	  compound_stmt
	  {
		purge_undecl();		   /* Deal with implicit declarations */
					   /* and undeclared symbols.	      */

		remove_symbols_from_table ( $2->args );  /* Delete arguments. */
		discard_symbol_chain      ( $2->args );

		gen( ":%s%d", L_RET, rlabel(1) );     /* End-of-function */
		gen( "unlink" 		       );     /*           code. */
		gen( "ret"    		       );
		gen( "ENDP",  $2->rname	       );

		yybss ( "\n#define  %s %d\t/* %s: locals */\n",
					Vspace, loc_var_space(), $2->name );
		yybss (   "#define  %s %d\t/* %s: temps. */\n",
					Tspace, tmp_var_space(), $2->name );

		tmp_reset();		   /* Reset temporary-variable system.*/
					   /* (This is just insurance.)       */
	  }
	;



stmt_list
	: stmt_list statement
	| /* epsilon */
	;

/*----------------------------------------------------------------------
 * Statements
 */

statement
	: SEMI
	| compound_stmt
	| expr SEMI  		{ release_value($1); tmp_freeall(); }
	| RETURN 	SEMI 	{ gen( "goto%s%d", L_RET, rlabel(0) ); }

	| RETURN expr	SEMI    { gen("=", IS_INT    ($2->type) ? "rF.w.low" :
					   IS_POINTER($2->type) ? "rF.pp"    :
								  "rF.l",
								   rvalue($2) );
				  gen( "goto%s%d", L_RET, rlabel(0) );
				  release_value( $2 );
				  tmp_freeall();
				}
	| GOTO target SEMI	{  gen("goto",$2); }
	| target COLON		{  gen(":",   $1); }
	 	      statement

	| IF LP test RP statement	{    gen( ":%s%d", L_NEXT, $3 );
					}

	| IF LP test RP statement ELSE  {   gen( "goto%s%d", L_ELSE, $3 );
					    gen( ":%s%d",    L_NEXT, $3 );
					}
	  statement			{   gen( ":%s%d",    L_ELSE, $3 );
					}






	| WHILE LP test RP	{   push(S_con, $3); push( S_con_label, L_TEST);
				    push(S_brk, $3); push( S_brk_label, L_NEXT);
			      	}
	  statement		{   gen( "goto%s%d", L_TEST, $3 );
				    gen( ":%s%d",    L_NEXT, $3 );
				    pop( S_con ); pop( S_con_label );
				    pop( S_brk ); pop( S_brk_label );
			        }

	| DO			{   static int label;

				    gen(":%s%d", L_DOTOP, $<num>$ = ++label );
				    push( S_con,	label );
				    push( S_con_label,	L_DOTEST );
				    push( S_brk,	label );
				    push( S_brk_label,	L_DOEXIT  );
			        }
	  statement WHILE	{   gen(":%s%d",    L_DOTEST,  $<num>2 ); }
	  LP test RP SEMI	{   gen("goto%s%d", L_DOTOP,   $<num>2 );
				    gen( ":%s%d",   L_DOEXIT,  $<num>2 );
				    gen( ":%s%d",   L_NEXT,    $7 	);
				    pop( S_con );
				    pop( S_con_label );
				    pop( S_brk );
				    pop( S_brk_label );
			        }

	| FOR LP opt_expr SEMI
		 test     SEMI  {
				    gen("goto%s%d", L_BODY,      $5 );
				    gen(":%s%d",    L_INCREMENT, $5 );

				    push(S_con,	$5);
				    push(S_con_label,	L_INCREMENT );
				    push(S_brk,	$5);
				    push(S_brk_label,	L_NEXT	    );
			        }
	  opt_expr RP	        {   gen("goto%s%d", L_TEST,	 $5 );
				    gen(":%s%d",    L_BODY,      $5 );
			        }
	  statement	        {   gen("goto%s%d", L_INCREMENT, $5 );
				    gen( ":%s%d",   L_NEXT,	 $5 );

				    pop( S_con 	     );
				    pop( S_con_label );
				    pop( S_brk       );
				    pop( S_brk_label );
			        }

	| BREAK SEMI		{   if( stack_empty(S_brk) )
					yyerror("Nothing to break from\n");

				    gen_comment("break");
				    gen("goto%s%d", stack_item(S_brk_label,0),
						     stack_item(S_brk,      0));
				}

	| CONTINUE SEMI		{   if( stack_empty(S_brk) )
					yyerror("Continue not in loop\n");

				    gen_comment("continue");
				    gen("goto%s%d", stack_item(S_con_label,0),
						     stack_item(S_con,0      ));
			        }



	| SWITCH LP expr RP
	  {
	       /* Note that the end-of-switch label is the 2nd argument to
		* new_stab + 1; This label should be used for breaks when in
		* the switch.
		*/

		push( S_switch,	new_stab($3, ++Case_label) );
		gen_comment("Jump to case-processing code" );
		gen("goto%s%d", L_SWITCH, Case_label );

		push( S_brk,	   ++Case_label	);
		push( S_brk_label, L_SWITCH   	);

		release_value( $3 );
		tmp_freeall();
	  }
	  compound_stmt
	  {
		gen_stab_and_free_table( pop( S_switch ) );
		pop( S_brk );
		pop( S_brk_label );
	  }

	| CASE const_expr COLON
	  {
		add_case    ( stack_item(S_switch,0), $2, ++Case_label );
		gen_comment ( "case %d:", $2 		 	       );
		gen	    ( ":%s%d"  , L_SWITCH, Case_label	       );
	  }

	| DEFAULT COLON
	  {
		add_default_case( stack_item(S_switch,0), ++Case_label );
		gen_comment("default:");
		gen(":%s%d", L_SWITCH, Case_label );
	  }
	;

target	: NAME	      		{   static char buf[ NAME_MAX ];
				    sprintf(buf, "_%0.*s", NAME_MAX-2, yytext );
				    $$ = buf;
			        }
	;

test	:	      		{   static int label = 0;
				    gen( ":%s%d", L_TEST, $<num>$ = ++label );
			        }
	  expr        	        {
				    $$ = $<num>1;
				    if( IS_INT_CONSTANT($2->type) )
				    {
					if( ! $2->type->V_INT )
					    yyerror("Test is always false\n");
				    }
				    else  /* not an endless loop */
				    {
					gen( "EQ",	     rvalue($2), "0" );
					gen( "goto%s%d", L_NEXT,     $$  );
				    }
				    release_value( $2 );
				    tmp_freeall();
				}
	| /* empty */		{   $$ = 0;  /* no test */
				}
	;
unary
	: LP expr RP 	{ $$ = $2;		      			}
	| FCON	  	{ yyerror("Floating-point not supported\n");	}
	| ICON	  	{ $$ = make_icon ( yytext,  0 );		}
	| NAME 		{ $$ = do_name   ( yytext, $1 );		}



	| string_const 	%prec COMMA
			{
			  $$ = make_scon();
			  yydata( "private\tchar\t%s[]=\"%s\";\n", $$->name,$1);
			}




	| SIZEOF LP string_const RP				%prec SIZEOF
				     { $$ = make_icon(NULL,strlen($3) + 1 ); }

	| SIZEOF LP expr RP	     				%prec SIZEOF
				     { $$ = make_icon(NULL,get_sizeof($3->type));
				       release_value( $3 );
				     }
	| SIZEOF LP abstract_decl RP				%prec SIZEOF
				     {
					 $$ = make_icon( NULL,
							  get_sizeof($3->type));
					 discard_symbol( $3 );
				     }



	| LP abstract_decl RP unary    				  %prec UNOP
	  {
		if( IS_AGGREGATE($2->type) )
		{
		    yyerror( "Illegal cast to aggregate type\n" );
		    $$ = $4;
		}
		else if( IS_POINTER($2->type) && IS_POINTER($4->type) )
		{
		    discard_link_chain( $4->type );
		    $4->type  = $2->type;
		    $4->etype = $2->type;
		    $$ = $4;
		}
		else
		{
		    $$ = tmp_gen( $2->type, $4 );
		}
	  }



	| MINUS	  unary		{ $$ = do_unop( '-', $2 );   }   %prec UNOP
	| UNOP	  unary		{ $$ = do_unop( $1,  $2 );   }

⌨️ 快捷键说明

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