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

📄 c--.y

📁 简单实现C--语言的编译器
💻 Y
📖 第 1 页 / 共 3 页
字号:
				sprintf(&code[len],"	cmp	edx , dword ptr [ebp-%d] ; %s\n",$3.place->offset+4,$3.place->name);
	
				len = strlen(code);
				if(strcmp(rop,"le")==0) 	sprintf(&code[len],"	jg	short	"); 
				else if(strcmp(rop,"l")==0)	sprintf(&code[len],"	jge	short	"); 
				else if(strcmp(rop,"g")==0)	sprintf(&code[len],"	jle	short	"); 
				else if(strcmp(rop,"ge")==0) sprintf(&code[len],"	jl	short	"); 
				else if(strcmp(rop,"e")==0)	 sprintf(&code[len],"	jne	short	"); 
				else if(strcmp(rop,"ne")==0)  sprintf(&code[len],"	jne	short	"); 
				len = strlen(code);
			}
			$$.code = (char *)malloc(len + 1);
			strcpy($$.code,code);
		}
	}
	} 
      |   add_expr
	{  $$ = $1; }
      ;

add_expr  :    add_expr addop term
	{  
	char code[1000];
       int len;
	char *op; 
		
	if ($1.is_const && $3.is_const) {   /* constant folding  均为常量*/
       	$$.is_const = 1;
		if($1.type != INT && $1.type != CHAR || $3.type != INT && $3.type != CHAR ){
			fprintf(errfile,"line %d : type unexpected \n",nline);
		 	is_error++; 
			return 0 ;
		}
       	else{
			$$.type = INT;	
              	if ($2 == '+')   $$.value = $1.value + $3.value;  // .value属性表示其值 
			else   $$.value = $1.value - $3.value; 
       	}
	} 
	else {  // 存在未知变量
              op = ($2 == '+')? "add" : "sub";
              $$.place = newtemp();  // 申请一个临时变元t? 
              $$.is_const = 0;
              is_one_var = 0;
	
		/* load the first oprand(操作数) */
              if ($1.is_const)    sprintf(code, "    mov     eax, %d\n", $1.value); 
		else{
			sprintf(code, "    	mov    eax, dword ptr [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); //add  eax, ..
		else{
			sprintf(&code[len], "	%s	eax, dword ptr [ebp-%d] ;%s\n", op,$3.place->offset+4,$3.place->name);  // 或 sub  eax, ...
		}
		len = strlen(code);                                               
              sprintf(&code[len],"	mov	dword ptr [ebp-%d], eax	;%s\n", $$.place->offset+4, $$.place->name);  
							/* mov	[ebp-..],eax;%s   其中%s 为[]地址上对应的变元的name  */
              $$.code = (char *)malloc(strlen(code)+1);
              strcpy($$.code, code);  
	}
       }    
      |   term
      ;
term  :    term mulop unary_expr 
	{  
	char code[1000]; 
       int len;
       char *op; 

	if (verbose) fprintf(stderr, "term => term mulop unary_expr   mulop=%c\n", $2);  
	if ($1.is_const && $3.is_const) {  /* constant folding */
              $$.is_const = 1;
		if($1.type != INT && $1.type != CHAR || $3.type != INT && $3.type != CHAR ){
			fprintf(errfile,"line %d : type unexpected \n",nline);
			is_error++; 
			return 0;
		}
		else{
			$$.type = INT; 
              	if ($2 == '*')	$$.value = $1.value * $3.value; 
			else if($2 == '/'){
				if($3.value == 0) fprintf(errfile,"line %d : fatal error by 0\n",nline);
				$$.value = $1.value / $3.value; 
			}
			else     $$.value = $1.value % $3.value; 
        	}
	}
	else {
              $$.place = newtemp();  // 申请一个临时变元t 
              $$.is_const = 0;
             
		if($2 == '%') op = "mod";   //汇编好象没这个??
              else op = ($2 == '*')? "mul" : "div";
 
		if ($1.is_const)    sprintf(code, "    mov     eax, %d\n", $1.value); 
		else{
			sprintf(code, "    mov    eax, dword ptr [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); //add  eax, ..
		else{
			sprintf(&code[len], "	%s	dword ptr [ebp-%d] ;%s\n", op,$3.place->offset+4,$3.place->name); 
			len = strlen(code);                                               
		}
              sprintf(&code[len],"	mov	dword ptr [ebp-%d], eax	;%s\n", $$.place->offset+4, $$.place->name);   // z这里只考虑没进位的情况,乘的结果保留在低位
							/* mov	[ebp-..],eax;%s   其中%s 为[]地址上对应的变元的name  */
              $$.code = (char *)malloc(strlen(code)+1);
              strcpy($$.code, code); 
       } 
      	}    
      |   unary_expr
      ;

unary_expr  :    unaryop unary_expr 
	{  
	char code [1000];
       int len;
       char *op;

	trace("unary_expr => unaryop unary_expr\n");  
	if($2.is_const) {
		$$.is_const = 1;
		if($2.type != INT && $2.type != CHAR){
			fprintf(errfile,"line %d : type unexpected \n",nline);
			is_error++; 
			return 0;
		}
 		else{	
			$$.type = INT;
			if ($1 == '!'){
				if($2.value == 1 )	$$.value =  0;  //   '!'
				else   $$.value = 0 ;
			}
			else
				$$.value = 0 - $2.value; 
		}
	}
	else{
		op = ($1 == '-')?"uminus":"not";    // 取反操作   汇编没这个符号??
		$$.place = newtemp();  // 申请一个临时变元t 
              $$.is_const = 0;

		if ($2.is_const)	sprintf(code, "	mov	eax, %d\n", 0 - $2.value); 
		else{
			sprintf(code, "	mov	eax,dword ptr [ebp-%d] ;%s\n", $2.place->offset + 4, $2.place->name);  
		}
		len = strlen(code);
		sprintf(&code[len], "	mov	dword ptr [ebp-%d], eax	;%s\n", $$.place->offset + 4, $$.place->name);  
		
		$$.code = (char *)malloc(strlen(code)+1);
              strcpy($$.code, code);
	}
	}
      |   factor
      ;


factor  :      '('    expr   ')'    
	{  trace("factor => ( expr )\n");  
	$$ = $2;
	}
      |   var
	{  
	$$.is_const = 0; 
	$$.place = $1;  
	$$.type = $1->type;
	$$.code = NULL;
	}
      |   call 
	{  
	trace("factor => call\n");
	$$.type = $1.place->ret;

	if(is_funret){   // 有函数返回值
		if($1.place->ret_const){  //返回的是常数
			$$.is_const = 1;
			$$.value = $1.place->retvalue;
		}
		else{
			$$.is_const = 0;
			$$.place = temp_ret;
		}
	is_funret = 0;   // 这样处理不够恰当,当函数被多次调用时
	}

	$$.code = $1.code;   //代码上传

	}
      |   NUM
	{  
	$$.is_const = 1; 
	$$.value = atoi($1);  
	$$.type = INT;
	$$.code = NULL;
	}
      |  STRING_LITERAL
	{
	char text[100];
	int i = 0;  	

	$$.is_const = 1;
	$$.type = CHAR_POINT;
	$$.aa = data_place;   //不这样就经常会出现死循环
	$$.place = $1;
	$$.code = NULL;

	strcpy(text,yytext);
	while(text[i+1] != '\"'){
		text[i] = text[i+1];
		i++;
	}
	if(text[i-1]=='n' && text[i-2] == '\\'){  //有带回车 , \ 和 n是分开的字符
		text[i-2] = '\0';
		const_strings[n_const_strings].is_n = 1;
		const_strings[n_const_strings].index = data_place;
		const_strings[n_const_strings].value = (char *)malloc(strlen(text)+1);
		strcpy(const_strings[n_const_strings].value,text);
		//const_strings[n_const_strings].value = text;
		data_place += strlen(text) + 2;	
	}
	else{
		text[i] = '\0';
		const_strings[n_const_strings].is_n = 0;
		const_strings[n_const_strings].index = data_place;
		const_strings[n_const_strings].value = (char *)malloc(strlen(text)+1);
		strcpy(const_strings[n_const_strings].value,text);   //为什么这样才不会被改变
		//const_strings[n_const_strings].value = text;
		data_place += strlen(text) + 1;	
	}
	//printf("%d   %s\n",0,const_strings[0].value );
	//printf("%d   %s\n",1,const_strings[1].value );
	n_const_strings++;  //常量串的个数
	
	}
     |  CHAR_LITERAL
	{  
	$$.is_const = 1;
	$$.place = $1;
	$$.type = CHAR;
	$$.value = yytext[0];  //字符可以当成是数
	$$.code =NULL;
	}
      ;

call  :    ID   '('    args   ')'  
	{  
	char code[1000];  //代码
	symbol *p;
	paramtp *i,*j;
	int len,t;
	int arg_num=0;
	struct table * tp = table_stack[table_len-1];

	trace("call => ID ( args )\n");
	if((p = lookup_all($1 ,tp))==0){    //没找到有定义
		fprintf(errfile,"line %d:%s error have not defined\n",nline,$1);
		is_error++; 
		return 0;
	}
	else{  // 找到同名标识符
		if(p->type == FUN_DEFINE || p->type == FUN_DECLAR){ //  定义或是声明
			for(i = p->paramer,j = $3;i!=NULL &&j!=NULL;i=i->next,j=j->next){ // 检查参数
				if(i->type != j->type)	break;	
				arg_num++;	//记录参数个数
			}
			if(i!=NULL || j!=NULL){
				fprintf(errfile,"line %d : the type or number of function argvments is unexpected!\n",nline);
				is_error++;
				return 0; 
			}
			else 	$$.place = p;  
		}
		else{  // 找到的不是函数定义或声明,可能是普通变量
			fprintf(errfile,"line %d :%s error have not define \n",nline,$1);
			is_error++;
			return 0;
		}
	}

	/* 过程调用所对应的代码
	......push ..
	......push ..
	......call ..   */
	
	if($3->code != NULL){
		strcpy(code,$3->code);  // push ... 函数参数  但是$3 没有.code ? 
		len = strlen(code);

		t = is_C($1);
		if(t==1){  //判断是否为C 的函数
			sprintf(&code[len],"	call	_%s\n",$1);
			len = strlen(code);
			sprintf(&code[len],"	pop	ecx\n");
			len = strlen(code);
			sprintf(&code[len],"	add	esp,%d\n",4*arg_num);
		}
		else{
			sprintf(&code[len],"	call	%s\n",$1);
			len = strlen(code);
			sprintf(&code[len],"	add	esp,%d\n",4*arg_num);
			len = strlen(code);
		}
	}
	else{
		t= is_C($1);
		if( t==1){  //判断是否为C 的函数
			sprintf(&code[0],"	call	_%s\n",$1);
			len = strlen(code);
			sprintf(&code[len],"	pop	ecx\n");
		}
		else{
			sprintf(&code[0],"	call	%s\n",$1);
			len = strlen(code);
		}
	}
	len = strlen(code);
	$$.code = (char *)malloc(strlen(code)+1);   
	strcpy($$.code, code);

	}
      ;

args  :    arg_list 
	{  
	trace("args => arg_list\n");
 	$$->code = $1->code;  
	}
      |   
	{  
	trace("args => ε\n");
 	 $$->code = NULL;
	}
      ;


arg_list  :    arg_list   ','   expr 
	{  
  	int len;
	char code[1000];
	paramtp *i;
	trace("arg_list => arg_list , expr\n");  
	
	i = (paramtp *)malloc(sizeof(paramtp)); 
	$$ = i;    /* 插入参数表 */
	$$->next = $1;                     
     	$$->type = $3.type ;

	if($3.code == NULL){
	if($3.is_const){   /* 常量参数 */
		if($3.type == INT)	sprintf(code,"	push       %d\n",$3.value);
		else if($3.type == CHAR)  sprintf(code,"	push	'%c'\n",$3.value);
		else{
			if( $3.aa == 0)	sprintf(code,"	push	  offset s@\n");
			else	sprintf(code,"	push      offset  s@+%d\n",$3.aa);  //??偏移量如何求得
		}
	}
	else{
		sprintf(code,"	push	dword ptr [ebp-%d] ; %s\n",$3.place->offset+4,$3.place->name);   // 变量
	}
	}
	else{     
		strcpy(code,$3.code);
		len = strlen(code);
		if($3.is_const){ 
			if($3.type == INT)	sprintf(&code[len],"	push       %d\n",$3.value);
			else if($3.type == CHAR)  sprintf(&code[len],"	push	'%c'\n",$3.value);
			else{
				if( $3.aa == 0)	sprintf(&code[len],"	push	  offset s@\n");
				else	sprintf(&code[len],"	push      offset  s@+%d\n",$3.aa);  //??偏移量如何求得
			}
		}
		else{
			sprintf(&code[len],"	push	dword ptr [ebp-%d] ; %s\n",$3.place->offset+4,$3.place->name);   
		}
	}   
	len = strlen(code);
	strcat(code,$1->code);   // $1 放在 $3  的后面,遵循从右向左压栈的顺序
	len = strlen(code);
	$$->code = (char *)malloc(len + 1);
	strcpy($$->code,code);

	}
      |   expr
	{ 
	int len;
	char code[1000];
	paramtp *i;
	trace("arg_list => expr\n"); 
 
	i = (paramtp *)malloc(sizeof(paramtp)); 	/* 插入参数表 */
	$$ = i; 
	$$->next = NULL;                       
     	$$->type = $1.type;
	
	if($1.code == NULL){
	if($1.is_const){   /* 常量参数 */
		if($1.type == INT)	sprintf(code,"	push       %d\n",$1.value);
		else if($1.type == CHAR)  sprintf(code,"	push	'%c'\n",$1.value);
		else{
			if( $1.aa == 0)	sprintf(code,"	push	  offset s@\n");
			else	sprintf(code,"	push      offset  s@+%d\n",$1.aa);  //偏移量如何求得
		}
	}
	else{
	      sprintf(code,"	push	dword ptr [ebp-%d] ; %s\n",$1.place->offset+4,$1.place->name);   // 
	}
	}

	else{       //前面的参数  
		strcpy(code,$1.code);
		len = strlen(code);
		if($1.is_const){
			if($1.type == INT)	sprintf(&code[len],"	push       %d\n",$1.value);
			else if($1.type == CHAR)  sprintf(&code[len],"	push	'%c'\n",$1.value);
			else{
				if( $1.aa == 0)	sprintf(&code[len],"	push	  offset s@\n");
				else	sprintf(&code[len],"	push      offset  s@+%d\n",$1.aa);  //??偏移量如何求得
			}
		}
		else{
			sprintf(&code[len],"	push	dword ptr [ebp-%d] ; %s\n",$1.place->offset+4,$1.place->name);  
		}
	}    
	len = strlen(code);
	$$->code = (char *)malloc(len + 1);
	strcpy($$->code,code);

	}
      ;

callconvent  :     CDECL 
	{  trace("callconvent =>  __cdecl\n");  }
      |   STDCALL 
	{  trace("callconvent =>  __stdcall\n");  }
      ;
addop :  '+'
	{ $$ = '+';}
	| '-'
	{ $$ = '-';}
	;
relop  :    LE
	{  trace("relop => <= \n"); $$.code = "le"; }
      |    LT
	{  trace("relop  => < \n"); $$.code = "l";  }
      |    GT 
	{  trace("relop  => > \n"); $$.code = "g"; }
      |    GE 
	{  trace("relop  => >= \n"); $$.code = "ge"; }
      |    EQ 
	{  trace("relop  => == \n"); $$.code = "e"; }
      |    NE
	{  trace("relop => !=\n");  $$.code = "ne";}
      ;
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 copyright(){

	printf("* * * * * * * *   C--   ComPiler  * * * * * * * * * * *\n");
	printf("Auther:JDWang    04120087      Complete Data: 07.08.30\n");
	printf("Program Function:\n");
	printf("Use the program ,you can compiler a c-- program ,and build\n");
	printf("a masm program(call masm code).Then you use some tools(LINK...)\n");
	printf("to create an executable file(...exe)\n");
	printf("However,because of several reasons,the compiler is not integrated\n");
	printf("There are maybe some that C can achieve but it not,for example:\n");
	printf("you can main() in C ,but don't use it in my compiler but only\n");
	printf("main(void),and if(j)..  and so on. I think i can conplete all that\n");
	printf("on some day  but it still a hand work!\n\n");
	printf("Usage:    \n");
}
void help(void) { 
	fprintf(stderr, "c-- [-v] sourcefile [targetfile]\n"); 
	exit(1); 
} 

int yyparse();
FILE *errfile;

int main(int argc, char **argv) {

	time_t   start, finish;    //计时
   	char filename[256];

	++argv;	
	--argc;
	if((argc > 0) && (strcmp(argv[0], "-v") == 0)){  // c-- -v ....	
		verbose++; 
		++argv; 
		--argc;   
	}
       if (argc > 0) {       // c-- [-v] sourcefile ...
		yyin = fopen(argv[0],"r");       /* argv[0] 为 soursefile */	
		if(yyin == NULL){
			fprintf(stderr, "cannot open %s\n",argv[0]); 
			exit(1);
		}
	}
	else{
		copyright();
		help();       // c-- [-v]
	}

	++argv;
	--argc;
	if(argc > 0) strcpy(filename, argv[0]); /* argv[0] 为 targetfile */
	else {    	                 //  默认为c--.asm
       	char * dot;
          	strcpy(filename, argv[-1]);      /* argv[-1] 为c-- */
	  	dot = strrchr(filename, '.');    // strrchr
          	if (dot!= NULL) 	*dot = 0;   /* '\0' */
          	strcat(filename, ".asm");      // c--.asm 
       }
          
 	if (verbose) yydebug = 1;   //-v
	yyout = fopen(filename,"w");
	if(yyout== NULL) { 
			fprintf(stderr, "cannot open %s\n", filename); 
			exit(1);
	}	
	
	errfile = fopen("errfile.txt","w+");
   	time(&start);
	yyparse( );    //warning
   	time(&finish);
	if(is_error == 0) fprintf(errfile," Congraduate You!\n Not any error in your file\n");
   	fprintf(stderr, "\nCompiling 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; }   //  yychar
	else if (yychar == ID)   errtok = yylval._ident; 
	else if (yychar < OR)    errtok = tokens[yychar-257]; 
	//else if (yychar == addop) errtok = (char *)yylval._op;     
	else{ 
		sprintf(buf, "%d", yychar); errtok = buf; 
	}
        
	fprintf(stderr, "%s at token %s in line %d\n", s, errtok, nline);
	yyerrok;
}

⌨️ 快捷键说明

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