www.pudn.com > yufafenxiqi.rar > c--.y


%{ 
#include 	 
#include 	 
#include 	 
#include 	 
#include  
 
#define HASHSIZE 128 
//s 
typedef struct aa 
{  int type; 
	struct aa *next; 
} fun_type; 
typedef struct { 
char *name; /* symbol name */ 
int scope; /* scope level */ 
int type; 
int value; 
int funargc; 
fun_type *functype; 
int isdeclar; 
int offset; /* for functions: size of local variables */ 
} symbol ; 
 
struct sym_entry { 
symbol sym; /* this symbol */ 
struct sym_entry *next; /* next entry on hash chain */ 
}; 
 
struct table { 
int level; /* scope level for this table */ 
struct table *previous; /* table at lower scope */ 
struct sym_entry *buckets[HASHSIZE]; /* hash buckets */ 
}; 
 
typedef struct 
{ 
    char op; 
    symbol *x, *y, *z; 
} Quadruple; 
 
 
typedef struct 
{ 
    char *translation; 
    int variable; 
} myattribute; 
 
 
 
struct string_data { 
  int index; 
  char * value; 
}; 
int n_const_strings = 0; 
struct string_data const_strings[100]; 
 
struct table * table_stack[100];  
struct table * global_table;  
int table_len = 0; 
int offset_stack[100]; 
int offset_len = 0; 
int level = 0; 
int verbose = 0; 
int argccount=0; 
int isfunction=0; 
int isdeclartion=0; 
fun_type *funtype=0; 
void trace(char *s) { if (verbose) fprintf(stderr, s); } 
//0 
symbol *lookup(char *name, struct table *tp) { 
struct sym_entry *p; 
unsigned h = ((unsigned)name)&(HASHSIZE-1); /*not素数 */ 
//	printf("look up %s  level  %d       tp.level  %d       table_len-1 %d\n",name,level,tp->level,table_len-1); 
 
do 
for (p = tp->buckets[h]; p; p = p->next) 
if (name == p->sym.name) {return &p->sym;} 
while (tp = tp->previous); 
return 0; 
} 
symbol *lookupred(char *name, struct table *tp) { 
struct sym_entry *p; 
unsigned h = ((unsigned)name)&(HASHSIZE-1); /*not素数 */ 
 
for (p = tp->buckets[h]; p; p = p->next) 
if (name == p->sym.name){//printf("find the symobl %s\n",p->sym.name);  
         return &p->sym;} 
 
return 0; 
} 
 
struct table * mktable(struct table *previous, int level) { 
	int i; 
	struct table *new = (struct table *)malloc(sizeof *new); 
	new->previous = previous; new->level = level; 
	for (i = 0; i < HASHSIZE; i++) new->buckets[i] = 0; 
	return new; 
} 
//i 
symbol *insert(char *name, struct table *tpp) { 
unsigned h = ((unsigned)name)&(HASHSIZE-1); 
struct table *tp = tpp; 
struct sym_entry *p = (struct entry *)malloc(sizeof *p); 
//printf("&&&&&&&&&tp->level =%d level=%d  inserting %s\n", tp->level,level,name); 
if (tp->level < level) { // 当前scope level 
	tp = mktable(tp, level); 
//	printf("make new table\n"); 
	table_stack[table_len] = tp;  
	table_len ++; 
	offset_stack[offset_len] = 0; 
	offset_len ++; 
} 
p->sym.name = name; p->sym.scope = level; 
if(isfunction) { p->sym.type = 1; } 
	else p->sym.type = 0; /*假设是常数, 常数的类型为0*/ 
p->next = tp->buckets[h]; 
p->sym.funargc=0; 
tp->buckets[h] = p; /* 新名字在表头 */ 
//printf("Inset  %s  level  %d       tp.level  %d       table_len-1 %d\n",name,level,tp->level,table_len-1); 
 
return &p->sym; 
} 
 
typedef struct { 
  int is_const; 
  int value; 
  int type; 
  symbol * place; 
  symbol * offset; /* for array */ 
  char * code; 
} expr; 
 
char * insert_id(char *name); 
 
symbol * newtemp() 
{ 
    static int index = 1; 
    char tmpname[20]; 
    char * p; 
    symbol * s; 
    sprintf(tmpname, "__t%d", index); 
    index++; 
    s = insert(insert_id(tmpname), table_stack[table_len-1]); 
    s->offset = offset_stack[offset_len-1]; 
    offset_stack[offset_len-1] += 4; 
    return s; 
} 
%} 
 
%token 	ID  NUM  INT  VOID  CHAR  IF  ELSE WHILE  RETURN   
	CDECL  STDCALL  EQ  NE  LT  GT  LE  GE   AND  OR   
        ADDOP CHARATER STRING 
%start 	program 
 
%right 	'=' 
%left  	ADDOP	 
%left  	'*'     '/'  
 
%union{       char * _ident; 
              char _op; 
              char _relop[3]; 
              int value; 
              symbol *_sym;  
              expr _expr; 
}; 
 
%token <_ident> NUM 
%token <_ident> ID 
%token <_op> CHARATER 
%token <_ident> STRING 
%token <_op> ADDOP 
%type  type_spec 
%type <_sym> var 
%type <_sym> fun_declar 
%type <_sym> fun_tag 
%type  params 
%type  param 
%type  param_list 
%type  args 
%type  arg_list 
%type <_expr> factor 
%type <_expr> unary_expr  
%type <_expr> term 
%type <_expr> add_expr 
%type <_expr> simple_expr 
%type <_expr> logicand_expr 
%type <_expr> logic_expr 
%type <_expr> expr 
%type <_op> mulop 
%type <_op> unaryop  
%type <_relop> relop 
//%token <_op> unaryop  
/* 为了简单起见,把所有能产生代码的非终极符也说明为_expr类型,其实应该用别的,但是也有code属性*/ 
%type <_expr> comp_stmt 
%type <_expr> if_stmt 
%type <_expr> while_stmt 
%type <_expr> stmt_list 
%type <_expr> stmt 
%type <_expr> expr_stmt  
%type <_expr> return_stmt 
%type <_expr> call 
 
%% 
program  :    M declar_list 
	{  fprintf(yyout, "	.data\n"); 
       { int i; 
        struct sym_entry *p; 
          
        for (i = 0; i< n_const_strings; i++) { 
 	   	fprintf(yyout, "s@%d	label	byte", const_strings[i].index); 
		fprintf(yyout, "	db	\"%s,0\"",const_strings[i].value); /* \n可能需要变成 10 */ 
        } 
       /* 生成全局变量 */ 
        for (i = 0; i< HASHSIZE; i++) { 
			p = global_table->buckets[i]; /* hash buckets */ 
			while (p) { 
				if (p->sym.type == INT) fprintf(yyout, "_%s	DD	?\n", p->sym.name); else 
				if (p->sym.type == CHAR) fprintf(yyout, "_%s	DB	?\n", p->sym.name); 
				p = p->next; 
			} 
	    } 
	   fprintf(yyout, "	public	_main\n"); 
	 
	   fprintf(yyout, "	end\n"); 
     }} 
      ; 
M : {    
	fprintf(yyout, "	.386p\n"); 
	fprintf(yyout, "	model flat\n"); 
	fprintf(yyout, "	.code\n"); 
	      
	global_table = mktable(NULL, 0);  
	table_stack[table_len] = global_table;  
	table_len ++; 
	offset_stack[offset_len] = 0; 
	offset_len ++; 
} 
     ; 
declar_list  :    declar_list declar  
	{  trace("declar_list => declar_list declar\n");  } 
      |   declar 
      ; 
declar  :    var_declar  
      |   fun_declar 
      ; 
var_declar  :    type_spec   ID   ';'  
	{   
		//1 
	struct table * tp = table_stack[table_len-1]; 
	if(lookupred($2,tp)==0){ 
	symbol * p = insert($2, tp); 
  int width = 0; 
	p->type = $1; 
	p->offset = offset_stack[offset_len-1]; 
    if ($1 == INT) width = 4; else if ($1 == CHAR) width = 1; 
        offset_stack[offset_len-1] += width; 
    }else   printf("line %d: error: %s :redefinition\n", nline, $2); 
    	   
	  trace("var_declar => type_spec ID  ;\n");  
	    } //12 
      |   type_spec   ID  '['  NUM  ']'     ';' 
	{  struct table * tp = table_stack[table_len-1]; 
	   trace("var_declar => type_spec ID [ NUM ] ;\n");   
	   if(lookupred($2,tp)==0){	  
	    symbol * p = insert($2, tp);  
        int width = 0; 
        int widthall=width; 
	      p->type = $1; 
	      p->offset = offset_stack[offset_len-1]; 
        if ($1 == INT) width = 4; else if ($1 == CHAR) width = 1; 
        offset_stack[offset_len-1] += widthall; 
    }else   printf("line %3d error: %s :redefinition\n", nline, $2);     
	}  //13 
      |   type_spec   '*'  ID   ';'  
	{ struct table * tp = table_stack[table_len-1];  
		trace(" var_declar =>  type_spec * ID ;\n"); 
		if(lookupred($3,tp)==0){	  
	    symbol * p = insert($3, tp);  
        int width = 0; 
        int widthall=width; 
	      p->type = $1; 
	      p->offset = offset_stack[offset_len-1]; 
        if ($1 == INT) width = 4; else if ($1 == CHAR) width = 1; 
        offset_stack[offset_len-1] += widthall; 
	   }else   printf("line %3d error: %s :redefinition\n", nline, $3);	   
  } 
      |   type_spec   '*'  ID  '['  NUM  ']'     ';' 
	{  
		 struct table * tp = table_stack[table_len-1];  
		 trace("var_declar =>  type_spec * ID [ NUM ] ;\n");  
		 if(lookupred($3,tp)==0){	  
	    symbol * p = insert($3, tp);  
        int width = 0; 
        int widthall=width; 
	      p->type = $1; 
	      p->offset = offset_stack[offset_len-1]; 
        if ($1 == INT) width = 4; else if ($1 == CHAR) width = 1; 
        offset_stack[offset_len-1] += widthall; 
		   }else   printf("line %3d error: %s :redefinition\n", nline, $3);	 
		 } 
		  |  error  '\n' 
		 
      ; 
type_spec  :    INT 
	{  $$ = INT;  //printf("type_spec   %d\n",$$);  
		} 
      |   VOID  
	{  $$ = VOID;  //printf("type_spec   %d\n",$$);  
		} 
      |   CHAR 
	{  $$ = CHAR;  //printf("type_spec   %d\n",$$); 
		} 
      | error {fprintf(stderr, "line %d :type name expected\n",nline); yyerrok; }  
      ; 
//3 
fun_declar  :    type_spec  fun_tag   '(' LL params   ')'  comp_stmt 
	{  fprintf(yyout, "_%s	proc	near\n", $2->name);   
	   fprintf(yyout, "	push      ebp\n"); 
	   fprintf(yyout, "	mov       ebp,esp\n"); 
           $2->offset = offset_stack[offset_len-1]; 
           $2->type=$1; 
        //   printf("function type is %d\n",$2->type); 
	   fprintf(yyout, "	sub	  esp, %d\n", $2->offset); 
	   fprintf(yyout, "%s\n", $7.code); 
	   fprintf(yyout, "	.....\n"); 
	   fprintf(yyout, "	ret\n"); 
	   fprintf(yyout, "_%s	endp\n\n", $2->name);   
	    
	    printf("_%s	:\n", $2->name); 	 
	      if($2->isdeclar==1) { 
	      	 	fun_type *p1=$2->functype,*p2=funtype;int i; 
	      	 	if($2->funargc!=$5) printf("     Type mismatch(defined more than declartion) in redeclaration of %s\n",$2->name);      	 
	      		 for(i=1;i<=$5;i++) 
	      		  {   
	      		  	if(p1==0||p2==0) break; 	      		  	  
	      		  	if(p1->type!=p2->type)  
	      		  	 printf("        Parater %d Type mismatch in redeclaration of %s\n",i,$2->name);  
	      		  	   p1=p1->next; p2=p2->next;	      		  	   
	      		  }   		  
	      		}else { 
	      			$2->funargc=$5; 
	             $2->functype=funtype; 
	      		//	printf("%d  = \n",$2->funargc); 
	      			 
	      			} 
           offset_len--; 
           table_len--; 
          // printf("                                            argc %d\n", $5); 
           level--; 
           funtype=0; 
        // printf("Level -------- %d   %d\n",level, table_len-1); 
           trace("fun_declar =>  type_spec  fun_tag   '(' LL params   ')'  comp_stmt	\n"); 
        } 
      |   type_spec  fun_tag   '(' LL   params   ')'      ';'		 
	{ 
// fprintf(yyout, "extrn	_%s:near\n", $2->name);    
	//55  
	trace("fun_declar => type_spec  fun_tag   '(' LL   params   ')'      ';'	\n"); 
// printf("ok here\n"); 
//printf("$5=========  %d\n",$5); 
	$2->isdeclar=1; 
	$2->funargc=$5; 
	$2->functype=funtype; 
	      funtype=0; 
	      table_len--; 
       // printf("aideclar %d   far    %d\n", $2->isdeclar,$5); 
        level--; 
       // printf("end of function declar _%s	\n\n", $2->name);  
		} 
		 |   type_spec  fun_tag   '(' LL   params   ')'  
		  { 
		 	printf("line %d:function %s declaration missing ;\n",nline-1,$2->name); 
		 	} 
      ; 
//2 
LL: ;{level++;trace("LL => ;\n"); insert(NULL, table_stack[table_len-1]); 
	// printf("Level -------- %d   %d\n",level, table_len-1);  
	 }       
fun_tag  :    callconvent  ID 
	{   
			struct table * tp = table_stack[table_len-1]; 
			symbol *tmp; 
			isfunction=1; 
			trace("fun_tag => callconvent  ID\n");   
		//   printf("Before insert %s inserat  level  %d       tp.level  %d       table_len-1 %d\n",$2,level,tp->level,table_len-1); 
			if((tmp=lookupred($2,tp))==0){	  
			 symbol * p; 
	     $$ = insert($2, table_stack[table_len-1]);   
	   }else { 
	   	$$=tmp; 
	   	if(tmp->type==1){ 
	        if(tmp->isdeclar==0) printf("line %d :error: %s :fuction redefinition\n", nline, $2); 
	         else  { $$=tmp ;} 
	   }else		 
	    	printf("line %d :error: %s :redefinition\n", nline, $2); 
	  } 
	   	isfunction=0; 
	} 
       |   ID 
	{  
		struct table * tp = table_stack[table_len-1]; 
		   symbol *tmp; 
			isfunction=1; 
		 
		  trace("fun_tag =>ID\n");   
	//   printf("Before insert %s inserat  level  %d       tp.level  %d       table_len-1 %d\n",$1,level,tp->level,table_len-1); 
			if((tmp=lookupred($1,tp))==0){	 
			 symbol * p; 
	     $$ = insert($1, table_stack[table_len-1]);   
	     }else { 
	     		$$=tmp; 
	   	if(tmp->type==1){ 
	        if(tmp->isdeclar==0)  {printf("line %d :error: %s :fuction redefinition\n", nline, $1);} 
	        	 else {$$=tmp ;} 
	   }else		 
	    	{printf("line %d :error: %s :redefinition\n", nline, $1);} 
	  } 
			 isfunction=0;  
		 } 
       ;	 
params  :    param_list  
	{  trace("params => param_list \n");   
        $$ = $1;          
         } 
      |VOID 
	{ trace("params => VOID \n");  argccount=0; 
	  $$ = 0;  
	  } 
      ; 
param_list  :    param_list   ',' param  
	{  trace("param_list => param_list , param \n");  $$ = $1+$3;   } 
      |   param 
	{  trace("param_list => param\n");  $$ = $1;  } 
      ; 
 //22 
param  :    type_spec ID  
	{  trace("param => type_spec ID\n");  
	         $$ = 1;  
        { 
	struct table * tp = table_stack[table_len-1]; 
  //33        
 if(lookupred($2,tp)==0){ 
	      symbol * p = insert($2, tp); 
	       int width=0; 
	      fun_type *tmp; fun_type *pp; 
	      tmp=(fun_type *)malloc(sizeof(fun_type)); 
	      tmp->type=$1; 
	      tmp->next=0; 
	      if(funtype==0) { 
	      	funtype=tmp;  
	      } 
	      	else {	       
	      	  	pp=funtype; 
	      		  while(pp->next){  
	      		 	   pp=pp->next; 
	      		  	} 
	      	  	pp->next=tmp; 
	      		} 
 
	      p->type = $1; 
	      p->offset = offset_stack[offset_len-1];  
       // if ($1 == INT) width = 4; else if ($1 == CHAR) width = 1; 
       //offset_stack[offset_len-1] -= width; 
    }else printf("line %d :error %s :redefinition\n", nline, $2);   
     
    } 
        $$ = 1; // printf("ok here\n"); 
  } 
      |   type_spec   '*'  ID  
	{  trace("param => type_spec * ID \n"); 
		 
		 { 
	struct table * tp = table_stack[table_len-1]; 
	 if(lookupred($3,tp)==0){ 
      	symbol * p = insert($3, tp); 
        int width = 0; 
            fun_type *tmp; fun_type *pp; 
	      tmp=(fun_type *)malloc(sizeof(fun_type)); 
	      tmp->type=$1; 
	      tmp->next=0; 
	      if(funtype==0) { 
	      	funtype=tmp;  
	      } 
	      	else {	       
	      	  	pp=funtype; 
	      		  while(pp->next){  
	      		 	   pp=pp->next; 
	      		  	} 
	      	  	pp->next=tmp; 
	      		} 
	      p->type = $1; 
	      p->offset = offset_stack[offset_len-1];  
        if ($1 == INT) width = 4; else if ($1 == CHAR) width = 1; 
        offset_stack[offset_len-1] -= width; 
        }else   printf("line %d :error: %s :redefinition\n", nline, $3);   
 
        } $$ = 1;  
		  } 
      |   type_spec ID  '['    ']'   
	{  trace("param => type_spec ID [ ]\n");  
		 { 
	struct table * tp = table_stack[table_len-1]; 
	 if(lookupred($2,tp)==0){ 
 
       	symbol * p = insert($2, tp); 
        int width = 0; 
            fun_type *tmp; fun_type *pp; 
	      tmp=(fun_type *)malloc(sizeof(fun_type)); 
	      tmp->type=$1; 
	      tmp->next=0; 
	      if(funtype==0) { 
	      	funtype=tmp;  
	      } 
	      	else {	       
	      	  	pp=funtype; 
	      		  while(pp->next){  
	      		 	   pp=pp->next; 
	      		  	} 
	      	  	pp->next=tmp; 
	      		} 
        p->type = $1; 
	      p->offset = offset_stack[offset_len-1];  
        if ($1 == INT) width = 4; else if ($1 == CHAR) width = 1; 
        offset_stack[offset_len-1] -= width; 
        }else   printf("line %d :error: %s :redefinition\n", nline, $2);   
    } $$ = 1;  
 }  
      ; 
      //66 
comp_stmt  :    '{'  local_declars stmt_list  '}' 
	{  $$ = $3; trace(" comp_stmt => local_declars stmt_list\n"); } 
      ; 
local_declars  :    local_declars var_declar  
      |    
	{  trace(" local_declars => ε\n");  } 
      ; 
stmt_list  :    stmt_list stmt  
	{   char * s; 
		  trace(" stmt_list =>  stmt_list stmt \n"); 
	    $$=$2; 
	 //   assert($1.code != NULL); 
	  //  assert($2.code != NULL); 
	 //   s = (char *)malloc(strlen($1.code) + strlen($2.code)+1); 
    //        strcpy(s, $1.code); 
     //       strcat(s, $2.code); 
             
    //    $$.code = s;   
        /*释放内存!*/ 
        /*free($1.code); free($2.code); */ 
     } 
      |       
	{  $$.code = "";  trace("empty stmt_list\n");} 
      ; 
stmt  :    expr_stmt  
	{  $$=$1;  trace("stmt => expr_stmt\n");  } 
      |   comp_stmt  
	{   $$=$1; trace("stmt => comp_stmt\n");  } 
      |   if_stmt  
	{   $$=$1; trace("stmt => if_stmt\n"); } 
      |   while_stmt  
	{    trace("stmt => while_stmt\n");  } 
      |   return_stmt 
	{   $$=$1; trace("stmt => return_stmt\n");  } 
      ; 
expr_stmt  :    expr   ';' 
	{  
		trace("expr_stmt => expr ;\n"); 
		 //77 
		/* if (verbose){ 
		 	  if($1.type==INT)  
		 	  fprintf(stderr, "expr_stmt => expr ; type is int code=%d\n", $1.value); 
		 	  else if($1.type==CHAR)  
		 	  	  fprintf(stderr, "expr_stmt => expr ; type is char  code=%s\n", $1); 
		 	  }*/ 
		 	   
	   $$=$1;   
}  
      |     ';' 
	{  trace("expr_stmt => ;\n");  } 
      ; 
if_stmt  :   IF  '('    expr   ')'    stmt 
	{  trace("if_stmt => if ( expr ) stmt\n"); $$=$5; }  
      |   IF   '('    expr   ')'    stmt ELSE stmt 
	{  trace("if_stmt => if ( expr ) stmt else stmt\n"); $$.code="if------"; } 
      ; 
while_stmt  :    WHILE   '('    expr   ')'    stmt 
	{  trace("while_stmt => while ( expr ) stmt\n");  } 
      ; 
return_stmt  :    RETURN   ';'  
	{  trace("return_stmt => return ; \n");  } 
      |   RETURN expr   ';' 
	{  trace("return_stmt => return expr ;\n");  
	   $$ = $2;  } 
      ; 
expr  :    var  '='  expr  
 	{  char code [1000]; 
		trace("expr =>   var  '='  expr  \n"); 
		    if ($1 != 0) { 
               if ($1->type != $3.type) { 
           //   printf("var type is %d   expr type is %d \n",$1->type,$3.type); 
                   printf("line %d :error  : = :the left and the right type does not match\n", nline, $1);                    
               } 
               $$.type = $1->type; 
		  } 
	/*	if ($3.is_const) sprintf(code, "	mov	[ebp-%d], %d	;%s\n", $1->offset+4, $3.value, $1->name);   
                else { int len;  
                      strcpy(code, $3.code); 
                      len = strlen(code); 
                      sprintf(&code[len], "	mov	%s, %s\n", $1->name, $3.place->name);   
                       } 
                $$.code = (char *)malloc(strlen(code)+1); 
                strcpy($$.code, code); 
               fprintf(yyout, code); 
*/ 
 
}	 
      |   logic_expr{ 
      	trace("expr =>  logic_expr ; \n"); 
      	$$.type=$1.type; 
      //	printf("expr =>  logic_expr  type is %d \n",$$.type); 
      	} 
      ;  
      //4 
var  :    ID 
	{  if (verbose) fprintf(stderr, "look for %s\n", $1); 
	   $$ = lookup($1, table_stack[table_len-1]);   
           if ($$ == NULL) { fprintf(stderr, "line %d :undeclared identifier: %s \n", nline, $1);  
            
           	  
           	}//	else printf("var id type is %d \n",$$->type);  
}  
      |   ID  '['  expr    ']'  
	{  trace("var => ID  [ expr ]\n");  
	 $$ = lookup($1, table_stack[table_len-1]);   
           if ($$ == NULL) { fprintf(stderr, "line %d :undeclared identifier: %s \n", nline, $1);  
           	//exit(0); 
           	} 
	 } 
      ; 
logic_expr  :    logic_expr OR logicand_expr    ///new added productions!! 
	{  trace("logic_expr => logic_expr OR logicand_expr\n");  
	   if($1.value||$3.value) $$.value=1; 
	    else $$.value=0; 
	     $$=$3; 
	   }  
      |   logicand_expr 
	{  trace("logic_expr => logicand_expr\n"); $$=$1; 
	  	//printf("expr =>  logic_expr  type is %d \n",$$.type); 
	 }  
      ; 
logicand_expr  :   logicand_expr AND simple_expr 
	{  trace("logicand_expr => logicand_expr AND simple_expr\n");  
	   
	   if($1.value&&$3.value) $$.value=1; 
	    else $$.value=0; 
	    $$.type=$3.type; 
	 }  
      |   simple_expr 
    { trace("logicand_expr => simple_expr\n");  
     $$=$1; 
     //printf("ogicand_expr => simple_expr type is %d \n",$$.type); 
      } 
      ;  
      //l 
simple_expr  :    add_expr relop add_expr 
	{   
	// printf("here is me %%%%%%%%%%%\n"); 
	  trace("simple_expr => add_expr relop add_expr\n");   
		$$.type=INT; 
	//	printf("simple_expr type is %d\n",$$.type); 
		 if (($1.type == INT || $1.type == CHAR) && ($3.type == INT || $3.type == CHAR)) { 
	  if($2=="<"){ 
	    if($1.value<$3.value){$$.value=1;}else $$.value=0; 
	  }else if($2=="<="){ 
	    if($1.value<=$3.value){$$.value=1;}else $$.value=0; 
	  }else if($2=="=="){ 
	    if($1.value==$3.value){$$.value=1;}else $$.value=0; 
	  }else if($2==">"){ 
	    if($1.value>$3.value){$$.value=1;}else $$.value=0; 
	  }else if($2==">="){ 
	    if($1.value>=$3.value){$$.value=1;}else $$.value=0; 
	  } 
	} 
	 if ($1.type != INT && $1.type != CHAR) { 
               printf("line %3d error: %s :illegal, left operand is not constant or character\n", nline, $2); 
           } 
   if ($3.type != INT && $3.type != CHAR) { 
              printf("line %3d error: %s :illegal, right operand is not constant or character\n", nline, $2); 
         } 
	  }  
      |   add_expr { 
       trace("simple_expr => add_expr\n");   
       if($1.value!=0) $$.value=0;else $$.value=1; 
       	$$.type = $1.type; 
       //	printf("simple_expr type is %d\n",$$.type); 
      } 
      ; 
add_expr  :    add_expr ADDOP term 
	{   
		trace("add_expr  =>  add_expr ADDOP term\n");   
		$$.type = INT; 
           if ($1.type == INT && $3.type == INT) { 
               if ($2 == '+') { 
                   $$.value = $1.value + $3.value; 
               } else { 
                   $$.value = $1.value - $3.value;    
               } 
           } 
           if ($1.type != INT) { 
               printf("line %3d error: %c :illegal, left operand is not constant\n", nline, $2); 
           } 
           if ($3.type != INT) { 
               printf("line %3d error: %c :illegal, right operand is not constant\n", nline, $2); 
           } 
		 
		 
	         if ($1.is_const && $3.is_const) {  /* constant folding */ 
               $$.is_const = 1; 
               if ($2 == '+') $$.value = $1.value + $3.value; else $$.value = $1.value - $3.value;  
           } else { 
               char code [1000]; 
               int len; 
               char * op = ($2 == '+')? "add" : "sub"; 
               $$.place = newtemp(); 
               $$.is_const = 0; 
               /* load the first oprand */ 
               if ($1.is_const) sprintf(code, "	mov	eax, %d\n", $1.value); else 
                  sprintf(code, "	mov	eax, [ebp-%d]	;%s\n", $1.place->offset+4, $1.place->name);   
               len = strlen(code); 
               if ($3.is_const) sprintf(&code[len], "	%s	eax, %d\n", op, $3.value); else 
                   sprintf(&code[len], "	%s	eax, %s\n", op, $3.place->name);  
               len = strlen(code); 
              sprintf(&code[len], "	mov	[ebp-%d], eax	;%s\n", $$.place->offset+4, $$.place->name);   
                $$.code = (char *)malloc(strlen(code)+1); 
                strcpy($$.code, code); 
               }  
        }     
      |   term  
      { 
      $$.type = $1.type; 
   //   printf("add_expr  => term type is %d\n",$$.type); 
      	trace("add_expr  => term\n");   
      } 
      ; 
term  :    term mulop unary_expr  
	{  if (verbose)  fprintf(stderr, "term => term mulop unary_expr   mulop=%c\n", $2);   
	  	trace("term => term mulop unary_expr \n"); 
	 $$.type = INT; 
           if ($1.type == INT && $3.type == INT) { 
               if ($2 == '*') { 
                   $$.value = $1.value * $3.value; 
               } else if ($2 == '/') { 
                   $$.value = $1.value / $3.value;    
               } else { 
                   $$.value = $1.value % $3.value;  
               } 
           } 
           if ($1.type != INT) { 
               printf("line %3d error: %c :illegal, left operand is not constant\n", nline, $2); 
           } 
           if ($3.type != INT) { 
               printf("line %3d error: %c :illegal, right operand is not constant\n", nline, $2); 
           } 
	 
	 
	if ($1.is_const && $3.is_const) {  /* constant folding */ 
	   
               $$.is_const = 1; 
               if ($2 == '*') $$.value = $1.value * $3.value; else $$.value = $1.value / $3.value; /* does not handle '%' yet */ 
           } else { 
               char code [1000]; 
               int len; 
               char * op = ($2 == '*')? "mul" : "div"; 
               $$.place = newtemp(); 
               $$.is_const = 0; 
               /* load the first operand */ 
               if ($1.is_const) sprintf(code, "	mov	eax, %d\n", $1.value); else 
                  sprintf(code, "	mov	eax, [ebp-%d]	;%s\n", $1.place->offset+4, $1.place->name);   
               len = strlen(code); 
               if ($3.is_const) sprintf(&code[len], "	%s	eax, %d\n", op, $3.value); else 
                   sprintf(&code[len], "	%s	eax, %s\n", op, $3.place->name);  
               len = strlen(code); 
               sprintf(&code[len], "	mov	[ebp-%d], eax	;%s\n", $$.place->offset+4, $$.place->name);   
                $$.code = (char *)malloc(strlen(code)+1); 
                strcpy($$.code, code); 
               }  
        }     
      |   unary_expr { 
      	  $$.type = $1.type; 
      	 //   printf("term =>unary_expr  type is %d\n",$$.type); 
      	   	trace("term =>unary_expr \n"); 
      	} 
      ; 
unary_expr  :    unaryop unary_expr  
	{  trace("unary_expr => unaryop unary_expr\n"); 
		 $$.type = INT; 
		   if ($2.type == INT) { 
               if ($1 == '!') { 
                   	if($2.value==0) $$.value=1;else $$.value=0; 
               } else { 
                   $$.value = -$2.value;  
               } 
           } 
           if ($2.type != INT) { 
               printf("line %3d error: %c :illegal, right operand is not constant\n", nline, $1); 
           } 
		  
		    
		 if($1=='!') 
		 	if($2.value==0) $$.value=1;else $$.value=0; 
		 else if($1=='-') $$.value =-$2.value; 
		} 
      |   factor 
        { 
      	 trace("unary_expr =>  factor\n");   
      	$$.value=$1.value;   
      	$$.type = $1.type; 
      	//  printf("unary_expr =>factor  type is %d\n",$$.type); 
      	} 
      ; 
factor  :      '('    expr   ')'     
	{  trace("factor => ( expr )\n"); $$.value=$2.value;$$.type = $2.type; } 
      |   var 
	{  trace("factor => var\n"); $$.is_const = 0; $$.place = $1; $$.type = $1->type; } 
      |   call  
	{  trace("factor => call\n"); $$.value=$1.value; $$.type = $1.type;  // printf("factor>>call  type is %d\n",$$.type); 
	} 
      |   NUM 
	{  trace("factor => NUM\n"); $$.is_const = 1; $$.value = atoi($1);  $$.type = INT; } 
      |  STRING { 
      trace("factor => STRING \n");$$.type=CHAR; 
      } 
      | CHARATER{ 
     trace("factor => CHARATER \n"); $$.type=CHAR; 
      } 
      ; 
call  :    ID   '('    args   ')'   
	{   
		 symbol *tmp = lookup($1, table_stack[table_len-1]); 
		 trace("call => ID ( args )\n");  
		  if(0!=tmp)  { $$.type=tmp->type;    } 
	//   printf("                                               fun call args is %d\n",$3); 
	 //  printf("                                  call >> id  type is %d\n",$$.type); 
	  
	   
	   if (0 == tmp) { 
          printf("line %3d error: %s :undeclared function\n", nline, $1);              
           } 
      else { 
       
      		fun_type *p1=tmp->functype,*p2=funtype;int i; 
      			 //printf("args   %d   ===%d \n",$3,tmp->funargc); 
      	   if(tmp->funargc>$3) printf("line %d  Too fewer (%d)parameters in call to fuction of %s \n",nline,tmp->funargc-$3,tmp->name); 
	         else 	if(tmp->funargc<$3) printf("line %d Too much (%d)parameters in call to fuction of %s \n",nline,$3-tmp->funargc,tmp->name);  	   	  
	       	 for(i=1;i<=$3;i++) 
	      		  {  
	      		  	if(p1==0||p2==0) break; 	      		  	  
	      		  	if(p1->type!=p2->type)  printf("line %d Parater %d Type mismatch in call to fuction  of %s \n",nline,i,tmp->name);  
	      		  	   p1=p1->next; p2=p2->next;	      		  	   
	      		  }     
      	}   
             funtype=0;  
	       $$.code = malloc(1000); 
	       sprintf($$.code, "	push ...\n	call %s\n", $1); 
	} 
      ;  
args  :   arg_list  
	{  $$=$1;trace("args => arg_list\n");  } 
      |    
	{ $$=0;  trace("args => ε\n");  } 
      ; 
arg_list  :    arg_list   ',' expr  
	{   
		    fun_type *tmp; fun_type *pp; 
	      tmp=(fun_type *)malloc(sizeof(fun_type)); 
	      tmp->type=$3.type; 
	      tmp->next=0; 
	      if(funtype==0) { 
	      	funtype=tmp;  
	      } 
	      	else {	       
	      	  	pp=funtype; 
	      		  while(pp->next){  
	      		 	   pp=pp->next; 
	      		  	} 
	      	  	pp->next=tmp; 
	      		} 
		 
		$$=$1 + 1;  
		trace("arg_list => arg_list , expr\n");  
		 } 
      |   expr 
	{   
		  fun_type *tmp; fun_type *pp; 
	      tmp=(fun_type *)malloc(sizeof(fun_type)); 
	      tmp->type=$1.type; 
	      tmp->next=0; 
	      if(funtype==0) { 
	      	funtype=tmp;  
	      } 
	      	else {	       
	      	  	pp=funtype; 
	      		  while(pp->next){  
	      		 	   pp=pp->next; 
	      		  	} 
	      	  	pp->next=tmp; 
	      		} 
		$$=1;trace("arg_list => expr\n");  
		 
		 } 
      ; 
callconvent  :     CDECL  
	{  trace("callconvent =>  __cdecl\n");  } 
      |   STDCALL  
	{  trace("callconvent =>  __stdcall\n");  } 
      ; 
/*      |    
	{  trace("callconvent => ε \n");  }  
      ;*/ 
relop  :    LE 
	{  trace("relop => <= \n");  } 
      |    LT 
	{  trace("relop  => < \n");  } 
      |    GT  
	{  trace("relop  => > \n");  } 
      |    GE  
	{  trace("relop  => >= \n");  } 
      |    EQ  
	{  trace("relop  => == \n");  } 
      |    NE 
	{  trace("relop => !=\n");  } 
      ; 
mulop  :      '*'   
	{  trace("mulop => * \n"); $$ = '*'; } 
      |      '/'  
	{  trace("mulop => / \n"); $$ = '/'; } 
      |      '%'  
	{  trace("mulop => % \n"); $$ = '%';  } 
      ; 
unaryop  :   '!' 
	{  trace("unaryop => !\n");  $$ = '!'; } 
      |     '-' 
	{  trace("unaryop => -\n");  $$ = '-';  } 
      ; 
 
%% 
#include "lex.yy.c" 
#include  
 
void help(void) { fprintf(stderr, "c-- [-v] sourcefile [targetfile]\n"); exit(1); }  
 
int main(int argc, char **argv) { 
   time_t   start, finish; 
   char filename[256]; 
 
	++argv; 
	--argc; 
	if((argc > 0) && (strcmp(argv[0], "-v") == 0)) { verbose++; ++argv; --argc; } 
        if (argc > 0) yyin = fopen(argv[0],"r"); else help(); 
	++argv; 
	--argc; 
	if(argc > 0) strcpy(filename, argv[0]); 
	else { 
          char * dot; 
          strcpy(filename, argv[-1]);  
	  dot = strrchr(filename, '.'); 
          if (dot != NULL) *dot = 0; 
          strcat(filename, ".asm"); 
        } 
        yyout  = fopen(filename, "w"); 
        if (yyout == NULL) { fprintf(stderr, "cannot open %s\n", filename); exit(1); } 
 	if (verbose) yydebug = 1; 
 
   	time( &start ); 
	yyparse( );  
   	time( &finish ); 
   	fprintf(stderr, "compiling to %s, takes %1.1f seconds.\n", filename, difftime( finish, start )); 
	return 0; 
} 
 
yyerror(char *s) { 
	static char * tokens[]={"ID",  "NUM",  "INT",  "VOID", "CHAR", "if", "else", "while", "return", "cdecl", 
        	"stdcall", "=", "!=", "<", ">", "<=", ">=", "and", "or"}; 
      	char *errtok, buf[256]; 
      	if (yychar < 256) { sprintf(buf, "%c", yychar); errtok = buf; } else 
      	if (yychar == ID) errtok = yylval._ident; else 
        if (yychar < OR) errtok = tokens[yychar-257]; else 
        if (yychar == ADDOP) errtok = yylval._op; else 
        { sprintf(buf, "%d", yychar); errtok = buf; } 
         
	fprintf(stderr, "line %d :%s at token %s \n", nline,s, errtok); 
	yyerrok; 
}