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

📄 c--.y

📁 c—语言的句法分析器。读入一个C--语言程序
💻 Y
📖 第 1 页 / 共 3 页
字号:
      //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 <time.h>

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;
}

⌨️ 快捷键说明

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