阅读背景:

基于C语言的TEST语言词法,语法,语义分析及虚拟机生成代码_陈帅的小黑屋_c语言test怎么用

来源:互联网 
//词法分析
#include<stdio.h>
#include<ctype.h>
#include<string.h>

//保留字数目与保留字数组 
#define keywordSum 10
char *keyword[keywordSum] = {"if","else","for","while","read","write","do","int","call","function"};

//纯单分界符
char singleword[50] = "+-*(){};,:";

//双分界符首字符
char doubleword[10] = "<>=!";

//用于接收输入输出文件名 
extern char Scanin[300],Scanout[300]; 

//用于指向输入输出文件的指针 
extern FILE *fin,*fout; 

//用于对保留字数组进行冒泡排序函数(为折半查找做准备)
void sort(char *KW[]){
	int i,j;
	char *temp;
	for(i=0;i<keywordSum;i++){
		for(j=0;j<keywordSum-1;j++){
			if(strcmp(KW[j],KW[j+1])>0){
				temp = KW[j];
				KW[j] = KW[j+1];
				KW[j+1] = temp;
			}
		}
	}
}

//用于查找保留字表的折半查找函数(保留字不区分大小写)
int Search_Bin(char *KW[],char *keyword){
	sort(KW);
	int low=0,high=keywordSum-1;
	int mid;
	while(low<=high){
		mid = (low+high)/2;
		if(stricmp(keyword,KW[mid])==0) return 1;		//stricmp比较不区分大小写 返回1表示查找到 
		else if(stricmp(keyword,KW[mid])>0) low=mid+1;
		else high=mid-1; 
	}
	return 0;											//返回0表示查找失败 
} 

int TESTscan(){
	char ch,token[40];									//ch用于保存当前读出的字符,token用于保存识别出的单词
	int es=0,j,n;										//es为错误识别代码,0表示没有错误。
	int linenum=1;										//用于保存行号 
	printf("请输入源程序文件名(包括路径):");
	scanf("%s",Scanin);
	printf("请输入词法分析输出文件名(包括路径):");
	scanf("%s",Scanout);
	if((fin = fopen(Scanin,"r"))==NULL){
		printf("\n打开词法分析输入文件出错!\n");
		return 1;										//输入文件出错返回错误代码1 
	}
	if((fout = fopen(Scanout,"w"))==NULL){
		printf("\n打开词法分析1输出文件出错!\n");
		return 2; 										//输出文件出错返回错误代码2 
	}
	ch = getc(fin);
	while(ch!=EOF){
		while(ch==' '||ch=='\n'||ch=='\t'){
			if(ch=='\n')								//记录行号 
				linenum++; 
			ch=getc(fin);
		} 
		if(isalpha(ch)){								//如果ch是字母的话,进行标识符处理 
			token[0]=ch;
			j=1;
			ch=getc(fin);
			while(isalnum(ch)){							//如果ch是字母或者数字的话 
				token[j++]=ch;							//组合的标识符保存在token中 
				ch=getc(fin);							//读下一个字符 
			}
			token[j]='
//词法分析
#include<stdio.h>
#include<ctype.h>
#include<string.h>

//保留字数目与保留字数组 
#define keywordSum 10
char *keyword[keywordSum] = {"if","else","for","while","read","write","do","int","call","function"};

//纯单分界符
char singleword[50] = "+-*(){};,:";

//双分界符首字符
char doubleword[10] = "<>=!";

//用于接收输入输出文件名 
extern char Scanin[300],Scanout[300]; 

//用于指向输入输出文件的指针 
extern FILE *fin,*fout; 

//用于对保留字数组进行冒泡排序函数(为折半查找做准备)
void sort(char *KW[]){
	int i,j;
	char *temp;
	for(i=0;i<keywordSum;i++){
		for(j=0;j<keywordSum-1;j++){
			if(strcmp(KW[j],KW[j+1])>0){
				temp = KW[j];
				KW[j] = KW[j+1];
				KW[j+1] = temp;
			}
		}
	}
}

//用于查找保留字表的折半查找函数(保留字不区分大小写)
int Search_Bin(char *KW[],char *keyword){
	sort(KW);
	int low=0,high=keywordSum-1;
	int mid;
	while(low<=high){
		mid = (low+high)/2;
		if(stricmp(keyword,KW[mid])==0) return 1;		//stricmp比较不区分大小写 返回1表示查找到 
		else if(stricmp(keyword,KW[mid])>0) low=mid+1;
		else high=mid-1; 
	}
	return 0;											//返回0表示查找失败 
} 

int TESTscan(){
	char ch,token[40];									//ch用于保存当前读出的字符,token用于保存识别出的单词
	int es=0,j,n;										//es为错误识别代码,0表示没有错误。
	int linenum=1;										//用于保存行号 
	printf("请输入源程序文件名(包括路径):");
	scanf("%s",Scanin);
	printf("请输入词法分析输出文件名(包括路径):");
	scanf("%s",Scanout);
	if((fin = fopen(Scanin,"r"))==NULL){
		printf("\n打开词法分析输入文件出错!\n");
		return 1;										//输入文件出错返回错误代码1 
	}
	if((fout = fopen(Scanout,"w"))==NULL){
		printf("\n打开词法分析1输出文件出错!\n");
		return 2; 										//输出文件出错返回错误代码2 
	}
	ch = getc(fin);
	while(ch!=EOF){
		while(ch==' '||ch=='\n'||ch=='\t'){
			if(ch=='\n')								//记录行号 
				linenum++; 
			ch=getc(fin);
		} 
		if(isalpha(ch)){								//如果ch是字母的话,进行标识符处理 
			token[0]=ch;
			j=1;
			ch=getc(fin);
			while(isalnum(ch)){							//如果ch是字母或者数字的话 
				token[j++]=ch;							//组合的标识符保存在token中 
				ch=getc(fin);							//读下一个字符 
			}
			token[j]='\0';								//标识符组合结束 
			//查保留字 
			n=Search_Bin(keyword,token);
			if(n==1)									//是保留字 
				fprintf(fout,"%s\t%s\n",token,token);
			else
				fprintf(fout,"%s\t%s\n","ID",token);	//不是保留字 
		}
		else if(isdigit(ch)){							//如果ch是数字的话,对数字进行处理 
			token[0]=ch;
			j=1;
			ch=getc(fin);
			while(isdigit(ch)){							//如果是数字则整合整数,否则退出 
				token[j++]=ch;
				ch=getc(fin);
			}
			token[j]='\0';
			fprintf(fout,"%s\t%s\n","NUM",token);
		}
		else if(strchr(singleword,ch)!=NULL){			//strchr用于查找某字符是否存在于某字符数组中,是则返回指针,不是则返回NULL 
			token[0]=ch;
			token[1]='\0';
			ch=getc(fin);								//读下一个符号以便识别单词 
			fprintf(fout,"%s\t%s\n",token,token);
		}
		else if(strchr(doubleword,ch)!=NULL){
			token[0]=ch;
			ch=getc(fin);								//读下一个字符判断是否是双分界符 
			if((token[0]!='&'&&token[0]!='|'&&ch=='=')||(token[0]=='|'&&ch=='|')||(token[0]=='&'&&ch=='&')){				//如果是=,|,&则组合双分界符 
				token[1]=ch;
				token[2]='\0';
				ch=getc(fin);
			}
			else{										//否则为单分界符 
				token[1]='\0';
			}
			if(token[0]=='!'||token[0]=='<'||token[0]=='>'||token[0]=='='){
				fprintf(fout,"%s\t%s\n",token,token);
			}
			else{
				printf("%d行发生错误",linenum);
				fprintf(fout,"\n%s\t%s\n","ERROR",token);
				fprintf(fout,"%s  %d\n\n","错误行号为:",linenum);
			} 
		}
		else if(ch=='/'){								//注释处理 
			ch=getc(fin);
			if(ch=='*'){								//如果下一个字符是*则开始进行注释处理 
				char ch1;
				ch1=getc(fin);
				do{
					if(ch1=='\n'){
						linenum++;
					}
					ch=ch1;
					ch1=getc(fin);
				}while((ch!='*'||ch1!='/')&&ch1!=EOF);	//删除注释 
				ch=getc(fin);
			}
			else{										//不是*则输出单分界符 
				token[0]=ch;
				token[1]='\0';
				fprintf(fout,"%s\t%s\n",token,token);
			}
		} 
		else{
			token[0]=ch;								//处理错误 
			token[1]='\0';
			ch=getc(fin);
			es=3;										//设置错误代码 
			printf("%d行发生错误",linenum);
			fprintf(fout,"\n%s\t%s\n","ERROR",token);
			fprintf(fout,"%s  %d\n\n","错误行号为:",linenum);
		}
	}
	fclose(fin);
	fclose(fout);
	return es;	
}
//语法及语义分析
#include<stdio.h>
#include<ctype.h>
#include<conio.h>
#include<string.h>

#define maxvartablep 500				//定义符号表的容量


struct vartable{
	char name[8];
	int address;
};								//符号表最多容纳maxvartablep个记录 

struct fun_table{
	char name[30];
	int address;
	int can_num;
	int first_address;			//记录第一个参数的地址 
}fun_table[maxvartablep];

int program();
int fun_declaration();
int canshu(struct vartable table[maxvartablep],int &num,int &can_num);
int main_declaration();
int function_body(struct vartable table[maxvartablep],int &num);
int declaration_list(struct vartable table[maxvartablep],int &num);
int declaration_stat(struct vartable table[maxvartablep],int &num);
int statement_list(struct vartable table[maxvartablep],int &num);
int statement(struct vartable table[maxvartablep],int &num);
int if_stat(struct vartable table[maxvartablep],int &num);
int while_stat(struct vartable table[maxvartablep],int &num);
int for_stat(struct vartable table[maxvartablep],int &num);
int write_stat(struct vartable table[maxvartablep],int &num);
int read_stat(struct vartable table[maxvartablep],int &num);
int compound_stat(struct vartable table[maxvartablep],int &num);
int expression_stat(struct vartable table[maxvartablep],int &num);
int call_stat(struct vartable table[maxvartablep],int &num);
int expression(struct vartable table[maxvartablep],int &num);
int bool_expr(struct vartable table[maxvartablep],int &num);
int additive_expr(struct vartable table[maxvartablep],int &num);
int term(struct vartable table[maxvartablep],int &num);
int factor(struct vartable table[maxvartablep],int &num);

int name_def(char *name,int vartablep,int datap);
char token[10],token1[40];
extern char Scanout[300],Codeout[300];
FILE *fp,*fout1;
int labelp = 1,datap=0;					//labelp用于记录当前标记,防止重复
int fun_var=0;
//插入符号表@name_def(↓n,t)的程序如下:
int name_def(char *name,vartable table[],int vartablep){
	int i,es = 0;
	if(vartablep>maxvartablep)
		return 21;
	for(i=vartablep-1;i>=0;i--){
		if(strcmp(table[i].name,name)==0){
			es=22;
			break;
		}
	} 
	if(es>0){
		return es;
	}
	strcpy(table[vartablep].name,name);
	table[vartablep].address = datap;
	datap++;
	return es;
}
int fun_def(char *name,int datap,int can_num,int first){
	int i,es = 0;
	if(fun_var>maxvartablep)
		return 31;
	for(i=fun_var-1;i>=0;i--){
		if(strcmp(fun_table[i].name,name)==0&&fun_table[i].can_num==can_num){
			es=32;
			break;
		}
	}
	strcpy(fun_table[fun_var].name,name);
	fun_table[fun_var].address = datap;
	fun_table[fun_var].can_num=can_num;
	fun_table[fun_var].first_address=first;
	fun_var++;
	return es; 
}
//查询符号表返回地址 
int lookup(struct vartable table[],char *name,int *paddress,int num){
	int i,es = 0;
	for(i=0;i<num;i++){
		if(strcmp(table[i].name,name)==0){
			*paddress = table[i].address;
			return es;
		}
	}
	es = 23;
	return es;
} 
int fun_lookup(char *name,int *paddress,int num){
	int i,es = 0;
	for(i=0;i<fun_var;i++){
		if(strcmp(fun_table[i].name,name)==0&&fun_table[i].can_num==num){
			*paddress = fun_table[i].address;
			return es;
		}
	}
	es = 33;
	return es;
} 
void cha(char *name,int &first){
	int i;
	for(i=0;i<fun_var;i++){
		if(strcmp(fun_table[i].name,name)==0){
			first=fun_table[i].first_address;
		}
	}
}
//语义语法分析及代码生成程序
int TESTparse(){
	int es = 0;
	if((fp=fopen(Scanout,"r"))==NULL){
		printf("打开%s错误!\n",Scanout);
		es = 10;
		return es;
	}
	printf("请输入目标文件名(包括路径):");
	char Codeout[20];
	scanf("%s",Codeout);
	if((fout1=fopen(Codeout,"w"))==NULL){
		printf("\n创建%s错误!\n",Codeout);
		es=10;
		return es;
	}
	if(es==0)
		es = program();
	printf("==语法,语义分析及代码生成程序结果==\n");
	switch(es){
		case 0: printf("语法分析成功!\n"); break;
		case 10: printf("打开文件%s失败!\n"); break;
		case 1: printf("缺少{\n"); break;
		case 2: printf("缺少}\n"); break;
		case 3: printf("缺少标识符\n"); break;
		case 4: printf("缺少分号\n"); break;
		case 5: printf("缺少(\n"); break;
		case 6: printf("缺少)\n"); break;
		case 7: printf("缺少操作数\n"); break;
		case 21:printf("符号表溢出\n");break;
		case 22:printf("变量重复定义\n");break;
		case 23:printf("变量未声明\n");break;
		case 31:printf("函数名符号表溢出\n");break;
		case 32:printf("函数重复定义");break; 
		case 33:printf("函数未定义");break; 
		case 41:printf("参数定义出错");break;
	}
	fclose(fp);
	fclose(fout1);
	return es;
} 

int program(){
	int es = 0;
	fscanf(fp,"%s %s\n",&token,&token1);
	fprintf(fout1,"	BR	LABEL0\n");					//产生停止指令
	while(!strcmp(token,"function")){
		es = fun_declaration();
		if(es>0)
			return es;
		fscanf(fp,"%s %s\n",&token,&token1);
	}	
	if(strcmp(token1,"main")){				 
		es = 8;
		return es;
	}
	else{
		es = main_declaration();
		if(es>0)
			return es;
	}
	fprintf(fout1,"	STOP\n");					//产生停止指令
	return es;
}
int fun_declaration(){
	int es = 0;
	struct vartable table[maxvartablep];
	int num = 0; 
	char fun_name[20];
	int can_num=0;	
	int first=0;	
	fprintf(fout1,"LABEL%d:\n",labelp++);
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"ID")){
		es = 9;
		return es;
	}
	strcpy(fun_name,token1);
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"(")){
		es = 5;
		return es;
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"int")==0){
		first=datap;
		es = canshu(table,num,can_num);
		if(es>0)
			return (es=41);
	}
	fun_def(fun_name,labelp-1,can_num,first);
	if(strcmp(token,")")){
		es = 6;
		return es;
	}	
	es = function_body(table,num);
	fprintf(fout1,"LABEL%d:\n",labelp++);
	fprintf(fout1,"	RET\n");
	return es;
}
int canshu(struct vartable table[maxvartablep],int &num,int &can_num){
	int es=0;
	while(strcmp(token,"int")==0){
		can_num++;
		fscanf(fp,"%s %s\n",&token,&token1);
		if(strcmp(token,"ID"))
			return (es = 3);			//不是标识符
		es = name_def(token1,table,num);
		num++;
		if(es>0)
			return es;
		fscanf(fp,"%s %s\n",&token,&token1);
		if(strcmp(token,")")==0){
			break;
		}
		else{
			fscanf(fp,"%s %s\n",&token,&token1);
		}	
	}
	return es;
}
int main_declaration(){
	int es = 0;
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"(")){
		es = 5;
		return es;
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,")")){
		es = 6;
		return es;
	}
	fprintf(fout1,"LABEL0:\n");
	struct vartable table[maxvartablep];
	int num = 0; 			
	es = function_body(table,num);
	return es;
}
int function_body(struct vartable table[maxvartablep],int &num){
	int es=0,i;
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"{")){
		es = 1;
		return es;
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	es = declaration_list(table,num);
	if(es>0)
		return es;
	printf("	符号表\n");
	printf("	变量名	地址\n");
	for(i=0;i<num;i++){
		printf("	%s	%d\n",table[i].name,table[i].address);
	}
	es = statement_list(table,num);
	if(es>0)
		return es;
	if(strcmp(token,"}")){
		es = 2;
		return es;
	} 
	return es;
}
int declaration_list(struct vartable table[maxvartablep],int &num){
	int es = 0;
	while(strcmp(token,"int")==0){
		es = declaration_stat(table,num);
		num++;
		if(es>0)
			return es;
	}
	return es;
}
int declaration_stat(struct vartable table[maxvartablep],int &num){
	int es=0;
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"ID"))
		return (es = 3);			//不是标识符
	es = name_def(token1,table,num);
	if(es>0)
		return es;
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,";")){
		es = 4;
		return es;
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	return es;
} 
int statement_list(struct vartable table[maxvartablep],int &num){
	int es = 0;
	while(strcmp(token,"}")){
		es = statement(table,num);
		if(es>0)
			return es; 
	}
	if(strcmp(token,"}")&&(feof(fp)||strcmp(token,"function")==0||strcmp(token1,"main")==0)){
			es=2;
			return es;
		}
	return es;	
}
int statement(struct vartable table[maxvartablep],int &num){
	int es = 0;
	if(es==0 && strcmp(token,"if")==0)
		es = if_stat(table,num);
	else if(es==0 && strcmp(token,"while")==0)
		es = while_stat(table,num);
	else if(es==0 && strcmp(token,"for")==0)
		es = for_stat(table,num);
	else if(es==0 && strcmp(token,"read")==0)
		es = read_stat(table,num);
	else if(es==0 && strcmp(token,"write")==0)
		es = write_stat(table,num);
	else if(es==0 && strcmp(token,"{")==0)
		es = compound_stat(table,num);
	else if(es==0 && (strcmp(token,"ID")==0)||strcmp(token,"NUM")==0||strcmp(token,"(")==0)
		es = expression_stat(table,num);
	else if(es==0 && strcmp(token,"call")==0)
		es = call_stat(table,num);
	return es;
}
/*if(<expression>)@BRF(↑label1)<statement>@BR(↑label2)@SETlabel(↓label1)
				  [else<statement>]@SETlabel(↓label2)
其中动作符号定义为
	@BRF(↑label1) 输出BRF label1
	@BR(↑label2) 输出BR label2
	@SETlabel(↓label1) 设置标号label1
	@SETlabel(↓label2) 设置标号label2*/
int if_stat(struct vartable table[maxvartablep],int &num){
	int es = 0,label1,label2;
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"(")){
		es = 5;
		return es;
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	es = expression(table,num);
	if(es>0)
		return es;
	if(strcmp(token,")")){
		es = 6;
		return es;
	}
	label1 = labelp++;						//用label1记住当条件为假时要转向的标号
	fprintf(fout1,"	BRF	LABEL%d\n",label1); //输出假转移指令 
	fscanf(fp,"%s %s\n",&token,&token1);
	es = statement(table,num);
	if(es>0)
		return es;
	label2 = labelp++;						//用label2记住要转向的标号 
	fprintf(fout1,"	BR	LABEL%d\n",label2);//输出无条件转移指令 
	fprintf(fout1,"LABEL%d:\n",label1);		//设置label1记住的符号 
	if(strcmp(token,"else")==0){
	fscanf(fp,"%s %s\n",&token,&token1);
	es = statement(table,num);
	if(es>0)
		return es;	
	}
	fprintf(fout1,"LABEL%d:\n",label2); 		//设置label2记住的标号 
	return es;	
}
/*<while_stat>::[email protected](↑label)(<expression>)@BRF(↑label2)
				<statement>@BR(↓label1)@SETlabel(↓label2)
	动作解释为
	@SETlabel(↑label):设置标号label1 
	@BRF(↑label2):输出BRF label2 
	@BR(↓label1):输出BR label1 
	@SETlabel(↓label2):设置标号 label2*/
int while_stat(struct vartable table[maxvartablep],int &num){
	int es = 0,label1,label2;
	label1 = labelp++;							//设置label1标号 
	fprintf(fout1,"LABEL%d:\n",label1);
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"(")){
		es = 5;
		return es;
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	es = expression(table,num);
	if(es>0)
		return es;
	if(strcmp(token,")")){
		es = 6;
		return es;
	}
	label2 = labelp++;
	fprintf(fout1,"	BRF	LABEL%d",label2);			//输出假转移指令 
	fscanf(fp,"%s %s\n",&token,&token1);
	es = statement(table,num);
	if(es>0){
		return es;
	} 
	fprintf(fout1,"	BR	LABEL%d\n",label1);		//输出无条件转移指令 
	fprintf(fout1,"LABEL%d:\n",label2);				//设置label2标号 
	return es;
}
/*<for_stat>::=for(<expression>@POP;
				@SETlabel(label1)<expression>@BRF(label2)@BR(label3)
				@SETlabel(label4)<expression>@[email protected](label1))
				@SETlabel(label3)<语句>@BR(label4)@SETlabel(label2)*/
int for_stat(struct vartable table[maxvartablep],int &num){
	int es = 0,label1,label2,label3,label4;
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"(")){						//少左括号 
		es = 5;
		return es;
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	es = expression(table,num);
	if(es>0)
		return es;
	fprintf(fout1,"	POP\n");				//设置出栈指令 
	if(strcmp(token,";")){
		es = 4;
		return es;
	}
	label1 = labelp++;
	fprintf(fout1,"LABEL%d:\n",label1);		//设置label1标号 
	fscanf(fp,"%s %s\n",&token,&token1);
	es = expression(table,num);
	if(es>0)
		return es;
	label2 = labelp++;
	fprintf(fout1,"	BRF	LABEL%d\n",label2);
	label3 = labelp++;
	fprintf(fout1,"	BR	LABEL%d\n",label3);
	if(strcmp(token,";")){
		es = 4;
		return es;
	}
	label4 = labelp++;
	fprintf(fout1,"LABEL%d:\n",label4);
	fscanf(fp,"%s %s\n",&token,&token1);
	es = expression(table,num);
	if(es>0)
		return es;
	fprintf(fout1,"	POP\n");	
	fprintf(fout1,"	BR	LABEL%d\n",label1);
	if(strcmp(token,")")){
		es = 6;
		return es;
	}
	fprintf(fout1,"LABEL%d:\n",label3);	
	fscanf(fp,"%s %s\n",&token,&token1);
	es = statement(table,num);
	if(es>0)
		return es;
	fprintf(fout1,"	BR	LABEL%d\n",label4);
	fprintf(fout1,"LABEL%d:\n",label2);	
	return es;	
}
int write_stat(struct vartable table[maxvartablep],int &num){									 
	int es = 0;
	fscanf(fp,"%s %s\n",&token,&token1);
	es = expression(table,num);
	if(es>0)
		return es;
	if(strcmp(token,";")){
		es = 4;
		return es;
	}
	fprintf(fout1,"	OUT\n"); 
	fscanf(fp,"%s %s\n",&token,&token1);
	return es;
}
//<read_stat>→read ID								read <标识符>
int read_stat(struct vartable table[],int &num){
	int es = 0,address;
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"ID")){
		es = 3;
		return es;
	}						//缺少标识符 
	es = lookup(table,token1,&address,num);
	if(es>0)	return es;
	fprintf(fout1,"	IN	\n");
	fprintf(fout1,"	STO	%d\n",address);
	fprintf(fout1,"	POP\n");
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,";")){
		es = 4;
		return es;							//缺少分号 
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	return es;
}
int compound_stat(struct vartable table[maxvartablep],int &num){
	int es = 0;
	fscanf(fp,"%s %s\n",&token,&token1);
	es = statement_list(table,num);
	if(es>0){
		return es;
	}
	if(strcmp(token,"}")){
		es=2;
		return es;
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	return es; 
}
//<expression_stat>→< expression >;|; 
int expression_stat(struct vartable table[maxvartablep],int &num){
	int es = 0;
	if(strcmp(token,";")==0){
		fscanf(fp,"%s %s\n",&token,&token1);
		return es;
	} 
	es = expression(table,num);
	if(es>0)
		return es;
	fprintf(fout1,"	POP\n");
	if(es==0 && strcmp(token,";")==0){ 
		fscanf(fp,"%s %s\n",&token,&token1);
		return es;
	}
	else{											//少分号 
		es = 4;
		return es;
	}
}
//< call _stat>→ call ID‘(’ ‘)’
int call_stat(struct vartable table[maxvartablep],int &num){
	int es = 0;
	int address;
	int address1;
	int canshunum=0;
	char fun_name[20];
	int first=0;
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"ID")){					//缺少函数名 
		es = 9;					
		return es; 
	}
	strcpy(fun_name,token1);	
	cha(fun_name,first);
	if(es>0){
		return es;
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"(")){
		es = 5;
		return es;
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	while(strcmp(token,"ID")==0){
		es=lookup(table,token1,&address1,num);
		if(es>0)	return es;
		fprintf(fout1,"	LOAD	%d\n",address1);
		fprintf(fout1,"	STO	%d\n",first+canshunum);
		fprintf(fout1,"	POP\n");
		canshunum++;
		fscanf(fp,"%s %s\n",&token,&token1);
		if(strcmp(token,")")==0)
			break;
		else{
			fscanf(fp,"%s %s\n",&token,&token1);
		} 
	}
	if(strcmp(token,")")){
		es = 6;
		return es;
	}
	es=fun_lookup(fun_name,&address,canshunum);
	fprintf(fout1,"	JSR LABEL%d\n",address);
	
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,";")){
		es = 4;
		return es;
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	return es;
}
//< expression >→ ID=<bool_expr>|<bool_expr> 
int expression(struct vartable table[maxvartablep],int &num){
	int es = 0;
	int fileadd;										//用于保存文件位置
	char token2[20],token3[40];
	if(strcmp(token,"ID")==0){
		fileadd = ftell(fp);							//记录文件位置
		fscanf(fp,"%s %s\n",&token2,&token3);
		if(strcmp(token2,"=")==0){
			int address;
			es=lookup(table,token1,&address,num);
			if(es>0)	return es;
			fscanf(fp,"%s %s\n",&token,&token1);
			es = bool_expr(table,num);
			if(es>0)
				return es; 
			fprintf(fout1,"	STO	%d\n",address);
		}
		else{											//如果不是等号,则指针返回等号之前的标识符 
			fseek(fp,fileadd,0); 
			es = bool_expr(table,num);
			if(es>0)
				return es;
		}
	}
	else{
		es = bool_expr(table,num);
	}
	return es;
}
//<bool_expr>-><additive_expr> |< additive_expr >(>|<|>=|<=|==|!=)< additive_expr > 
//<bool_expr>→<additive_expr>{(>|<|>=|<=|==|!=)<additive_expr>}
int bool_expr(struct vartable table[maxvartablep],int &num){
	int es = 0;
	es = additive_expr(table,num);
	if(es>0)
		return es;
	if(strcmp(token,">")==0||strcmp(token,">=")==0||strcmp(token,"<")==0||strcmp(token,"<=")==0||strcmp(token,"==")==0||strcmp(token,"!=")==0){
		char token2[20];
		strcpy(token2,token);
		fscanf(fp,"%s %s\n",&token,&token1);
		es = additive_expr(table,num);
		if(es>0)
			return es;
		if(strcmp(token2,">")==0)	fprintf(fout1,"	GT\n");
		if(strcmp(token2,">=")==0)	fprintf(fout1,"	GE\n");
		if(strcmp(token2,"<")==0)	fprintf(fout1,"	LES\n");
		if(strcmp(token2,"<=")==0)	fprintf(fout1,"	LE\n");
		if(strcmp(token2,"==")==0)	fprintf(fout1,"	EQ\n");
		if(strcmp(token2,"!=")==0)	fprintf(fout1,"	NOTEQ\n");
	}
	return es;
}
//< additive_expr>→<term>{(+|-)< term >}				算数表达式定义为项或者项加减项
int additive_expr(struct vartable table[maxvartablep],int &num){
	int es = 0;
	es = term(table,num);
	if(es>0)
		return es;
	while(strcmp(token,"+")==0||strcmp(token,"-")==0){
		char token2[20];
		strcpy(token2,token);
		fscanf(fp,"%s %s\n",&token,&token1);
		es = term(table,num);
		if(es>0)
			return es;
		if(strcmp(token2,"+")==0)	fprintf(fout1,"	ADD\n");
		if(strcmp(token2,"-")==0)	fprintf(fout1,"	SUB\n");
	}
	return es;
}
//< term >→<factor>{(*| /)< factor >}					项定义为因子或因子乘或除因子
int term(struct vartable table[maxvartablep],int &num){
	int es = 0;
	es = factor(table,num);
	if(es>0)
		return es;	
	while(strcmp(token,"*")==0||strcmp(token,"/")==0){
		char token2[20];
		strcpy(token2,token);
		fscanf(fp,"%s %s\n",&token,&token1);
		es = factor(table,num);
		if(es>0)
			return es;
		if(strcmp(token2,"*")==0)	fprintf(fout1,"	MULT\n");
		if(strcmp(token2,"/")==0)	fprintf(fout1,"	DIV\n");
	}
	return es;
}
//< factor >→’(‘< additive_expr >’)’|ID|NUM		因子定义为表达式或者标识符或者数字
int factor(struct vartable table[maxvartablep],int &num){
	int es = 0;
	if(strcmp(token,"(")==0){										//因子定义成表达式,根据左括号进行判断
		fscanf(fp,"%s %s\n",&token,&token1);
		es = expression(table,num);
		if(es>0)
			return es;
		if(strcmp(token,")")){										//当缺少右括号时
			es = 6;
			return es;
		}
		fscanf(fp,"%s %s\n",&token,&token1);
	}
	else{															//因子定义成标识符或数字
		if(strcmp(token,"ID")==0){
			int address;
			int flag=1;
			es=lookup(table,token1,&address,num);
			if(es>0)	return es;
			fprintf(fout1,"	LOAD	%d\n",address);
			fscanf(fp,"%s %s\n",&token,&token1);
			return es;
		}
		else if(strcmp(token,"NUM")==0){
			fprintf(fout1,"	LOADI	%s\n",token1);
			fscanf(fp,"%s %s\n",&token,&token1);
		}
		else{
			es = 7;												//缺少操作数
			return es;
		}
	}
	return es; 
}
//词法语法语义分析主函数
#include<stdio.h>
#include<ctype.h>

extern int TESTscan();
extern int TESTparse();

char Scanin[300],Scanout[300];
FILE *fin,*fout;

int main(){
	int es=0;
	es = TESTscan();
	if(es>0)
		printf("词法分析有错,编译停止!\n");
	else
		printf("词法分析成功!\n");
	if(es==0){
		es = TESTparse();
		if(es==0)
			printf("语法分析成功!\n");
		else
			printf("语法语义分析错误!\n");
	}
	return 0; 
}
//虚拟机生成
#include<stdio.h>
#include<ctype.h>
#include<stdlib.h>
#include<string.h>

int TESTmachine();

int TESTmachine(){
	int es=0,i,k=0,codecount,stack[1000],stacktop=0;
	int funstack[100],funstacktop=0;
	char Codein[300],code[1000][20],data[1000];
	int label[100]={0};
	char lno[4];
	FILE *fin;
	/*printf("请输入目标文件名(包括路径):");
	scanf("%s",Codein);*/
	if((fin=fopen("3.txt","r"))==NULL){					
		printf("\n打开%s是错误!\n",code);
		es=10;
		return es;
	}
	codecount=0;
	i=fscanf(fin,"%s",&code[codecount]);
	while(!feof(fin)){
		printf("----|  %d  %s  \n",codecount,code[codecount]);
		i=strlen(code[codecount])-1;
		if(code[codecount][i]==':'){
			i=i-5;
			strncpy(lno,&code[codecount][5],i);
			lno[i]='\0';
			label[atoi(lno)]=codecount;							//???			用label数组记住每一个标号的地址 
			//printf("label[%d]=  %d  \n",atoi(lno),label[atoi(lno)]);
			code[codecount][0]=':';
			code[codecount][1]='\0';
			strcat(code[codecount],lno);
			k++;
		}
		codecount++;
		i=fscanf(fin,"%s",&code[codecount]);
	}
	fclose(fin);
	for(i=0;i<codecount;i++){
		int l;
		l=strlen(code[i]);
		if((l>1)&&(code[i][1]=='A')){
			strncpy(lno,&code[i][5],l-5);
			lno[l-5]='\0';
			itoa(label[atoi(lno)],code[i],10);
		}
	}		
	i=0;
	while(i<codecount){								//执行每条指令 
		//printf("code %d %s \n",i,code[i]);
		if(strcmp(code[i],"JSR")==0){				//JSR LAB 无条件跳到LAB,并将JAR下一行的行标保存在函数栈中,便于执行完函数后继续执行主函数 
			i++;
			funstack[funstacktop]=i+1;
			funstacktop++;
			i=atoi(code[i]);
		}
		if(strcmp(code[i],"RET")==0){				//RET 表示当前函数执行完毕,返回调用处 
			i=funstack[funstacktop-1];
			funstacktop--;
		} 
		if(strcmp(code[i],"LOAD")==0){				//LOAD D 将D中的内容加载到操作数栈 
			i++;
			stack[stacktop]=data[atoi(code[i])];
			stacktop++;
		} 
		if(strcmp(code[i],"LOADI")==0){				//LOADI a 将常量a压入操作数栈 
			i++;
			stack[stacktop]=atoi(code[i]);
			stacktop++; 
		} 
		//STO D将操作数栈顶单元内容存入D,切栈顶单元内容保持不变 
		if(strcmp(code[i],"STO")==0){
			i++; 
			data[atoi(code[i])]=stack[stacktop-1];
			//printf("sto  stack %d\n",stack[stacktop-1]);
			//printf("sto  data %d\n",data[atoi(code[i])]); 
		} 
		//POP 栈顶内容出栈 
		if(strcmp(code[i],"POP")==0){
			stacktop--; 
		} 
		//ADD 将栈顶单元与次栈顶单元出栈并相加,和置于栈顶
		if(strcmp(code[i],"ADD")==0){
			stack[stacktop-2] = stack[stacktop-1]+stack[stacktop-2];
			//printf("add  %d\n",stack[stacktop-1]);
			stacktop--;
		}
		//SUB 将次栈顶单元减去栈顶单元并出栈,差置于栈顶
		if(strcmp(code[i],"SUB")==0){
		 	stack[stacktop-2] = stack[stacktop-2]-stack[stacktop-1];
		 	stacktop--; 
		} 
		//MULT 将次栈顶单元与栈顶单元相乘并出栈,积置于栈顶
		if(strcmp(code[i],"MULT")==0){
		 	stack[stacktop-2] = stack[stacktop-2]*stack[stacktop-1];
		 	stacktop--; 
		} 
	 	//DIV 将次栈顶单元与栈顶单元相除并出栈,商置于栈顶 
		if(strcmp(code[i],"DIV")==0){
		 	stack[stacktop-2] = stack[stacktop-2]/stack[stacktop-1];
		 	stacktop--; 
		} 
		//BR	lab 无条件转移到lab 
		if(strcmp(code[i],"BR")==0){
		 	i++;
		 	i=atoi(code[i]);
		} 
		//BRF lab 	检查栈顶单元逻辑值并出栈,若为假则转移到lab 
		if(strcmp(code[i],"BRF")==0){
		 	i++;
			if(stack[stacktop-1]==0)
				i=atoi(code[i]);
			i--; 
		} 
		//EQ 将栈顶两单元做等于比较并出栈,并将结果真或假(1或0),置于栈顶 
		if(strcmp(code[i],"EQ")==0){
		 	stack[stacktop-2] = stack[stacktop-2]==stack[stacktop-1];
		 	stacktop--; 
		} 
		//NOTEQ 将栈顶两单元做不等于比较并出栈,并将结果真或假(1或0),置于栈顶 
		if(strcmp(code[i],"NOTEQ")==0){
		 	stack[stacktop-2] = stack[stacktop-2]!=stack[stacktop-1];
		 	stacktop--; 
		} 
		//GT 次栈顶大于栈顶操作数并出栈,则栈顶置1,否则置0 
		if(strcmp(code[i],"GT")==0){
		 	stack[stacktop-2] = stack[stacktop-2]>stack[stacktop-1];
		 	stacktop--; 
		} 
		//LES 次栈顶小于栈顶操作数并出栈,则栈顶置1,否则置0 
		if(strcmp(code[i],"LES")==0){
		 	stack[stacktop-2] = stack[stacktop-2]<stack[stacktop-1];
		 	stacktop--; 
		} 
		//GE 次栈顶大于等于栈顶操作数并出栈,则栈顶置1,否则置0 
		if(strcmp(code[i],"GE")==0){
		 	stack[stacktop-2] = stack[stacktop-2]>=stack[stacktop-1];
		 	stacktop--; 
		} 
		//LE 次栈顶小于等于栈顶操作数并出栈,则栈顶置1,否则置0 
		if(strcmp(code[i],"LE")==0){
		 	stack[stacktop-2] = stack[stacktop-2]<=stack[stacktop-1];
		 	stacktop--; 
		} 
		//AND 将栈顶两单元做逻辑与运算并出战,并将结果真或假(1或0)置于栈顶
		if(strcmp(code[i],"AND")==0){
		 	stack[stacktop-2] = stack[stacktop-2]&&stack[stacktop-1];
		 	stacktop--; 
		} 
		//OR 将栈顶两单元做逻辑或运算并出战,并将结果真或假(1或0)置于栈顶
		if(strcmp(code[i],"OR")==0){
		 	stack[stacktop-2] = stack[stacktop-2]||stack[stacktop-1];
		 	stacktop--; 
		} 
		//NOT 将栈顶逻辑值取反
		if(strcmp(code[i],"NOT")==0){
		 	stack[stacktop-1]=!stack[stacktop-1];
		} 
		//IN 从标准输入设备读入一个整型数据,并入栈
		if(strcmp(code[i],"IN")==0){
			printf("请输入数据:");
			scanf("%d",&stack[stacktop]);
			stacktop++; 
		} 
		//OUT 将栈顶内容出栈,并输出到标准输出设备上 
		if(strcmp(code[i],"OUT")==0){
		 	printf("程序输出%d\n",stack[stacktop-1]);
			stacktop--; 
		} 
		//STOP 停止执行
		if(strcmp(code[i],"STOP")==0){
			break;
		} 
		i++;
		//显示栈内容
		/*for(k=stacktop-1;k>=0;k--)
		 	printf("%d  ",stack[k]);
		printf("\n");*/
		//printf("	%d		%d\n",data[0],data[1]);
	} 
	return es;
} 
int main(){
	int es=0;
	es = TESTmachine();
}

 


'; //标识符组合结束 //查保留字 n=Search_Bin(keyword,token); if(n==1) //是保留字 fprintf(fout,"%s\t%s\n",token,token); else fprintf(fout,"%s\t%s\n","ID",token); //不是保留字 } else if(isdigit(ch)){ //如果ch是数字的话,对数字进行处理 token[0]=ch; j=1; ch=getc(fin); while(isdigit(ch)){ //如果是数字则整合整数,否则退出 token[j++]=ch; ch=getc(fin); } token[j]='
//词法分析
#include<stdio.h>
#include<ctype.h>
#include<string.h>

//保留字数目与保留字数组 
#define keywordSum 10
char *keyword[keywordSum] = {"if","else","for","while","read","write","do","int","call","function"};

//纯单分界符
char singleword[50] = "+-*(){};,:";

//双分界符首字符
char doubleword[10] = "<>=!";

//用于接收输入输出文件名 
extern char Scanin[300],Scanout[300]; 

//用于指向输入输出文件的指针 
extern FILE *fin,*fout; 

//用于对保留字数组进行冒泡排序函数(为折半查找做准备)
void sort(char *KW[]){
	int i,j;
	char *temp;
	for(i=0;i<keywordSum;i++){
		for(j=0;j<keywordSum-1;j++){
			if(strcmp(KW[j],KW[j+1])>0){
				temp = KW[j];
				KW[j] = KW[j+1];
				KW[j+1] = temp;
			}
		}
	}
}

//用于查找保留字表的折半查找函数(保留字不区分大小写)
int Search_Bin(char *KW[],char *keyword){
	sort(KW);
	int low=0,high=keywordSum-1;
	int mid;
	while(low<=high){
		mid = (low+high)/2;
		if(stricmp(keyword,KW[mid])==0) return 1;		//stricmp比较不区分大小写 返回1表示查找到 
		else if(stricmp(keyword,KW[mid])>0) low=mid+1;
		else high=mid-1; 
	}
	return 0;											//返回0表示查找失败 
} 

int TESTscan(){
	char ch,token[40];									//ch用于保存当前读出的字符,token用于保存识别出的单词
	int es=0,j,n;										//es为错误识别代码,0表示没有错误。
	int linenum=1;										//用于保存行号 
	printf("请输入源程序文件名(包括路径):");
	scanf("%s",Scanin);
	printf("请输入词法分析输出文件名(包括路径):");
	scanf("%s",Scanout);
	if((fin = fopen(Scanin,"r"))==NULL){
		printf("\n打开词法分析输入文件出错!\n");
		return 1;										//输入文件出错返回错误代码1 
	}
	if((fout = fopen(Scanout,"w"))==NULL){
		printf("\n打开词法分析1输出文件出错!\n");
		return 2; 										//输出文件出错返回错误代码2 
	}
	ch = getc(fin);
	while(ch!=EOF){
		while(ch==' '||ch=='\n'||ch=='\t'){
			if(ch=='\n')								//记录行号 
				linenum++; 
			ch=getc(fin);
		} 
		if(isalpha(ch)){								//如果ch是字母的话,进行标识符处理 
			token[0]=ch;
			j=1;
			ch=getc(fin);
			while(isalnum(ch)){							//如果ch是字母或者数字的话 
				token[j++]=ch;							//组合的标识符保存在token中 
				ch=getc(fin);							//读下一个字符 
			}
			token[j]='\0';								//标识符组合结束 
			//查保留字 
			n=Search_Bin(keyword,token);
			if(n==1)									//是保留字 
				fprintf(fout,"%s\t%s\n",token,token);
			else
				fprintf(fout,"%s\t%s\n","ID",token);	//不是保留字 
		}
		else if(isdigit(ch)){							//如果ch是数字的话,对数字进行处理 
			token[0]=ch;
			j=1;
			ch=getc(fin);
			while(isdigit(ch)){							//如果是数字则整合整数,否则退出 
				token[j++]=ch;
				ch=getc(fin);
			}
			token[j]='\0';
			fprintf(fout,"%s\t%s\n","NUM",token);
		}
		else if(strchr(singleword,ch)!=NULL){			//strchr用于查找某字符是否存在于某字符数组中,是则返回指针,不是则返回NULL 
			token[0]=ch;
			token[1]='\0';
			ch=getc(fin);								//读下一个符号以便识别单词 
			fprintf(fout,"%s\t%s\n",token,token);
		}
		else if(strchr(doubleword,ch)!=NULL){
			token[0]=ch;
			ch=getc(fin);								//读下一个字符判断是否是双分界符 
			if((token[0]!='&'&&token[0]!='|'&&ch=='=')||(token[0]=='|'&&ch=='|')||(token[0]=='&'&&ch=='&')){				//如果是=,|,&则组合双分界符 
				token[1]=ch;
				token[2]='\0';
				ch=getc(fin);
			}
			else{										//否则为单分界符 
				token[1]='\0';
			}
			if(token[0]=='!'||token[0]=='<'||token[0]=='>'||token[0]=='='){
				fprintf(fout,"%s\t%s\n",token,token);
			}
			else{
				printf("%d行发生错误",linenum);
				fprintf(fout,"\n%s\t%s\n","ERROR",token);
				fprintf(fout,"%s  %d\n\n","错误行号为:",linenum);
			} 
		}
		else if(ch=='/'){								//注释处理 
			ch=getc(fin);
			if(ch=='*'){								//如果下一个字符是*则开始进行注释处理 
				char ch1;
				ch1=getc(fin);
				do{
					if(ch1=='\n'){
						linenum++;
					}
					ch=ch1;
					ch1=getc(fin);
				}while((ch!='*'||ch1!='/')&&ch1!=EOF);	//删除注释 
				ch=getc(fin);
			}
			else{										//不是*则输出单分界符 
				token[0]=ch;
				token[1]='\0';
				fprintf(fout,"%s\t%s\n",token,token);
			}
		} 
		else{
			token[0]=ch;								//处理错误 
			token[1]='\0';
			ch=getc(fin);
			es=3;										//设置错误代码 
			printf("%d行发生错误",linenum);
			fprintf(fout,"\n%s\t%s\n","ERROR",token);
			fprintf(fout,"%s  %d\n\n","错误行号为:",linenum);
		}
	}
	fclose(fin);
	fclose(fout);
	return es;	
}
//语法及语义分析
#include<stdio.h>
#include<ctype.h>
#include<conio.h>
#include<string.h>

#define maxvartablep 500				//定义符号表的容量


struct vartable{
	char name[8];
	int address;
};								//符号表最多容纳maxvartablep个记录 

struct fun_table{
	char name[30];
	int address;
	int can_num;
	int first_address;			//记录第一个参数的地址 
}fun_table[maxvartablep];

int program();
int fun_declaration();
int canshu(struct vartable table[maxvartablep],int &num,int &can_num);
int main_declaration();
int function_body(struct vartable table[maxvartablep],int &num);
int declaration_list(struct vartable table[maxvartablep],int &num);
int declaration_stat(struct vartable table[maxvartablep],int &num);
int statement_list(struct vartable table[maxvartablep],int &num);
int statement(struct vartable table[maxvartablep],int &num);
int if_stat(struct vartable table[maxvartablep],int &num);
int while_stat(struct vartable table[maxvartablep],int &num);
int for_stat(struct vartable table[maxvartablep],int &num);
int write_stat(struct vartable table[maxvartablep],int &num);
int read_stat(struct vartable table[maxvartablep],int &num);
int compound_stat(struct vartable table[maxvartablep],int &num);
int expression_stat(struct vartable table[maxvartablep],int &num);
int call_stat(struct vartable table[maxvartablep],int &num);
int expression(struct vartable table[maxvartablep],int &num);
int bool_expr(struct vartable table[maxvartablep],int &num);
int additive_expr(struct vartable table[maxvartablep],int &num);
int term(struct vartable table[maxvartablep],int &num);
int factor(struct vartable table[maxvartablep],int &num);

int name_def(char *name,int vartablep,int datap);
char token[10],token1[40];
extern char Scanout[300],Codeout[300];
FILE *fp,*fout1;
int labelp = 1,datap=0;					//labelp用于记录当前标记,防止重复
int fun_var=0;
//插入符号表@name_def(↓n,t)的程序如下:
int name_def(char *name,vartable table[],int vartablep){
	int i,es = 0;
	if(vartablep>maxvartablep)
		return 21;
	for(i=vartablep-1;i>=0;i--){
		if(strcmp(table[i].name,name)==0){
			es=22;
			break;
		}
	} 
	if(es>0){
		return es;
	}
	strcpy(table[vartablep].name,name);
	table[vartablep].address = datap;
	datap++;
	return es;
}
int fun_def(char *name,int datap,int can_num,int first){
	int i,es = 0;
	if(fun_var>maxvartablep)
		return 31;
	for(i=fun_var-1;i>=0;i--){
		if(strcmp(fun_table[i].name,name)==0&&fun_table[i].can_num==can_num){
			es=32;
			break;
		}
	}
	strcpy(fun_table[fun_var].name,name);
	fun_table[fun_var].address = datap;
	fun_table[fun_var].can_num=can_num;
	fun_table[fun_var].first_address=first;
	fun_var++;
	return es; 
}
//查询符号表返回地址 
int lookup(struct vartable table[],char *name,int *paddress,int num){
	int i,es = 0;
	for(i=0;i<num;i++){
		if(strcmp(table[i].name,name)==0){
			*paddress = table[i].address;
			return es;
		}
	}
	es = 23;
	return es;
} 
int fun_lookup(char *name,int *paddress,int num){
	int i,es = 0;
	for(i=0;i<fun_var;i++){
		if(strcmp(fun_table[i].name,name)==0&&fun_table[i].can_num==num){
			*paddress = fun_table[i].address;
			return es;
		}
	}
	es = 33;
	return es;
} 
void cha(char *name,int &first){
	int i;
	for(i=0;i<fun_var;i++){
		if(strcmp(fun_table[i].name,name)==0){
			first=fun_table[i].first_address;
		}
	}
}
//语义语法分析及代码生成程序
int TESTparse(){
	int es = 0;
	if((fp=fopen(Scanout,"r"))==NULL){
		printf("打开%s错误!\n",Scanout);
		es = 10;
		return es;
	}
	printf("请输入目标文件名(包括路径):");
	char Codeout[20];
	scanf("%s",Codeout);
	if((fout1=fopen(Codeout,"w"))==NULL){
		printf("\n创建%s错误!\n",Codeout);
		es=10;
		return es;
	}
	if(es==0)
		es = program();
	printf("==语法,语义分析及代码生成程序结果==\n");
	switch(es){
		case 0: printf("语法分析成功!\n"); break;
		case 10: printf("打开文件%s失败!\n"); break;
		case 1: printf("缺少{\n"); break;
		case 2: printf("缺少}\n"); break;
		case 3: printf("缺少标识符\n"); break;
		case 4: printf("缺少分号\n"); break;
		case 5: printf("缺少(\n"); break;
		case 6: printf("缺少)\n"); break;
		case 7: printf("缺少操作数\n"); break;
		case 21:printf("符号表溢出\n");break;
		case 22:printf("变量重复定义\n");break;
		case 23:printf("变量未声明\n");break;
		case 31:printf("函数名符号表溢出\n");break;
		case 32:printf("函数重复定义");break; 
		case 33:printf("函数未定义");break; 
		case 41:printf("参数定义出错");break;
	}
	fclose(fp);
	fclose(fout1);
	return es;
} 

int program(){
	int es = 0;
	fscanf(fp,"%s %s\n",&token,&token1);
	fprintf(fout1,"	BR	LABEL0\n");					//产生停止指令
	while(!strcmp(token,"function")){
		es = fun_declaration();
		if(es>0)
			return es;
		fscanf(fp,"%s %s\n",&token,&token1);
	}	
	if(strcmp(token1,"main")){				 
		es = 8;
		return es;
	}
	else{
		es = main_declaration();
		if(es>0)
			return es;
	}
	fprintf(fout1,"	STOP\n");					//产生停止指令
	return es;
}
int fun_declaration(){
	int es = 0;
	struct vartable table[maxvartablep];
	int num = 0; 
	char fun_name[20];
	int can_num=0;	
	int first=0;	
	fprintf(fout1,"LABEL%d:\n",labelp++);
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"ID")){
		es = 9;
		return es;
	}
	strcpy(fun_name,token1);
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"(")){
		es = 5;
		return es;
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"int")==0){
		first=datap;
		es = canshu(table,num,can_num);
		if(es>0)
			return (es=41);
	}
	fun_def(fun_name,labelp-1,can_num,first);
	if(strcmp(token,")")){
		es = 6;
		return es;
	}	
	es = function_body(table,num);
	fprintf(fout1,"LABEL%d:\n",labelp++);
	fprintf(fout1,"	RET\n");
	return es;
}
int canshu(struct vartable table[maxvartablep],int &num,int &can_num){
	int es=0;
	while(strcmp(token,"int")==0){
		can_num++;
		fscanf(fp,"%s %s\n",&token,&token1);
		if(strcmp(token,"ID"))
			return (es = 3);			//不是标识符
		es = name_def(token1,table,num);
		num++;
		if(es>0)
			return es;
		fscanf(fp,"%s %s\n",&token,&token1);
		if(strcmp(token,")")==0){
			break;
		}
		else{
			fscanf(fp,"%s %s\n",&token,&token1);
		}	
	}
	return es;
}
int main_declaration(){
	int es = 0;
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"(")){
		es = 5;
		return es;
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,")")){
		es = 6;
		return es;
	}
	fprintf(fout1,"LABEL0:\n");
	struct vartable table[maxvartablep];
	int num = 0; 			
	es = function_body(table,num);
	return es;
}
int function_body(struct vartable table[maxvartablep],int &num){
	int es=0,i;
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"{")){
		es = 1;
		return es;
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	es = declaration_list(table,num);
	if(es>0)
		return es;
	printf("	符号表\n");
	printf("	变量名	地址\n");
	for(i=0;i<num;i++){
		printf("	%s	%d\n",table[i].name,table[i].address);
	}
	es = statement_list(table,num);
	if(es>0)
		return es;
	if(strcmp(token,"}")){
		es = 2;
		return es;
	} 
	return es;
}
int declaration_list(struct vartable table[maxvartablep],int &num){
	int es = 0;
	while(strcmp(token,"int")==0){
		es = declaration_stat(table,num);
		num++;
		if(es>0)
			return es;
	}
	return es;
}
int declaration_stat(struct vartable table[maxvartablep],int &num){
	int es=0;
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"ID"))
		return (es = 3);			//不是标识符
	es = name_def(token1,table,num);
	if(es>0)
		return es;
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,";")){
		es = 4;
		return es;
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	return es;
} 
int statement_list(struct vartable table[maxvartablep],int &num){
	int es = 0;
	while(strcmp(token,"}")){
		es = statement(table,num);
		if(es>0)
			return es; 
	}
	if(strcmp(token,"}")&&(feof(fp)||strcmp(token,"function")==0||strcmp(token1,"main")==0)){
			es=2;
			return es;
		}
	return es;	
}
int statement(struct vartable table[maxvartablep],int &num){
	int es = 0;
	if(es==0 && strcmp(token,"if")==0)
		es = if_stat(table,num);
	else if(es==0 && strcmp(token,"while")==0)
		es = while_stat(table,num);
	else if(es==0 && strcmp(token,"for")==0)
		es = for_stat(table,num);
	else if(es==0 && strcmp(token,"read")==0)
		es = read_stat(table,num);
	else if(es==0 && strcmp(token,"write")==0)
		es = write_stat(table,num);
	else if(es==0 && strcmp(token,"{")==0)
		es = compound_stat(table,num);
	else if(es==0 && (strcmp(token,"ID")==0)||strcmp(token,"NUM")==0||strcmp(token,"(")==0)
		es = expression_stat(table,num);
	else if(es==0 && strcmp(token,"call")==0)
		es = call_stat(table,num);
	return es;
}
/*if(<expression>)@BRF(↑label1)<statement>@BR(↑label2)@SETlabel(↓label1)
				  [else<statement>]@SETlabel(↓label2)
其中动作符号定义为
	@BRF(↑label1) 输出BRF label1
	@BR(↑label2) 输出BR label2
	@SETlabel(↓label1) 设置标号label1
	@SETlabel(↓label2) 设置标号label2*/
int if_stat(struct vartable table[maxvartablep],int &num){
	int es = 0,label1,label2;
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"(")){
		es = 5;
		return es;
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	es = expression(table,num);
	if(es>0)
		return es;
	if(strcmp(token,")")){
		es = 6;
		return es;
	}
	label1 = labelp++;						//用label1记住当条件为假时要转向的标号
	fprintf(fout1,"	BRF	LABEL%d\n",label1); //输出假转移指令 
	fscanf(fp,"%s %s\n",&token,&token1);
	es = statement(table,num);
	if(es>0)
		return es;
	label2 = labelp++;						//用label2记住要转向的标号 
	fprintf(fout1,"	BR	LABEL%d\n",label2);//输出无条件转移指令 
	fprintf(fout1,"LABEL%d:\n",label1);		//设置label1记住的符号 
	if(strcmp(token,"else")==0){
	fscanf(fp,"%s %s\n",&token,&token1);
	es = statement(table,num);
	if(es>0)
		return es;	
	}
	fprintf(fout1,"LABEL%d:\n",label2); 		//设置label2记住的标号 
	return es;	
}
/*<while_stat>::[email protected](↑label)(<expression>)@BRF(↑label2)
				<statement>@BR(↓label1)@SETlabel(↓label2)
	动作解释为
	@SETlabel(↑label):设置标号label1 
	@BRF(↑label2):输出BRF label2 
	@BR(↓label1):输出BR label1 
	@SETlabel(↓label2):设置标号 label2*/
int while_stat(struct vartable table[maxvartablep],int &num){
	int es = 0,label1,label2;
	label1 = labelp++;							//设置label1标号 
	fprintf(fout1,"LABEL%d:\n",label1);
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"(")){
		es = 5;
		return es;
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	es = expression(table,num);
	if(es>0)
		return es;
	if(strcmp(token,")")){
		es = 6;
		return es;
	}
	label2 = labelp++;
	fprintf(fout1,"	BRF	LABEL%d",label2);			//输出假转移指令 
	fscanf(fp,"%s %s\n",&token,&token1);
	es = statement(table,num);
	if(es>0){
		return es;
	} 
	fprintf(fout1,"	BR	LABEL%d\n",label1);		//输出无条件转移指令 
	fprintf(fout1,"LABEL%d:\n",label2);				//设置label2标号 
	return es;
}
/*<for_stat>::=for(<expression>@POP;
				@SETlabel(label1)<expression>@BRF(label2)@BR(label3)
				@SETlabel(label4)<expression>@[email protected](label1))
				@SETlabel(label3)<语句>@BR(label4)@SETlabel(label2)*/
int for_stat(struct vartable table[maxvartablep],int &num){
	int es = 0,label1,label2,label3,label4;
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"(")){						//少左括号 
		es = 5;
		return es;
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	es = expression(table,num);
	if(es>0)
		return es;
	fprintf(fout1,"	POP\n");				//设置出栈指令 
	if(strcmp(token,";")){
		es = 4;
		return es;
	}
	label1 = labelp++;
	fprintf(fout1,"LABEL%d:\n",label1);		//设置label1标号 
	fscanf(fp,"%s %s\n",&token,&token1);
	es = expression(table,num);
	if(es>0)
		return es;
	label2 = labelp++;
	fprintf(fout1,"	BRF	LABEL%d\n",label2);
	label3 = labelp++;
	fprintf(fout1,"	BR	LABEL%d\n",label3);
	if(strcmp(token,";")){
		es = 4;
		return es;
	}
	label4 = labelp++;
	fprintf(fout1,"LABEL%d:\n",label4);
	fscanf(fp,"%s %s\n",&token,&token1);
	es = expression(table,num);
	if(es>0)
		return es;
	fprintf(fout1,"	POP\n");	
	fprintf(fout1,"	BR	LABEL%d\n",label1);
	if(strcmp(token,")")){
		es = 6;
		return es;
	}
	fprintf(fout1,"LABEL%d:\n",label3);	
	fscanf(fp,"%s %s\n",&token,&token1);
	es = statement(table,num);
	if(es>0)
		return es;
	fprintf(fout1,"	BR	LABEL%d\n",label4);
	fprintf(fout1,"LABEL%d:\n",label2);	
	return es;	
}
int write_stat(struct vartable table[maxvartablep],int &num){									 
	int es = 0;
	fscanf(fp,"%s %s\n",&token,&token1);
	es = expression(table,num);
	if(es>0)
		return es;
	if(strcmp(token,";")){
		es = 4;
		return es;
	}
	fprintf(fout1,"	OUT\n"); 
	fscanf(fp,"%s %s\n",&token,&token1);
	return es;
}
//<read_stat>→read ID								read <标识符>
int read_stat(struct vartable table[],int &num){
	int es = 0,address;
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"ID")){
		es = 3;
		return es;
	}						//缺少标识符 
	es = lookup(table,token1,&address,num);
	if(es>0)	return es;
	fprintf(fout1,"	IN	\n");
	fprintf(fout1,"	STO	%d\n",address);
	fprintf(fout1,"	POP\n");
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,";")){
		es = 4;
		return es;							//缺少分号 
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	return es;
}
int compound_stat(struct vartable table[maxvartablep],int &num){
	int es = 0;
	fscanf(fp,"%s %s\n",&token,&token1);
	es = statement_list(table,num);
	if(es>0){
		return es;
	}
	if(strcmp(token,"}")){
		es=2;
		return es;
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	return es; 
}
//<expression_stat>→< expression >;|; 
int expression_stat(struct vartable table[maxvartablep],int &num){
	int es = 0;
	if(strcmp(token,";")==0){
		fscanf(fp,"%s %s\n",&token,&token1);
		return es;
	} 
	es = expression(table,num);
	if(es>0)
		return es;
	fprintf(fout1,"	POP\n");
	if(es==0 && strcmp(token,";")==0){ 
		fscanf(fp,"%s %s\n",&token,&token1);
		return es;
	}
	else{											//少分号 
		es = 4;
		return es;
	}
}
//< call _stat>→ call ID‘(’ ‘)’
int call_stat(struct vartable table[maxvartablep],int &num){
	int es = 0;
	int address;
	int address1;
	int canshunum=0;
	char fun_name[20];
	int first=0;
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"ID")){					//缺少函数名 
		es = 9;					
		return es; 
	}
	strcpy(fun_name,token1);	
	cha(fun_name,first);
	if(es>0){
		return es;
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"(")){
		es = 5;
		return es;
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	while(strcmp(token,"ID")==0){
		es=lookup(table,token1,&address1,num);
		if(es>0)	return es;
		fprintf(fout1,"	LOAD	%d\n",address1);
		fprintf(fout1,"	STO	%d\n",first+canshunum);
		fprintf(fout1,"	POP\n");
		canshunum++;
		fscanf(fp,"%s %s\n",&token,&token1);
		if(strcmp(token,")")==0)
			break;
		else{
			fscanf(fp,"%s %s\n",&token,&token1);
		} 
	}
	if(strcmp(token,")")){
		es = 6;
		return es;
	}
	es=fun_lookup(fun_name,&address,canshunum);
	fprintf(fout1,"	JSR LABEL%d\n",address);
	
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,";")){
		es = 4;
		return es;
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	return es;
}
//< expression >→ ID=<bool_expr>|<bool_expr> 
int expression(struct vartable table[maxvartablep],int &num){
	int es = 0;
	int fileadd;										//用于保存文件位置
	char token2[20],token3[40];
	if(strcmp(token,"ID")==0){
		fileadd = ftell(fp);							//记录文件位置
		fscanf(fp,"%s %s\n",&token2,&token3);
		if(strcmp(token2,"=")==0){
			int address;
			es=lookup(table,token1,&address,num);
			if(es>0)	return es;
			fscanf(fp,"%s %s\n",&token,&token1);
			es = bool_expr(table,num);
			if(es>0)
				return es; 
			fprintf(fout1,"	STO	%d\n",address);
		}
		else{											//如果不是等号,则指针返回等号之前的标识符 
			fseek(fp,fileadd,0); 
			es = bool_expr(table,num);
			if(es>0)
				return es;
		}
	}
	else{
		es = bool_expr(table,num);
	}
	return es;
}
//<bool_expr>-><additive_expr> |< additive_expr >(>|<|>=|<=|==|!=)< additive_expr > 
//<bool_expr>→<additive_expr>{(>|<|>=|<=|==|!=)<additive_expr>}
int bool_expr(struct vartable table[maxvartablep],int &num){
	int es = 0;
	es = additive_expr(table,num);
	if(es>0)
		return es;
	if(strcmp(token,">")==0||strcmp(token,">=")==0||strcmp(token,"<")==0||strcmp(token,"<=")==0||strcmp(token,"==")==0||strcmp(token,"!=")==0){
		char token2[20];
		strcpy(token2,token);
		fscanf(fp,"%s %s\n",&token,&token1);
		es = additive_expr(table,num);
		if(es>0)
			return es;
		if(strcmp(token2,">")==0)	fprintf(fout1,"	GT\n");
		if(strcmp(token2,">=")==0)	fprintf(fout1,"	GE\n");
		if(strcmp(token2,"<")==0)	fprintf(fout1,"	LES\n");
		if(strcmp(token2,"<=")==0)	fprintf(fout1,"	LE\n");
		if(strcmp(token2,"==")==0)	fprintf(fout1,"	EQ\n");
		if(strcmp(token2,"!=")==0)	fprintf(fout1,"	NOTEQ\n");
	}
	return es;
}
//< additive_expr>→<term>{(+|-)< term >}				算数表达式定义为项或者项加减项
int additive_expr(struct vartable table[maxvartablep],int &num){
	int es = 0;
	es = term(table,num);
	if(es>0)
		return es;
	while(strcmp(token,"+")==0||strcmp(token,"-")==0){
		char token2[20];
		strcpy(token2,token);
		fscanf(fp,"%s %s\n",&token,&token1);
		es = term(table,num);
		if(es>0)
			return es;
		if(strcmp(token2,"+")==0)	fprintf(fout1,"	ADD\n");
		if(strcmp(token2,"-")==0)	fprintf(fout1,"	SUB\n");
	}
	return es;
}
//< term >→<factor>{(*| /)< factor >}					项定义为因子或因子乘或除因子
int term(struct vartable table[maxvartablep],int &num){
	int es = 0;
	es = factor(table,num);
	if(es>0)
		return es;	
	while(strcmp(token,"*")==0||strcmp(token,"/")==0){
		char token2[20];
		strcpy(token2,token);
		fscanf(fp,"%s %s\n",&token,&token1);
		es = factor(table,num);
		if(es>0)
			return es;
		if(strcmp(token2,"*")==0)	fprintf(fout1,"	MULT\n");
		if(strcmp(token2,"/")==0)	fprintf(fout1,"	DIV\n");
	}
	return es;
}
//< factor >→’(‘< additive_expr >’)’|ID|NUM		因子定义为表达式或者标识符或者数字
int factor(struct vartable table[maxvartablep],int &num){
	int es = 0;
	if(strcmp(token,"(")==0){										//因子定义成表达式,根据左括号进行判断
		fscanf(fp,"%s %s\n",&token,&token1);
		es = expression(table,num);
		if(es>0)
			return es;
		if(strcmp(token,")")){										//当缺少右括号时
			es = 6;
			return es;
		}
		fscanf(fp,"%s %s\n",&token,&token1);
	}
	else{															//因子定义成标识符或数字
		if(strcmp(token,"ID")==0){
			int address;
			int flag=1;
			es=lookup(table,token1,&address,num);
			if(es>0)	return es;
			fprintf(fout1,"	LOAD	%d\n",address);
			fscanf(fp,"%s %s\n",&token,&token1);
			return es;
		}
		else if(strcmp(token,"NUM")==0){
			fprintf(fout1,"	LOADI	%s\n",token1);
			fscanf(fp,"%s %s\n",&token,&token1);
		}
		else{
			es = 7;												//缺少操作数
			return es;
		}
	}
	return es; 
}
//词法语法语义分析主函数
#include<stdio.h>
#include<ctype.h>

extern int TESTscan();
extern int TESTparse();

char Scanin[300],Scanout[300];
FILE *fin,*fout;

int main(){
	int es=0;
	es = TESTscan();
	if(es>0)
		printf("词法分析有错,编译停止!\n");
	else
		printf("词法分析成功!\n");
	if(es==0){
		es = TESTparse();
		if(es==0)
			printf("语法分析成功!\n");
		else
			printf("语法语义分析错误!\n");
	}
	return 0; 
}
//虚拟机生成
#include<stdio.h>
#include<ctype.h>
#include<stdlib.h>
#include<string.h>

int TESTmachine();

int TESTmachine(){
	int es=0,i,k=0,codecount,stack[1000],stacktop=0;
	int funstack[100],funstacktop=0;
	char Codein[300],code[1000][20],data[1000];
	int label[100]={0};
	char lno[4];
	FILE *fin;
	/*printf("请输入目标文件名(包括路径):");
	scanf("%s",Codein);*/
	if((fin=fopen("3.txt","r"))==NULL){					
		printf("\n打开%s是错误!\n",code);
		es=10;
		return es;
	}
	codecount=0;
	i=fscanf(fin,"%s",&code[codecount]);
	while(!feof(fin)){
		printf("----|  %d  %s  \n",codecount,code[codecount]);
		i=strlen(code[codecount])-1;
		if(code[codecount][i]==':'){
			i=i-5;
			strncpy(lno,&code[codecount][5],i);
			lno[i]='\0';
			label[atoi(lno)]=codecount;							//???			用label数组记住每一个标号的地址 
			//printf("label[%d]=  %d  \n",atoi(lno),label[atoi(lno)]);
			code[codecount][0]=':';
			code[codecount][1]='\0';
			strcat(code[codecount],lno);
			k++;
		}
		codecount++;
		i=fscanf(fin,"%s",&code[codecount]);
	}
	fclose(fin);
	for(i=0;i<codecount;i++){
		int l;
		l=strlen(code[i]);
		if((l>1)&&(code[i][1]=='A')){
			strncpy(lno,&code[i][5],l-5);
			lno[l-5]='\0';
			itoa(label[atoi(lno)],code[i],10);
		}
	}		
	i=0;
	while(i<codecount){								//执行每条指令 
		//printf("code %d %s \n",i,code[i]);
		if(strcmp(code[i],"JSR")==0){				//JSR LAB 无条件跳到LAB,并将JAR下一行的行标保存在函数栈中,便于执行完函数后继续执行主函数 
			i++;
			funstack[funstacktop]=i+1;
			funstacktop++;
			i=atoi(code[i]);
		}
		if(strcmp(code[i],"RET")==0){				//RET 表示当前函数执行完毕,返回调用处 
			i=funstack[funstacktop-1];
			funstacktop--;
		} 
		if(strcmp(code[i],"LOAD")==0){				//LOAD D 将D中的内容加载到操作数栈 
			i++;
			stack[stacktop]=data[atoi(code[i])];
			stacktop++;
		} 
		if(strcmp(code[i],"LOADI")==0){				//LOADI a 将常量a压入操作数栈 
			i++;
			stack[stacktop]=atoi(code[i]);
			stacktop++; 
		} 
		//STO D将操作数栈顶单元内容存入D,切栈顶单元内容保持不变 
		if(strcmp(code[i],"STO")==0){
			i++; 
			data[atoi(code[i])]=stack[stacktop-1];
			//printf("sto  stack %d\n",stack[stacktop-1]);
			//printf("sto  data %d\n",data[atoi(code[i])]); 
		} 
		//POP 栈顶内容出栈 
		if(strcmp(code[i],"POP")==0){
			stacktop--; 
		} 
		//ADD 将栈顶单元与次栈顶单元出栈并相加,和置于栈顶
		if(strcmp(code[i],"ADD")==0){
			stack[stacktop-2] = stack[stacktop-1]+stack[stacktop-2];
			//printf("add  %d\n",stack[stacktop-1]);
			stacktop--;
		}
		//SUB 将次栈顶单元减去栈顶单元并出栈,差置于栈顶
		if(strcmp(code[i],"SUB")==0){
		 	stack[stacktop-2] = stack[stacktop-2]-stack[stacktop-1];
		 	stacktop--; 
		} 
		//MULT 将次栈顶单元与栈顶单元相乘并出栈,积置于栈顶
		if(strcmp(code[i],"MULT")==0){
		 	stack[stacktop-2] = stack[stacktop-2]*stack[stacktop-1];
		 	stacktop--; 
		} 
	 	//DIV 将次栈顶单元与栈顶单元相除并出栈,商置于栈顶 
		if(strcmp(code[i],"DIV")==0){
		 	stack[stacktop-2] = stack[stacktop-2]/stack[stacktop-1];
		 	stacktop--; 
		} 
		//BR	lab 无条件转移到lab 
		if(strcmp(code[i],"BR")==0){
		 	i++;
		 	i=atoi(code[i]);
		} 
		//BRF lab 	检查栈顶单元逻辑值并出栈,若为假则转移到lab 
		if(strcmp(code[i],"BRF")==0){
		 	i++;
			if(stack[stacktop-1]==0)
				i=atoi(code[i]);
			i--; 
		} 
		//EQ 将栈顶两单元做等于比较并出栈,并将结果真或假(1或0),置于栈顶 
		if(strcmp(code[i],"EQ")==0){
		 	stack[stacktop-2] = stack[stacktop-2]==stack[stacktop-1];
		 	stacktop--; 
		} 
		//NOTEQ 将栈顶两单元做不等于比较并出栈,并将结果真或假(1或0),置于栈顶 
		if(strcmp(code[i],"NOTEQ")==0){
		 	stack[stacktop-2] = stack[stacktop-2]!=stack[stacktop-1];
		 	stacktop--; 
		} 
		//GT 次栈顶大于栈顶操作数并出栈,则栈顶置1,否则置0 
		if(strcmp(code[i],"GT")==0){
		 	stack[stacktop-2] = stack[stacktop-2]>stack[stacktop-1];
		 	stacktop--; 
		} 
		//LES 次栈顶小于栈顶操作数并出栈,则栈顶置1,否则置0 
		if(strcmp(code[i],"LES")==0){
		 	stack[stacktop-2] = stack[stacktop-2]<stack[stacktop-1];
		 	stacktop--; 
		} 
		//GE 次栈顶大于等于栈顶操作数并出栈,则栈顶置1,否则置0 
		if(strcmp(code[i],"GE")==0){
		 	stack[stacktop-2] = stack[stacktop-2]>=stack[stacktop-1];
		 	stacktop--; 
		} 
		//LE 次栈顶小于等于栈顶操作数并出栈,则栈顶置1,否则置0 
		if(strcmp(code[i],"LE")==0){
		 	stack[stacktop-2] = stack[stacktop-2]<=stack[stacktop-1];
		 	stacktop--; 
		} 
		//AND 将栈顶两单元做逻辑与运算并出战,并将结果真或假(1或0)置于栈顶
		if(strcmp(code[i],"AND")==0){
		 	stack[stacktop-2] = stack[stacktop-2]&&stack[stacktop-1];
		 	stacktop--; 
		} 
		//OR 将栈顶两单元做逻辑或运算并出战,并将结果真或假(1或0)置于栈顶
		if(strcmp(code[i],"OR")==0){
		 	stack[stacktop-2] = stack[stacktop-2]||stack[stacktop-1];
		 	stacktop--; 
		} 
		//NOT 将栈顶逻辑值取反
		if(strcmp(code[i],"NOT")==0){
		 	stack[stacktop-1]=!stack[stacktop-1];
		} 
		//IN 从标准输入设备读入一个整型数据,并入栈
		if(strcmp(code[i],"IN")==0){
			printf("请输入数据:");
			scanf("%d",&stack[stacktop]);
			stacktop++; 
		} 
		//OUT 将栈顶内容出栈,并输出到标准输出设备上 
		if(strcmp(code[i],"OUT")==0){
		 	printf("程序输出%d\n",stack[stacktop-1]);
			stacktop--; 
		} 
		//STOP 停止执行
		if(strcmp(code[i],"STOP")==0){
			break;
		} 
		i++;
		//显示栈内容
		/*for(k=stacktop-1;k>=0;k--)
		 	printf("%d  ",stack[k]);
		printf("\n");*/
		//printf("	%d		%d\n",data[0],data[1]);
	} 
	return es;
} 
int main(){
	int es=0;
	es = TESTmachine();
}

 


'; fprintf(fout,"%s\t%s\n","NUM",token); } else if(strchr(singleword,ch)!=NULL){ //strchr用于查找某字符是否存在于某字符数组中,是则返回指针,不是则返回NULL token[0]=ch; token[1]='
//词法分析
#include<stdio.h>
#include<ctype.h>
#include<string.h>

//保留字数目与保留字数组 
#define keywordSum 10
char *keyword[keywordSum] = {"if","else","for","while","read","write","do","int","call","function"};

//纯单分界符
char singleword[50] = "+-*(){};,:";

//双分界符首字符
char doubleword[10] = "<>=!";

//用于接收输入输出文件名 
extern char Scanin[300],Scanout[300]; 

//用于指向输入输出文件的指针 
extern FILE *fin,*fout; 

//用于对保留字数组进行冒泡排序函数(为折半查找做准备)
void sort(char *KW[]){
	int i,j;
	char *temp;
	for(i=0;i<keywordSum;i++){
		for(j=0;j<keywordSum-1;j++){
			if(strcmp(KW[j],KW[j+1])>0){
				temp = KW[j];
				KW[j] = KW[j+1];
				KW[j+1] = temp;
			}
		}
	}
}

//用于查找保留字表的折半查找函数(保留字不区分大小写)
int Search_Bin(char *KW[],char *keyword){
	sort(KW);
	int low=0,high=keywordSum-1;
	int mid;
	while(low<=high){
		mid = (low+high)/2;
		if(stricmp(keyword,KW[mid])==0) return 1;		//stricmp比较不区分大小写 返回1表示查找到 
		else if(stricmp(keyword,KW[mid])>0) low=mid+1;
		else high=mid-1; 
	}
	return 0;											//返回0表示查找失败 
} 

int TESTscan(){
	char ch,token[40];									//ch用于保存当前读出的字符,token用于保存识别出的单词
	int es=0,j,n;										//es为错误识别代码,0表示没有错误。
	int linenum=1;										//用于保存行号 
	printf("请输入源程序文件名(包括路径):");
	scanf("%s",Scanin);
	printf("请输入词法分析输出文件名(包括路径):");
	scanf("%s",Scanout);
	if((fin = fopen(Scanin,"r"))==NULL){
		printf("\n打开词法分析输入文件出错!\n");
		return 1;										//输入文件出错返回错误代码1 
	}
	if((fout = fopen(Scanout,"w"))==NULL){
		printf("\n打开词法分析1输出文件出错!\n");
		return 2; 										//输出文件出错返回错误代码2 
	}
	ch = getc(fin);
	while(ch!=EOF){
		while(ch==' '||ch=='\n'||ch=='\t'){
			if(ch=='\n')								//记录行号 
				linenum++; 
			ch=getc(fin);
		} 
		if(isalpha(ch)){								//如果ch是字母的话,进行标识符处理 
			token[0]=ch;
			j=1;
			ch=getc(fin);
			while(isalnum(ch)){							//如果ch是字母或者数字的话 
				token[j++]=ch;							//组合的标识符保存在token中 
				ch=getc(fin);							//读下一个字符 
			}
			token[j]='\0';								//标识符组合结束 
			//查保留字 
			n=Search_Bin(keyword,token);
			if(n==1)									//是保留字 
				fprintf(fout,"%s\t%s\n",token,token);
			else
				fprintf(fout,"%s\t%s\n","ID",token);	//不是保留字 
		}
		else if(isdigit(ch)){							//如果ch是数字的话,对数字进行处理 
			token[0]=ch;
			j=1;
			ch=getc(fin);
			while(isdigit(ch)){							//如果是数字则整合整数,否则退出 
				token[j++]=ch;
				ch=getc(fin);
			}
			token[j]='\0';
			fprintf(fout,"%s\t%s\n","NUM",token);
		}
		else if(strchr(singleword,ch)!=NULL){			//strchr用于查找某字符是否存在于某字符数组中,是则返回指针,不是则返回NULL 
			token[0]=ch;
			token[1]='\0';
			ch=getc(fin);								//读下一个符号以便识别单词 
			fprintf(fout,"%s\t%s\n",token,token);
		}
		else if(strchr(doubleword,ch)!=NULL){
			token[0]=ch;
			ch=getc(fin);								//读下一个字符判断是否是双分界符 
			if((token[0]!='&'&&token[0]!='|'&&ch=='=')||(token[0]=='|'&&ch=='|')||(token[0]=='&'&&ch=='&')){				//如果是=,|,&则组合双分界符 
				token[1]=ch;
				token[2]='\0';
				ch=getc(fin);
			}
			else{										//否则为单分界符 
				token[1]='\0';
			}
			if(token[0]=='!'||token[0]=='<'||token[0]=='>'||token[0]=='='){
				fprintf(fout,"%s\t%s\n",token,token);
			}
			else{
				printf("%d行发生错误",linenum);
				fprintf(fout,"\n%s\t%s\n","ERROR",token);
				fprintf(fout,"%s  %d\n\n","错误行号为:",linenum);
			} 
		}
		else if(ch=='/'){								//注释处理 
			ch=getc(fin);
			if(ch=='*'){								//如果下一个字符是*则开始进行注释处理 
				char ch1;
				ch1=getc(fin);
				do{
					if(ch1=='\n'){
						linenum++;
					}
					ch=ch1;
					ch1=getc(fin);
				}while((ch!='*'||ch1!='/')&&ch1!=EOF);	//删除注释 
				ch=getc(fin);
			}
			else{										//不是*则输出单分界符 
				token[0]=ch;
				token[1]='\0';
				fprintf(fout,"%s\t%s\n",token,token);
			}
		} 
		else{
			token[0]=ch;								//处理错误 
			token[1]='\0';
			ch=getc(fin);
			es=3;										//设置错误代码 
			printf("%d行发生错误",linenum);
			fprintf(fout,"\n%s\t%s\n","ERROR",token);
			fprintf(fout,"%s  %d\n\n","错误行号为:",linenum);
		}
	}
	fclose(fin);
	fclose(fout);
	return es;	
}
//语法及语义分析
#include<stdio.h>
#include<ctype.h>
#include<conio.h>
#include<string.h>

#define maxvartablep 500				//定义符号表的容量


struct vartable{
	char name[8];
	int address;
};								//符号表最多容纳maxvartablep个记录 

struct fun_table{
	char name[30];
	int address;
	int can_num;
	int first_address;			//记录第一个参数的地址 
}fun_table[maxvartablep];

int program();
int fun_declaration();
int canshu(struct vartable table[maxvartablep],int &num,int &can_num);
int main_declaration();
int function_body(struct vartable table[maxvartablep],int &num);
int declaration_list(struct vartable table[maxvartablep],int &num);
int declaration_stat(struct vartable table[maxvartablep],int &num);
int statement_list(struct vartable table[maxvartablep],int &num);
int statement(struct vartable table[maxvartablep],int &num);
int if_stat(struct vartable table[maxvartablep],int &num);
int while_stat(struct vartable table[maxvartablep],int &num);
int for_stat(struct vartable table[maxvartablep],int &num);
int write_stat(struct vartable table[maxvartablep],int &num);
int read_stat(struct vartable table[maxvartablep],int &num);
int compound_stat(struct vartable table[maxvartablep],int &num);
int expression_stat(struct vartable table[maxvartablep],int &num);
int call_stat(struct vartable table[maxvartablep],int &num);
int expression(struct vartable table[maxvartablep],int &num);
int bool_expr(struct vartable table[maxvartablep],int &num);
int additive_expr(struct vartable table[maxvartablep],int &num);
int term(struct vartable table[maxvartablep],int &num);
int factor(struct vartable table[maxvartablep],int &num);

int name_def(char *name,int vartablep,int datap);
char token[10],token1[40];
extern char Scanout[300],Codeout[300];
FILE *fp,*fout1;
int labelp = 1,datap=0;					//labelp用于记录当前标记,防止重复
int fun_var=0;
//插入符号表@name_def(↓n,t)的程序如下:
int name_def(char *name,vartable table[],int vartablep){
	int i,es = 0;
	if(vartablep>maxvartablep)
		return 21;
	for(i=vartablep-1;i>=0;i--){
		if(strcmp(table[i].name,name)==0){
			es=22;
			break;
		}
	} 
	if(es>0){
		return es;
	}
	strcpy(table[vartablep].name,name);
	table[vartablep].address = datap;
	datap++;
	return es;
}
int fun_def(char *name,int datap,int can_num,int first){
	int i,es = 0;
	if(fun_var>maxvartablep)
		return 31;
	for(i=fun_var-1;i>=0;i--){
		if(strcmp(fun_table[i].name,name)==0&&fun_table[i].can_num==can_num){
			es=32;
			break;
		}
	}
	strcpy(fun_table[fun_var].name,name);
	fun_table[fun_var].address = datap;
	fun_table[fun_var].can_num=can_num;
	fun_table[fun_var].first_address=first;
	fun_var++;
	return es; 
}
//查询符号表返回地址 
int lookup(struct vartable table[],char *name,int *paddress,int num){
	int i,es = 0;
	for(i=0;i<num;i++){
		if(strcmp(table[i].name,name)==0){
			*paddress = table[i].address;
			return es;
		}
	}
	es = 23;
	return es;
} 
int fun_lookup(char *name,int *paddress,int num){
	int i,es = 0;
	for(i=0;i<fun_var;i++){
		if(strcmp(fun_table[i].name,name)==0&&fun_table[i].can_num==num){
			*paddress = fun_table[i].address;
			return es;
		}
	}
	es = 33;
	return es;
} 
void cha(char *name,int &first){
	int i;
	for(i=0;i<fun_var;i++){
		if(strcmp(fun_table[i].name,name)==0){
			first=fun_table[i].first_address;
		}
	}
}
//语义语法分析及代码生成程序
int TESTparse(){
	int es = 0;
	if((fp=fopen(Scanout,"r"))==NULL){
		printf("打开%s错误!\n",Scanout);
		es = 10;
		return es;
	}
	printf("请输入目标文件名(包括路径):");
	char Codeout[20];
	scanf("%s",Codeout);
	if((fout1=fopen(Codeout,"w"))==NULL){
		printf("\n创建%s错误!\n",Codeout);
		es=10;
		return es;
	}
	if(es==0)
		es = program();
	printf("==语法,语义分析及代码生成程序结果==\n");
	switch(es){
		case 0: printf("语法分析成功!\n"); break;
		case 10: printf("打开文件%s失败!\n"); break;
		case 1: printf("缺少{\n"); break;
		case 2: printf("缺少}\n"); break;
		case 3: printf("缺少标识符\n"); break;
		case 4: printf("缺少分号\n"); break;
		case 5: printf("缺少(\n"); break;
		case 6: printf("缺少)\n"); break;
		case 7: printf("缺少操作数\n"); break;
		case 21:printf("符号表溢出\n");break;
		case 22:printf("变量重复定义\n");break;
		case 23:printf("变量未声明\n");break;
		case 31:printf("函数名符号表溢出\n");break;
		case 32:printf("函数重复定义");break; 
		case 33:printf("函数未定义");break; 
		case 41:printf("参数定义出错");break;
	}
	fclose(fp);
	fclose(fout1);
	return es;
} 

int program(){
	int es = 0;
	fscanf(fp,"%s %s\n",&token,&token1);
	fprintf(fout1,"	BR	LABEL0\n");					//产生停止指令
	while(!strcmp(token,"function")){
		es = fun_declaration();
		if(es>0)
			return es;
		fscanf(fp,"%s %s\n",&token,&token1);
	}	
	if(strcmp(token1,"main")){				 
		es = 8;
		return es;
	}
	else{
		es = main_declaration();
		if(es>0)
			return es;
	}
	fprintf(fout1,"	STOP\n");					//产生停止指令
	return es;
}
int fun_declaration(){
	int es = 0;
	struct vartable table[maxvartablep];
	int num = 0; 
	char fun_name[20];
	int can_num=0;	
	int first=0;	
	fprintf(fout1,"LABEL%d:\n",labelp++);
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"ID")){
		es = 9;
		return es;
	}
	strcpy(fun_name,token1);
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"(")){
		es = 5;
		return es;
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"int")==0){
		first=datap;
		es = canshu(table,num,can_num);
		if(es>0)
			return (es=41);
	}
	fun_def(fun_name,labelp-1,can_num,first);
	if(strcmp(token,")")){
		es = 6;
		return es;
	}	
	es = function_body(table,num);
	fprintf(fout1,"LABEL%d:\n",labelp++);
	fprintf(fout1,"	RET\n");
	return es;
}
int canshu(struct vartable table[maxvartablep],int &num,int &can_num){
	int es=0;
	while(strcmp(token,"int")==0){
		can_num++;
		fscanf(fp,"%s %s\n",&token,&token1);
		if(strcmp(token,"ID"))
			return (es = 3);			//不是标识符
		es = name_def(token1,table,num);
		num++;
		if(es>0)
			return es;
		fscanf(fp,"%s %s\n",&token,&token1);
		if(strcmp(token,")")==0){
			break;
		}
		else{
			fscanf(fp,"%s %s\n",&token,&token1);
		}	
	}
	return es;
}
int main_declaration(){
	int es = 0;
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"(")){
		es = 5;
		return es;
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,")")){
		es = 6;
		return es;
	}
	fprintf(fout1,"LABEL0:\n");
	struct vartable table[maxvartablep];
	int num = 0; 			
	es = function_body(table,num);
	return es;
}
int function_body(struct vartable table[maxvartablep],int &num){
	int es=0,i;
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"{")){
		es = 1;
		return es;
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	es = declaration_list(table,num);
	if(es>0)
		return es;
	printf("	符号表\n");
	printf("	变量名	地址\n");
	for(i=0;i<num;i++){
		printf("	%s	%d\n",table[i].name,table[i].address);
	}
	es = statement_list(table,num);
	if(es>0)
		return es;
	if(strcmp(token,"}")){
		es = 2;
		return es;
	} 
	return es;
}
int declaration_list(struct vartable table[maxvartablep],int &num){
	int es = 0;
	while(strcmp(token,"int")==0){
		es = declaration_stat(table,num);
		num++;
		if(es>0)
			return es;
	}
	return es;
}
int declaration_stat(struct vartable table[maxvartablep],int &num){
	int es=0;
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"ID"))
		return (es = 3);			//不是标识符
	es = name_def(token1,table,num);
	if(es>0)
		return es;
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,";")){
		es = 4;
		return es;
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	return es;
} 
int statement_list(struct vartable table[maxvartablep],int &num){
	int es = 0;
	while(strcmp(token,"}")){
		es = statement(table,num);
		if(es>0)
			return es; 
	}
	if(strcmp(token,"}")&&(feof(fp)||strcmp(token,"function")==0||strcmp(token1,"main")==0)){
			es=2;
			return es;
		}
	return es;	
}
int statement(struct vartable table[maxvartablep],int &num){
	int es = 0;
	if(es==0 && strcmp(token,"if")==0)
		es = if_stat(table,num);
	else if(es==0 && strcmp(token,"while")==0)
		es = while_stat(table,num);
	else if(es==0 && strcmp(token,"for")==0)
		es = for_stat(table,num);
	else if(es==0 && strcmp(token,"read")==0)
		es = read_stat(table,num);
	else if(es==0 && strcmp(token,"write")==0)
		es = write_stat(table,num);
	else if(es==0 && strcmp(token,"{")==0)
		es = compound_stat(table,num);
	else if(es==0 && (strcmp(token,"ID")==0)||strcmp(token,"NUM")==0||strcmp(token,"(")==0)
		es = expression_stat(table,num);
	else if(es==0 && strcmp(token,"call")==0)
		es = call_stat(table,num);
	return es;
}
/*if(<expression>)@BRF(↑label1)<statement>@BR(↑label2)@SETlabel(↓label1)
				  [else<statement>]@SETlabel(↓label2)
其中动作符号定义为
	@BRF(↑label1) 输出BRF label1
	@BR(↑label2) 输出BR label2
	@SETlabel(↓label1) 设置标号label1
	@SETlabel(↓label2) 设置标号label2*/
int if_stat(struct vartable table[maxvartablep],int &num){
	int es = 0,label1,label2;
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"(")){
		es = 5;
		return es;
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	es = expression(table,num);
	if(es>0)
		return es;
	if(strcmp(token,")")){
		es = 6;
		return es;
	}
	label1 = labelp++;						//用label1记住当条件为假时要转向的标号
	fprintf(fout1,"	BRF	LABEL%d\n",label1); //输出假转移指令 
	fscanf(fp,"%s %s\n",&token,&token1);
	es = statement(table,num);
	if(es>0)
		return es;
	label2 = labelp++;						//用label2记住要转向的标号 
	fprintf(fout1,"	BR	LABEL%d\n",label2);//输出无条件转移指令 
	fprintf(fout1,"LABEL%d:\n",label1);		//设置label1记住的符号 
	if(strcmp(token,"else")==0){
	fscanf(fp,"%s %s\n",&token,&token1);
	es = statement(table,num);
	if(es>0)
		return es;	
	}
	fprintf(fout1,"LABEL%d:\n",label2); 		//设置label2记住的标号 
	return es;	
}
/*<while_stat>::[email protected](↑label)(<expression>)@BRF(↑label2)
				<statement>@BR(↓label1)@SETlabel(↓label2)
	动作解释为
	@SETlabel(↑label):设置标号label1 
	@BRF(↑label2):输出BRF label2 
	@BR(↓label1):输出BR label1 
	@SETlabel(↓label2):设置标号 label2*/
int while_stat(struct vartable table[maxvartablep],int &num){
	int es = 0,label1,label2;
	label1 = labelp++;							//设置label1标号 
	fprintf(fout1,"LABEL%d:\n",label1);
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"(")){
		es = 5;
		return es;
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	es = expression(table,num);
	if(es>0)
		return es;
	if(strcmp(token,")")){
		es = 6;
		return es;
	}
	label2 = labelp++;
	fprintf(fout1,"	BRF	LABEL%d",label2);			//输出假转移指令 
	fscanf(fp,"%s %s\n",&token,&token1);
	es = statement(table,num);
	if(es>0){
		return es;
	} 
	fprintf(fout1,"	BR	LABEL%d\n",label1);		//输出无条件转移指令 
	fprintf(fout1,"LABEL%d:\n",label2);				//设置label2标号 
	return es;
}
/*<for_stat>::=for(<expression>@POP;
				@SETlabel(label1)<expression>@BRF(label2)@BR(label3)
				@SETlabel(label4)<expression>@[email protected](label1))
				@SETlabel(label3)<语句>@BR(label4)@SETlabel(label2)*/
int for_stat(struct vartable table[maxvartablep],int &num){
	int es = 0,label1,label2,label3,label4;
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"(")){						//少左括号 
		es = 5;
		return es;
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	es = expression(table,num);
	if(es>0)
		return es;
	fprintf(fout1,"	POP\n");				//设置出栈指令 
	if(strcmp(token,";")){
		es = 4;
		return es;
	}
	label1 = labelp++;
	fprintf(fout1,"LABEL%d:\n",label1);		//设置label1标号 
	fscanf(fp,"%s %s\n",&token,&token1);
	es = expression(table,num);
	if(es>0)
		return es;
	label2 = labelp++;
	fprintf(fout1,"	BRF	LABEL%d\n",label2);
	label3 = labelp++;
	fprintf(fout1,"	BR	LABEL%d\n",label3);
	if(strcmp(token,";")){
		es = 4;
		return es;
	}
	label4 = labelp++;
	fprintf(fout1,"LABEL%d:\n",label4);
	fscanf(fp,"%s %s\n",&token,&token1);
	es = expression(table,num);
	if(es>0)
		return es;
	fprintf(fout1,"	POP\n");	
	fprintf(fout1,"	BR	LABEL%d\n",label1);
	if(strcmp(token,")")){
		es = 6;
		return es;
	}
	fprintf(fout1,"LABEL%d:\n",label3);	
	fscanf(fp,"%s %s\n",&token,&token1);
	es = statement(table,num);
	if(es>0)
		return es;
	fprintf(fout1,"	BR	LABEL%d\n",label4);
	fprintf(fout1,"LABEL%d:\n",label2);	
	return es;	
}
int write_stat(struct vartable table[maxvartablep],int &num){									 
	int es = 0;
	fscanf(fp,"%s %s\n",&token,&token1);
	es = expression(table,num);
	if(es>0)
		return es;
	if(strcmp(token,";")){
		es = 4;
		return es;
	}
	fprintf(fout1,"	OUT\n"); 
	fscanf(fp,"%s %s\n",&token,&token1);
	return es;
}
//<read_stat>→read ID								read <标识符>
int read_stat(struct vartable table[],int &num){
	int es = 0,address;
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"ID")){
		es = 3;
		return es;
	}						//缺少标识符 
	es = lookup(table,token1,&address,num);
	if(es>0)	return es;
	fprintf(fout1,"	IN	\n");
	fprintf(fout1,"	STO	%d\n",address);
	fprintf(fout1,"	POP\n");
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,";")){
		es = 4;
		return es;							//缺少分号 
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	return es;
}
int compound_stat(struct vartable table[maxvartablep],int &num){
	int es = 0;
	fscanf(fp,"%s %s\n",&token,&token1);
	es = statement_list(table,num);
	if(es>0){
		return es;
	}
	if(strcmp(token,"}")){
		es=2;
		return es;
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	return es; 
}
//<expression_stat>→< expression >;|; 
int expression_stat(struct vartable table[maxvartablep],int &num){
	int es = 0;
	if(strcmp(token,";")==0){
		fscanf(fp,"%s %s\n",&token,&token1);
		return es;
	} 
	es = expression(table,num);
	if(es>0)
		return es;
	fprintf(fout1,"	POP\n");
	if(es==0 && strcmp(token,";")==0){ 
		fscanf(fp,"%s %s\n",&token,&token1);
		return es;
	}
	else{											//少分号 
		es = 4;
		return es;
	}
}
//< call _stat>→ call ID‘(’ ‘)’
int call_stat(struct vartable table[maxvartablep],int &num){
	int es = 0;
	int address;
	int address1;
	int canshunum=0;
	char fun_name[20];
	int first=0;
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"ID")){					//缺少函数名 
		es = 9;					
		return es; 
	}
	strcpy(fun_name,token1);	
	cha(fun_name,first);
	if(es>0){
		return es;
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"(")){
		es = 5;
		return es;
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	while(strcmp(token,"ID")==0){
		es=lookup(table,token1,&address1,num);
		if(es>0)	return es;
		fprintf(fout1,"	LOAD	%d\n",address1);
		fprintf(fout1,"	STO	%d\n",first+canshunum);
		fprintf(fout1,"	POP\n");
		canshunum++;
		fscanf(fp,"%s %s\n",&token,&token1);
		if(strcmp(token,")")==0)
			break;
		else{
			fscanf(fp,"%s %s\n",&token,&token1);
		} 
	}
	if(strcmp(token,")")){
		es = 6;
		return es;
	}
	es=fun_lookup(fun_name,&address,canshunum);
	fprintf(fout1,"	JSR LABEL%d\n",address);
	
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,";")){
		es = 4;
		return es;
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	return es;
}
//< expression >→ ID=<bool_expr>|<bool_expr> 
int expression(struct vartable table[maxvartablep],int &num){
	int es = 0;
	int fileadd;										//用于保存文件位置
	char token2[20],token3[40];
	if(strcmp(token,"ID")==0){
		fileadd = ftell(fp);							//记录文件位置
		fscanf(fp,"%s %s\n",&token2,&token3);
		if(strcmp(token2,"=")==0){
			int address;
			es=lookup(table,token1,&address,num);
			if(es>0)	return es;
			fscanf(fp,"%s %s\n",&token,&token1);
			es = bool_expr(table,num);
			if(es>0)
				return es; 
			fprintf(fout1,"	STO	%d\n",address);
		}
		else{											//如果不是等号,则指针返回等号之前的标识符 
			fseek(fp,fileadd,0); 
			es = bool_expr(table,num);
			if(es>0)
				return es;
		}
	}
	else{
		es = bool_expr(table,num);
	}
	return es;
}
//<bool_expr>-><additive_expr> |< additive_expr >(>|<|>=|<=|==|!=)< additive_expr > 
//<bool_expr>→<additive_expr>{(>|<|>=|<=|==|!=)<additive_expr>}
int bool_expr(struct vartable table[maxvartablep],int &num){
	int es = 0;
	es = additive_expr(table,num);
	if(es>0)
		return es;
	if(strcmp(token,">")==0||strcmp(token,">=")==0||strcmp(token,"<")==0||strcmp(token,"<=")==0||strcmp(token,"==")==0||strcmp(token,"!=")==0){
		char token2[20];
		strcpy(token2,token);
		fscanf(fp,"%s %s\n",&token,&token1);
		es = additive_expr(table,num);
		if(es>0)
			return es;
		if(strcmp(token2,">")==0)	fprintf(fout1,"	GT\n");
		if(strcmp(token2,">=")==0)	fprintf(fout1,"	GE\n");
		if(strcmp(token2,"<")==0)	fprintf(fout1,"	LES\n");
		if(strcmp(token2,"<=")==0)	fprintf(fout1,"	LE\n");
		if(strcmp(token2,"==")==0)	fprintf(fout1,"	EQ\n");
		if(strcmp(token2,"!=")==0)	fprintf(fout1,"	NOTEQ\n");
	}
	return es;
}
//< additive_expr>→<term>{(+|-)< term >}				算数表达式定义为项或者项加减项
int additive_expr(struct vartable table[maxvartablep],int &num){
	int es = 0;
	es = term(table,num);
	if(es>0)
		return es;
	while(strcmp(token,"+")==0||strcmp(token,"-")==0){
		char token2[20];
		strcpy(token2,token);
		fscanf(fp,"%s %s\n",&token,&token1);
		es = term(table,num);
		if(es>0)
			return es;
		if(strcmp(token2,"+")==0)	fprintf(fout1,"	ADD\n");
		if(strcmp(token2,"-")==0)	fprintf(fout1,"	SUB\n");
	}
	return es;
}
//< term >→<factor>{(*| /)< factor >}					项定义为因子或因子乘或除因子
int term(struct vartable table[maxvartablep],int &num){
	int es = 0;
	es = factor(table,num);
	if(es>0)
		return es;	
	while(strcmp(token,"*")==0||strcmp(token,"/")==0){
		char token2[20];
		strcpy(token2,token);
		fscanf(fp,"%s %s\n",&token,&token1);
		es = factor(table,num);
		if(es>0)
			return es;
		if(strcmp(token2,"*")==0)	fprintf(fout1,"	MULT\n");
		if(strcmp(token2,"/")==0)	fprintf(fout1,"	DIV\n");
	}
	return es;
}
//< factor >→’(‘< additive_expr >’)’|ID|NUM		因子定义为表达式或者标识符或者数字
int factor(struct vartable table[maxvartablep],int &num){
	int es = 0;
	if(strcmp(token,"(")==0){										//因子定义成表达式,根据左括号进行判断
		fscanf(fp,"%s %s\n",&token,&token1);
		es = expression(table,num);
		if(es>0)
			return es;
		if(strcmp(token,")")){										//当缺少右括号时
			es = 6;
			return es;
		}
		fscanf(fp,"%s %s\n",&token,&token1);
	}
	else{															//因子定义成标识符或数字
		if(strcmp(token,"ID")==0){
			int address;
			int flag=1;
			es=lookup(table,token1,&address,num);
			if(es>0)	return es;
			fprintf(fout1,"	LOAD	%d\n",address);
			fscanf(fp,"%s %s\n",&token,&token1);
			return es;
		}
		else if(strcmp(token,"NUM")==0){
			fprintf(fout1,"	LOADI	%s\n",token1);
			fscanf(fp,"%s %s\n",&token,&token1);
		}
		else{
			es = 7;												//缺少操作数
			return es;
		}
	}
	return es; 
}
//词法语法语义分析主函数
#include<stdio.h>
#include<ctype.h>

extern int TESTscan();
extern int TESTparse();

char Scanin[300],Scanout[300];
FILE *fin,*fout;

int main(){
	int es=0;
	es = TESTscan();
	if(es>0)
		printf("词法分析有错,编译停止!\n");
	else
		printf("词法分析成功!\n");
	if(es==0){
		es = TESTparse();
		if(es==0)
			printf("语法分析成功!\n");
		else
			printf("语法语义分析错误!\n");
	}
	return 0; 
}
//虚拟机生成
#include<stdio.h>
#include<ctype.h>
#include<stdlib.h>
#include<string.h>

int TESTmachine();

int TESTmachine(){
	int es=0,i,k=0,codecount,stack[1000],stacktop=0;
	int funstack[100],funstacktop=0;
	char Codein[300],code[1000][20],data[1000];
	int label[100]={0};
	char lno[4];
	FILE *fin;
	/*printf("请输入目标文件名(包括路径):");
	scanf("%s",Codein);*/
	if((fin=fopen("3.txt","r"))==NULL){					
		printf("\n打开%s是错误!\n",code);
		es=10;
		return es;
	}
	codecount=0;
	i=fscanf(fin,"%s",&code[codecount]);
	while(!feof(fin)){
		printf("----|  %d  %s  \n",codecount,code[codecount]);
		i=strlen(code[codecount])-1;
		if(code[codecount][i]==':'){
			i=i-5;
			strncpy(lno,&code[codecount][5],i);
			lno[i]='\0';
			label[atoi(lno)]=codecount;							//???			用label数组记住每一个标号的地址 
			//printf("label[%d]=  %d  \n",atoi(lno),label[atoi(lno)]);
			code[codecount][0]=':';
			code[codecount][1]='\0';
			strcat(code[codecount],lno);
			k++;
		}
		codecount++;
		i=fscanf(fin,"%s",&code[codecount]);
	}
	fclose(fin);
	for(i=0;i<codecount;i++){
		int l;
		l=strlen(code[i]);
		if((l>1)&&(code[i][1]=='A')){
			strncpy(lno,&code[i][5],l-5);
			lno[l-5]='\0';
			itoa(label[atoi(lno)],code[i],10);
		}
	}		
	i=0;
	while(i<codecount){								//执行每条指令 
		//printf("code %d %s \n",i,code[i]);
		if(strcmp(code[i],"JSR")==0){				//JSR LAB 无条件跳到LAB,并将JAR下一行的行标保存在函数栈中,便于执行完函数后继续执行主函数 
			i++;
			funstack[funstacktop]=i+1;
			funstacktop++;
			i=atoi(code[i]);
		}
		if(strcmp(code[i],"RET")==0){				//RET 表示当前函数执行完毕,返回调用处 
			i=funstack[funstacktop-1];
			funstacktop--;
		} 
		if(strcmp(code[i],"LOAD")==0){				//LOAD D 将D中的内容加载到操作数栈 
			i++;
			stack[stacktop]=data[atoi(code[i])];
			stacktop++;
		} 
		if(strcmp(code[i],"LOADI")==0){				//LOADI a 将常量a压入操作数栈 
			i++;
			stack[stacktop]=atoi(code[i]);
			stacktop++; 
		} 
		//STO D将操作数栈顶单元内容存入D,切栈顶单元内容保持不变 
		if(strcmp(code[i],"STO")==0){
			i++; 
			data[atoi(code[i])]=stack[stacktop-1];
			//printf("sto  stack %d\n",stack[stacktop-1]);
			//printf("sto  data %d\n",data[atoi(code[i])]); 
		} 
		//POP 栈顶内容出栈 
		if(strcmp(code[i],"POP")==0){
			stacktop--; 
		} 
		//ADD 将栈顶单元与次栈顶单元出栈并相加,和置于栈顶
		if(strcmp(code[i],"ADD")==0){
			stack[stacktop-2] = stack[stacktop-1]+stack[stacktop-2];
			//printf("add  %d\n",stack[stacktop-1]);
			stacktop--;
		}
		//SUB 将次栈顶单元减去栈顶单元并出栈,差置于栈顶
		if(strcmp(code[i],"SUB")==0){
		 	stack[stacktop-2] = stack[stacktop-2]-stack[stacktop-1];
		 	stacktop--; 
		} 
		//MULT 将次栈顶单元与栈顶单元相乘并出栈,积置于栈顶
		if(strcmp(code[i],"MULT")==0){
		 	stack[stacktop-2] = stack[stacktop-2]*stack[stacktop-1];
		 	stacktop--; 
		} 
	 	//DIV 将次栈顶单元与栈顶单元相除并出栈,商置于栈顶 
		if(strcmp(code[i],"DIV")==0){
		 	stack[stacktop-2] = stack[stacktop-2]/stack[stacktop-1];
		 	stacktop--; 
		} 
		//BR	lab 无条件转移到lab 
		if(strcmp(code[i],"BR")==0){
		 	i++;
		 	i=atoi(code[i]);
		} 
		//BRF lab 	检查栈顶单元逻辑值并出栈,若为假则转移到lab 
		if(strcmp(code[i],"BRF")==0){
		 	i++;
			if(stack[stacktop-1]==0)
				i=atoi(code[i]);
			i--; 
		} 
		//EQ 将栈顶两单元做等于比较并出栈,并将结果真或假(1或0),置于栈顶 
		if(strcmp(code[i],"EQ")==0){
		 	stack[stacktop-2] = stack[stacktop-2]==stack[stacktop-1];
		 	stacktop--; 
		} 
		//NOTEQ 将栈顶两单元做不等于比较并出栈,并将结果真或假(1或0),置于栈顶 
		if(strcmp(code[i],"NOTEQ")==0){
		 	stack[stacktop-2] = stack[stacktop-2]!=stack[stacktop-1];
		 	stacktop--; 
		} 
		//GT 次栈顶大于栈顶操作数并出栈,则栈顶置1,否则置0 
		if(strcmp(code[i],"GT")==0){
		 	stack[stacktop-2] = stack[stacktop-2]>stack[stacktop-1];
		 	stacktop--; 
		} 
		//LES 次栈顶小于栈顶操作数并出栈,则栈顶置1,否则置0 
		if(strcmp(code[i],"LES")==0){
		 	stack[stacktop-2] = stack[stacktop-2]<stack[stacktop-1];
		 	stacktop--; 
		} 
		//GE 次栈顶大于等于栈顶操作数并出栈,则栈顶置1,否则置0 
		if(strcmp(code[i],"GE")==0){
		 	stack[stacktop-2] = stack[stacktop-2]>=stack[stacktop-1];
		 	stacktop--; 
		} 
		//LE 次栈顶小于等于栈顶操作数并出栈,则栈顶置1,否则置0 
		if(strcmp(code[i],"LE")==0){
		 	stack[stacktop-2] = stack[stacktop-2]<=stack[stacktop-1];
		 	stacktop--; 
		} 
		//AND 将栈顶两单元做逻辑与运算并出战,并将结果真或假(1或0)置于栈顶
		if(strcmp(code[i],"AND")==0){
		 	stack[stacktop-2] = stack[stacktop-2]&&stack[stacktop-1];
		 	stacktop--; 
		} 
		//OR 将栈顶两单元做逻辑或运算并出战,并将结果真或假(1或0)置于栈顶
		if(strcmp(code[i],"OR")==0){
		 	stack[stacktop-2] = stack[stacktop-2]||stack[stacktop-1];
		 	stacktop--; 
		} 
		//NOT 将栈顶逻辑值取反
		if(strcmp(code[i],"NOT")==0){
		 	stack[stacktop-1]=!stack[stacktop-1];
		} 
		//IN 从标准输入设备读入一个整型数据,并入栈
		if(strcmp(code[i],"IN")==0){
			printf("请输入数据:");
			scanf("%d",&stack[stacktop]);
			stacktop++; 
		} 
		//OUT 将栈顶内容出栈,并输出到标准输出设备上 
		if(strcmp(code[i],"OUT")==0){
		 	printf("程序输出%d\n",stack[stacktop-1]);
			stacktop--; 
		} 
		//STOP 停止执行
		if(strcmp(code[i],"STOP")==0){
			break;
		} 
		i++;
		//显示栈内容
		/*for(k=stacktop-1;k>=0;k--)
		 	printf("%d  ",stack[k]);
		printf("\n");*/
		//printf("	%d		%d\n",data[0],data[1]);
	} 
	return es;
} 
int main(){
	int es=0;
	es = TESTmachine();
}

 


'; ch=getc(fin); //读下一个符号以便识别单词 fprintf(fout,"%s\t%s\n",token,token); } else if(strchr(doubleword,ch)!=NULL){ token[0]=ch; ch=getc(fin); //读下一个字符判断是否是双分界符 if((token[0]!='&'&&token[0]!='|'&&ch=='=')||(token[0]=='|'&&ch=='|')||(token[0]=='&'&&ch=='&')){ //如果是=,|,&则组合双分界符 token[1]=ch; token[2]='
//词法分析
#include<stdio.h>
#include<ctype.h>
#include<string.h>

//保留字数目与保留字数组 
#define keywordSum 10
char *keyword[keywordSum] = {"if","else","for","while","read","write","do","int","call","function"};

//纯单分界符
char singleword[50] = "+-*(){};,:";

//双分界符首字符
char doubleword[10] = "<>=!";

//用于接收输入输出文件名 
extern char Scanin[300],Scanout[300]; 

//用于指向输入输出文件的指针 
extern FILE *fin,*fout; 

//用于对保留字数组进行冒泡排序函数(为折半查找做准备)
void sort(char *KW[]){
	int i,j;
	char *temp;
	for(i=0;i<keywordSum;i++){
		for(j=0;j<keywordSum-1;j++){
			if(strcmp(KW[j],KW[j+1])>0){
				temp = KW[j];
				KW[j] = KW[j+1];
				KW[j+1] = temp;
			}
		}
	}
}

//用于查找保留字表的折半查找函数(保留字不区分大小写)
int Search_Bin(char *KW[],char *keyword){
	sort(KW);
	int low=0,high=keywordSum-1;
	int mid;
	while(low<=high){
		mid = (low+high)/2;
		if(stricmp(keyword,KW[mid])==0) return 1;		//stricmp比较不区分大小写 返回1表示查找到 
		else if(stricmp(keyword,KW[mid])>0) low=mid+1;
		else high=mid-1; 
	}
	return 0;											//返回0表示查找失败 
} 

int TESTscan(){
	char ch,token[40];									//ch用于保存当前读出的字符,token用于保存识别出的单词
	int es=0,j,n;										//es为错误识别代码,0表示没有错误。
	int linenum=1;										//用于保存行号 
	printf("请输入源程序文件名(包括路径):");
	scanf("%s",Scanin);
	printf("请输入词法分析输出文件名(包括路径):");
	scanf("%s",Scanout);
	if((fin = fopen(Scanin,"r"))==NULL){
		printf("\n打开词法分析输入文件出错!\n");
		return 1;										//输入文件出错返回错误代码1 
	}
	if((fout = fopen(Scanout,"w"))==NULL){
		printf("\n打开词法分析1输出文件出错!\n");
		return 2; 										//输出文件出错返回错误代码2 
	}
	ch = getc(fin);
	while(ch!=EOF){
		while(ch==' '||ch=='\n'||ch=='\t'){
			if(ch=='\n')								//记录行号 
				linenum++; 
			ch=getc(fin);
		} 
		if(isalpha(ch)){								//如果ch是字母的话,进行标识符处理 
			token[0]=ch;
			j=1;
			ch=getc(fin);
			while(isalnum(ch)){							//如果ch是字母或者数字的话 
				token[j++]=ch;							//组合的标识符保存在token中 
				ch=getc(fin);							//读下一个字符 
			}
			token[j]='\0';								//标识符组合结束 
			//查保留字 
			n=Search_Bin(keyword,token);
			if(n==1)									//是保留字 
				fprintf(fout,"%s\t%s\n",token,token);
			else
				fprintf(fout,"%s\t%s\n","ID",token);	//不是保留字 
		}
		else if(isdigit(ch)){							//如果ch是数字的话,对数字进行处理 
			token[0]=ch;
			j=1;
			ch=getc(fin);
			while(isdigit(ch)){							//如果是数字则整合整数,否则退出 
				token[j++]=ch;
				ch=getc(fin);
			}
			token[j]='\0';
			fprintf(fout,"%s\t%s\n","NUM",token);
		}
		else if(strchr(singleword,ch)!=NULL){			//strchr用于查找某字符是否存在于某字符数组中,是则返回指针,不是则返回NULL 
			token[0]=ch;
			token[1]='\0';
			ch=getc(fin);								//读下一个符号以便识别单词 
			fprintf(fout,"%s\t%s\n",token,token);
		}
		else if(strchr(doubleword,ch)!=NULL){
			token[0]=ch;
			ch=getc(fin);								//读下一个字符判断是否是双分界符 
			if((token[0]!='&'&&token[0]!='|'&&ch=='=')||(token[0]=='|'&&ch=='|')||(token[0]=='&'&&ch=='&')){				//如果是=,|,&则组合双分界符 
				token[1]=ch;
				token[2]='\0';
				ch=getc(fin);
			}
			else{										//否则为单分界符 
				token[1]='\0';
			}
			if(token[0]=='!'||token[0]=='<'||token[0]=='>'||token[0]=='='){
				fprintf(fout,"%s\t%s\n",token,token);
			}
			else{
				printf("%d行发生错误",linenum);
				fprintf(fout,"\n%s\t%s\n","ERROR",token);
				fprintf(fout,"%s  %d\n\n","错误行号为:",linenum);
			} 
		}
		else if(ch=='/'){								//注释处理 
			ch=getc(fin);
			if(ch=='*'){								//如果下一个字符是*则开始进行注释处理 
				char ch1;
				ch1=getc(fin);
				do{
					if(ch1=='\n'){
						linenum++;
					}
					ch=ch1;
					ch1=getc(fin);
				}while((ch!='*'||ch1!='/')&&ch1!=EOF);	//删除注释 
				ch=getc(fin);
			}
			else{										//不是*则输出单分界符 
				token[0]=ch;
				token[1]='\0';
				fprintf(fout,"%s\t%s\n",token,token);
			}
		} 
		else{
			token[0]=ch;								//处理错误 
			token[1]='\0';
			ch=getc(fin);
			es=3;										//设置错误代码 
			printf("%d行发生错误",linenum);
			fprintf(fout,"\n%s\t%s\n","ERROR",token);
			fprintf(fout,"%s  %d\n\n","错误行号为:",linenum);
		}
	}
	fclose(fin);
	fclose(fout);
	return es;	
}
//语法及语义分析
#include<stdio.h>
#include<ctype.h>
#include<conio.h>
#include<string.h>

#define maxvartablep 500				//定义符号表的容量


struct vartable{
	char name[8];
	int address;
};								//符号表最多容纳maxvartablep个记录 

struct fun_table{
	char name[30];
	int address;
	int can_num;
	int first_address;			//记录第一个参数的地址 
}fun_table[maxvartablep];

int program();
int fun_declaration();
int canshu(struct vartable table[maxvartablep],int &num,int &can_num);
int main_declaration();
int function_body(struct vartable table[maxvartablep],int &num);
int declaration_list(struct vartable table[maxvartablep],int &num);
int declaration_stat(struct vartable table[maxvartablep],int &num);
int statement_list(struct vartable table[maxvartablep],int &num);
int statement(struct vartable table[maxvartablep],int &num);
int if_stat(struct vartable table[maxvartablep],int &num);
int while_stat(struct vartable table[maxvartablep],int &num);
int for_stat(struct vartable table[maxvartablep],int &num);
int write_stat(struct vartable table[maxvartablep],int &num);
int read_stat(struct vartable table[maxvartablep],int &num);
int compound_stat(struct vartable table[maxvartablep],int &num);
int expression_stat(struct vartable table[maxvartablep],int &num);
int call_stat(struct vartable table[maxvartablep],int &num);
int expression(struct vartable table[maxvartablep],int &num);
int bool_expr(struct vartable table[maxvartablep],int &num);
int additive_expr(struct vartable table[maxvartablep],int &num);
int term(struct vartable table[maxvartablep],int &num);
int factor(struct vartable table[maxvartablep],int &num);

int name_def(char *name,int vartablep,int datap);
char token[10],token1[40];
extern char Scanout[300],Codeout[300];
FILE *fp,*fout1;
int labelp = 1,datap=0;					//labelp用于记录当前标记,防止重复
int fun_var=0;
//插入符号表@name_def(↓n,t)的程序如下:
int name_def(char *name,vartable table[],int vartablep){
	int i,es = 0;
	if(vartablep>maxvartablep)
		return 21;
	for(i=vartablep-1;i>=0;i--){
		if(strcmp(table[i].name,name)==0){
			es=22;
			break;
		}
	} 
	if(es>0){
		return es;
	}
	strcpy(table[vartablep].name,name);
	table[vartablep].address = datap;
	datap++;
	return es;
}
int fun_def(char *name,int datap,int can_num,int first){
	int i,es = 0;
	if(fun_var>maxvartablep)
		return 31;
	for(i=fun_var-1;i>=0;i--){
		if(strcmp(fun_table[i].name,name)==0&&fun_table[i].can_num==can_num){
			es=32;
			break;
		}
	}
	strcpy(fun_table[fun_var].name,name);
	fun_table[fun_var].address = datap;
	fun_table[fun_var].can_num=can_num;
	fun_table[fun_var].first_address=first;
	fun_var++;
	return es; 
}
//查询符号表返回地址 
int lookup(struct vartable table[],char *name,int *paddress,int num){
	int i,es = 0;
	for(i=0;i<num;i++){
		if(strcmp(table[i].name,name)==0){
			*paddress = table[i].address;
			return es;
		}
	}
	es = 23;
	return es;
} 
int fun_lookup(char *name,int *paddress,int num){
	int i,es = 0;
	for(i=0;i<fun_var;i++){
		if(strcmp(fun_table[i].name,name)==0&&fun_table[i].can_num==num){
			*paddress = fun_table[i].address;
			return es;
		}
	}
	es = 33;
	return es;
} 
void cha(char *name,int &first){
	int i;
	for(i=0;i<fun_var;i++){
		if(strcmp(fun_table[i].name,name)==0){
			first=fun_table[i].first_address;
		}
	}
}
//语义语法分析及代码生成程序
int TESTparse(){
	int es = 0;
	if((fp=fopen(Scanout,"r"))==NULL){
		printf("打开%s错误!\n",Scanout);
		es = 10;
		return es;
	}
	printf("请输入目标文件名(包括路径):");
	char Codeout[20];
	scanf("%s",Codeout);
	if((fout1=fopen(Codeout,"w"))==NULL){
		printf("\n创建%s错误!\n",Codeout);
		es=10;
		return es;
	}
	if(es==0)
		es = program();
	printf("==语法,语义分析及代码生成程序结果==\n");
	switch(es){
		case 0: printf("语法分析成功!\n"); break;
		case 10: printf("打开文件%s失败!\n"); break;
		case 1: printf("缺少{\n"); break;
		case 2: printf("缺少}\n"); break;
		case 3: printf("缺少标识符\n"); break;
		case 4: printf("缺少分号\n"); break;
		case 5: printf("缺少(\n"); break;
		case 6: printf("缺少)\n"); break;
		case 7: printf("缺少操作数\n"); break;
		case 21:printf("符号表溢出\n");break;
		case 22:printf("变量重复定义\n");break;
		case 23:printf("变量未声明\n");break;
		case 31:printf("函数名符号表溢出\n");break;
		case 32:printf("函数重复定义");break; 
		case 33:printf("函数未定义");break; 
		case 41:printf("参数定义出错");break;
	}
	fclose(fp);
	fclose(fout1);
	return es;
} 

int program(){
	int es = 0;
	fscanf(fp,"%s %s\n",&token,&token1);
	fprintf(fout1,"	BR	LABEL0\n");					//产生停止指令
	while(!strcmp(token,"function")){
		es = fun_declaration();
		if(es>0)
			return es;
		fscanf(fp,"%s %s\n",&token,&token1);
	}	
	if(strcmp(token1,"main")){				 
		es = 8;
		return es;
	}
	else{
		es = main_declaration();
		if(es>0)
			return es;
	}
	fprintf(fout1,"	STOP\n");					//产生停止指令
	return es;
}
int fun_declaration(){
	int es = 0;
	struct vartable table[maxvartablep];
	int num = 0; 
	char fun_name[20];
	int can_num=0;	
	int first=0;	
	fprintf(fout1,"LABEL%d:\n",labelp++);
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"ID")){
		es = 9;
		return es;
	}
	strcpy(fun_name,token1);
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"(")){
		es = 5;
		return es;
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"int")==0){
		first=datap;
		es = canshu(table,num,can_num);
		if(es>0)
			return (es=41);
	}
	fun_def(fun_name,labelp-1,can_num,first);
	if(strcmp(token,")")){
		es = 6;
		return es;
	}	
	es = function_body(table,num);
	fprintf(fout1,"LABEL%d:\n",labelp++);
	fprintf(fout1,"	RET\n");
	return es;
}
int canshu(struct vartable table[maxvartablep],int &num,int &can_num){
	int es=0;
	while(strcmp(token,"int")==0){
		can_num++;
		fscanf(fp,"%s %s\n",&token,&token1);
		if(strcmp(token,"ID"))
			return (es = 3);			//不是标识符
		es = name_def(token1,table,num);
		num++;
		if(es>0)
			return es;
		fscanf(fp,"%s %s\n",&token,&token1);
		if(strcmp(token,")")==0){
			break;
		}
		else{
			fscanf(fp,"%s %s\n",&token,&token1);
		}	
	}
	return es;
}
int main_declaration(){
	int es = 0;
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"(")){
		es = 5;
		return es;
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,")")){
		es = 6;
		return es;
	}
	fprintf(fout1,"LABEL0:\n");
	struct vartable table[maxvartablep];
	int num = 0; 			
	es = function_body(table,num);
	return es;
}
int function_body(struct vartable table[maxvartablep],int &num){
	int es=0,i;
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"{")){
		es = 1;
		return es;
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	es = declaration_list(table,num);
	if(es>0)
		return es;
	printf("	符号表\n");
	printf("	变量名	地址\n");
	for(i=0;i<num;i++){
		printf("	%s	%d\n",table[i].name,table[i].address);
	}
	es = statement_list(table,num);
	if(es>0)
		return es;
	if(strcmp(token,"}")){
		es = 2;
		return es;
	} 
	return es;
}
int declaration_list(struct vartable table[maxvartablep],int &num){
	int es = 0;
	while(strcmp(token,"int")==0){
		es = declaration_stat(table,num);
		num++;
		if(es>0)
			return es;
	}
	return es;
}
int declaration_stat(struct vartable table[maxvartablep],int &num){
	int es=0;
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"ID"))
		return (es = 3);			//不是标识符
	es = name_def(token1,table,num);
	if(es>0)
		return es;
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,";")){
		es = 4;
		return es;
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	return es;
} 
int statement_list(struct vartable table[maxvartablep],int &num){
	int es = 0;
	while(strcmp(token,"}")){
		es = statement(table,num);
		if(es>0)
			return es; 
	}
	if(strcmp(token,"}")&&(feof(fp)||strcmp(token,"function")==0||strcmp(token1,"main")==0)){
			es=2;
			return es;
		}
	return es;	
}
int statement(struct vartable table[maxvartablep],int &num){
	int es = 0;
	if(es==0 && strcmp(token,"if")==0)
		es = if_stat(table,num);
	else if(es==0 && strcmp(token,"while")==0)
		es = while_stat(table,num);
	else if(es==0 && strcmp(token,"for")==0)
		es = for_stat(table,num);
	else if(es==0 && strcmp(token,"read")==0)
		es = read_stat(table,num);
	else if(es==0 && strcmp(token,"write")==0)
		es = write_stat(table,num);
	else if(es==0 && strcmp(token,"{")==0)
		es = compound_stat(table,num);
	else if(es==0 && (strcmp(token,"ID")==0)||strcmp(token,"NUM")==0||strcmp(token,"(")==0)
		es = expression_stat(table,num);
	else if(es==0 && strcmp(token,"call")==0)
		es = call_stat(table,num);
	return es;
}
/*if(<expression>)@BRF(↑label1)<statement>@BR(↑label2)@SETlabel(↓label1)
				  [else<statement>]@SETlabel(↓label2)
其中动作符号定义为
	@BRF(↑label1) 输出BRF label1
	@BR(↑label2) 输出BR label2
	@SETlabel(↓label1) 设置标号label1
	@SETlabel(↓label2) 设置标号label2*/
int if_stat(struct vartable table[maxvartablep],int &num){
	int es = 0,label1,label2;
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"(")){
		es = 5;
		return es;
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	es = expression(table,num);
	if(es>0)
		return es;
	if(strcmp(token,")")){
		es = 6;
		return es;
	}
	label1 = labelp++;						//用label1记住当条件为假时要转向的标号
	fprintf(fout1,"	BRF	LABEL%d\n",label1); //输出假转移指令 
	fscanf(fp,"%s %s\n",&token,&token1);
	es = statement(table,num);
	if(es>0)
		return es;
	label2 = labelp++;						//用label2记住要转向的标号 
	fprintf(fout1,"	BR	LABEL%d\n",label2);//输出无条件转移指令 
	fprintf(fout1,"LABEL%d:\n",label1);		//设置label1记住的符号 
	if(strcmp(token,"else")==0){
	fscanf(fp,"%s %s\n",&token,&token1);
	es = statement(table,num);
	if(es>0)
		return es;	
	}
	fprintf(fout1,"LABEL%d:\n",label2); 		//设置label2记住的标号 
	return es;	
}
/*<while_stat>::[email protected](↑label)(<expression>)@BRF(↑label2)
				<statement>@BR(↓label1)@SETlabel(↓label2)
	动作解释为
	@SETlabel(↑label):设置标号label1 
	@BRF(↑label2):输出BRF label2 
	@BR(↓label1):输出BR label1 
	@SETlabel(↓label2):设置标号 label2*/
int while_stat(struct vartable table[maxvartablep],int &num){
	int es = 0,label1,label2;
	label1 = labelp++;							//设置label1标号 
	fprintf(fout1,"LABEL%d:\n",label1);
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"(")){
		es = 5;
		return es;
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	es = expression(table,num);
	if(es>0)
		return es;
	if(strcmp(token,")")){
		es = 6;
		return es;
	}
	label2 = labelp++;
	fprintf(fout1,"	BRF	LABEL%d",label2);			//输出假转移指令 
	fscanf(fp,"%s %s\n",&token,&token1);
	es = statement(table,num);
	if(es>0){
		return es;
	} 
	fprintf(fout1,"	BR	LABEL%d\n",label1);		//输出无条件转移指令 
	fprintf(fout1,"LABEL%d:\n",label2);				//设置label2标号 
	return es;
}
/*<for_stat>::=for(<expression>@POP;
				@SETlabel(label1)<expression>@BRF(label2)@BR(label3)
				@SETlabel(label4)<expression>@[email protected](label1))
				@SETlabel(label3)<语句>@BR(label4)@SETlabel(label2)*/
int for_stat(struct vartable table[maxvartablep],int &num){
	int es = 0,label1,label2,label3,label4;
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"(")){						//少左括号 
		es = 5;
		return es;
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	es = expression(table,num);
	if(es>0)
		return es;
	fprintf(fout1,"	POP\n");				//设置出栈指令 
	if(strcmp(token,";")){
		es = 4;
		return es;
	}
	label1 = labelp++;
	fprintf(fout1,"LABEL%d:\n",label1);		//设置label1标号 
	fscanf(fp,"%s %s\n",&token,&token1);
	es = expression(table,num);
	if(es>0)
		return es;
	label2 = labelp++;
	fprintf(fout1,"	BRF	LABEL%d\n",label2);
	label3 = labelp++;
	fprintf(fout1,"	BR	LABEL%d\n",label3);
	if(strcmp(token,";")){
		es = 4;
		return es;
	}
	label4 = labelp++;
	fprintf(fout1,"LABEL%d:\n",label4);
	fscanf(fp,"%s %s\n",&token,&token1);
	es = expression(table,num);
	if(es>0)
		return es;
	fprintf(fout1,"	POP\n");	
	fprintf(fout1,"	BR	LABEL%d\n",label1);
	if(strcmp(token,")")){
		es = 6;
		return es;
	}
	fprintf(fout1,"LABEL%d:\n",label3);	
	fscanf(fp,"%s %s\n",&token,&token1);
	es = statement(table,num);
	if(es>0)
		return es;
	fprintf(fout1,"	BR	LABEL%d\n",label4);
	fprintf(fout1,"LABEL%d:\n",label2);	
	return es;	
}
int write_stat(struct vartable table[maxvartablep],int &num){									 
	int es = 0;
	fscanf(fp,"%s %s\n",&token,&token1);
	es = expression(table,num);
	if(es>0)
		return es;
	if(strcmp(token,";")){
		es = 4;
		return es;
	}
	fprintf(fout1,"	OUT\n"); 
	fscanf(fp,"%s %s\n",&token,&token1);
	return es;
}
//<read_stat>→read ID								read <标识符>
int read_stat(struct vartable table[],int &num){
	int es = 0,address;
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"ID")){
		es = 3;
		return es;
	}						//缺少标识符 
	es = lookup(table,token1,&address,num);
	if(es>0)	return es;
	fprintf(fout1,"	IN	\n");
	fprintf(fout1,"	STO	%d\n",address);
	fprintf(fout1,"	POP\n");
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,";")){
		es = 4;
		return es;							//缺少分号 
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	return es;
}
int compound_stat(struct vartable table[maxvartablep],int &num){
	int es = 0;
	fscanf(fp,"%s %s\n",&token,&token1);
	es = statement_list(table,num);
	if(es>0){
		return es;
	}
	if(strcmp(token,"}")){
		es=2;
		return es;
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	return es; 
}
//<expression_stat>→< expression >;|; 
int expression_stat(struct vartable table[maxvartablep],int &num){
	int es = 0;
	if(strcmp(token,";")==0){
		fscanf(fp,"%s %s\n",&token,&token1);
		return es;
	} 
	es = expression(table,num);
	if(es>0)
		return es;
	fprintf(fout1,"	POP\n");
	if(es==0 && strcmp(token,";")==0){ 
		fscanf(fp,"%s %s\n",&token,&token1);
		return es;
	}
	else{											//少分号 
		es = 4;
		return es;
	}
}
//< call _stat>→ call ID‘(’ ‘)’
int call_stat(struct vartable table[maxvartablep],int &num){
	int es = 0;
	int address;
	int address1;
	int canshunum=0;
	char fun_name[20];
	int first=0;
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"ID")){					//缺少函数名 
		es = 9;					
		return es; 
	}
	strcpy(fun_name,token1);	
	cha(fun_name,first);
	if(es>0){
		return es;
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"(")){
		es = 5;
		return es;
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	while(strcmp(token,"ID")==0){
		es=lookup(table,token1,&address1,num);
		if(es>0)	return es;
		fprintf(fout1,"	LOAD	%d\n",address1);
		fprintf(fout1,"	STO	%d\n",first+canshunum);
		fprintf(fout1,"	POP\n");
		canshunum++;
		fscanf(fp,"%s %s\n",&token,&token1);
		if(strcmp(token,")")==0)
			break;
		else{
			fscanf(fp,"%s %s\n",&token,&token1);
		} 
	}
	if(strcmp(token,")")){
		es = 6;
		return es;
	}
	es=fun_lookup(fun_name,&address,canshunum);
	fprintf(fout1,"	JSR LABEL%d\n",address);
	
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,";")){
		es = 4;
		return es;
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	return es;
}
//< expression >→ ID=<bool_expr>|<bool_expr> 
int expression(struct vartable table[maxvartablep],int &num){
	int es = 0;
	int fileadd;										//用于保存文件位置
	char token2[20],token3[40];
	if(strcmp(token,"ID")==0){
		fileadd = ftell(fp);							//记录文件位置
		fscanf(fp,"%s %s\n",&token2,&token3);
		if(strcmp(token2,"=")==0){
			int address;
			es=lookup(table,token1,&address,num);
			if(es>0)	return es;
			fscanf(fp,"%s %s\n",&token,&token1);
			es = bool_expr(table,num);
			if(es>0)
				return es; 
			fprintf(fout1,"	STO	%d\n",address);
		}
		else{											//如果不是等号,则指针返回等号之前的标识符 
			fseek(fp,fileadd,0); 
			es = bool_expr(table,num);
			if(es>0)
				return es;
		}
	}
	else{
		es = bool_expr(table,num);
	}
	return es;
}
//<bool_expr>-><additive_expr> |< additive_expr >(>|<|>=|<=|==|!=)< additive_expr > 
//<bool_expr>→<additive_expr>{(>|<|>=|<=|==|!=)<additive_expr>}
int bool_expr(struct vartable table[maxvartablep],int &num){
	int es = 0;
	es = additive_expr(table,num);
	if(es>0)
		return es;
	if(strcmp(token,">")==0||strcmp(token,">=")==0||strcmp(token,"<")==0||strcmp(token,"<=")==0||strcmp(token,"==")==0||strcmp(token,"!=")==0){
		char token2[20];
		strcpy(token2,token);
		fscanf(fp,"%s %s\n",&token,&token1);
		es = additive_expr(table,num);
		if(es>0)
			return es;
		if(strcmp(token2,">")==0)	fprintf(fout1,"	GT\n");
		if(strcmp(token2,">=")==0)	fprintf(fout1,"	GE\n");
		if(strcmp(token2,"<")==0)	fprintf(fout1,"	LES\n");
		if(strcmp(token2,"<=")==0)	fprintf(fout1,"	LE\n");
		if(strcmp(token2,"==")==0)	fprintf(fout1,"	EQ\n");
		if(strcmp(token2,"!=")==0)	fprintf(fout1,"	NOTEQ\n");
	}
	return es;
}
//< additive_expr>→<term>{(+|-)< term >}				算数表达式定义为项或者项加减项
int additive_expr(struct vartable table[maxvartablep],int &num){
	int es = 0;
	es = term(table,num);
	if(es>0)
		return es;
	while(strcmp(token,"+")==0||strcmp(token,"-")==0){
		char token2[20];
		strcpy(token2,token);
		fscanf(fp,"%s %s\n",&token,&token1);
		es = term(table,num);
		if(es>0)
			return es;
		if(strcmp(token2,"+")==0)	fprintf(fout1,"	ADD\n");
		if(strcmp(token2,"-")==0)	fprintf(fout1,"	SUB\n");
	}
	return es;
}
//< term >→<factor>{(*| /)< factor >}					项定义为因子或因子乘或除因子
int term(struct vartable table[maxvartablep],int &num){
	int es = 0;
	es = factor(table,num);
	if(es>0)
		return es;	
	while(strcmp(token,"*")==0||strcmp(token,"/")==0){
		char token2[20];
		strcpy(token2,token);
		fscanf(fp,"%s %s\n",&token,&token1);
		es = factor(table,num);
		if(es>0)
			return es;
		if(strcmp(token2,"*")==0)	fprintf(fout1,"	MULT\n");
		if(strcmp(token2,"/")==0)	fprintf(fout1,"	DIV\n");
	}
	return es;
}
//< factor >→’(‘< additive_expr >’)’|ID|NUM		因子定义为表达式或者标识符或者数字
int factor(struct vartable table[maxvartablep],int &num){
	int es = 0;
	if(strcmp(token,"(")==0){										//因子定义成表达式,根据左括号进行判断
		fscanf(fp,"%s %s\n",&token,&token1);
		es = expression(table,num);
		if(es>0)
			return es;
		if(strcmp(token,")")){										//当缺少右括号时
			es = 6;
			return es;
		}
		fscanf(fp,"%s %s\n",&token,&token1);
	}
	else{															//因子定义成标识符或数字
		if(strcmp(token,"ID")==0){
			int address;
			int flag=1;
			es=lookup(table,token1,&address,num);
			if(es>0)	return es;
			fprintf(fout1,"	LOAD	%d\n",address);
			fscanf(fp,"%s %s\n",&token,&token1);
			return es;
		}
		else if(strcmp(token,"NUM")==0){
			fprintf(fout1,"	LOADI	%s\n",token1);
			fscanf(fp,"%s %s\n",&token,&token1);
		}
		else{
			es = 7;												//缺少操作数
			return es;
		}
	}
	return es; 
}
//词法语法语义分析主函数
#include<stdio.h>
#include<ctype.h>

extern int TESTscan();
extern int TESTparse();

char Scanin[300],Scanout[300];
FILE *fin,*fout;

int main(){
	int es=0;
	es = TESTscan();
	if(es>0)
		printf("词法分析有错,编译停止!\n");
	else
		printf("词法分析成功!\n");
	if(es==0){
		es = TESTparse();
		if(es==0)
			printf("语法分析成功!\n");
		else
			printf("语法语义分析错误!\n");
	}
	return 0; 
}
//虚拟机生成
#include<stdio.h>
#include<ctype.h>
#include<stdlib.h>
#include<string.h>

int TESTmachine();

int TESTmachine(){
	int es=0,i,k=0,codecount,stack[1000],stacktop=0;
	int funstack[100],funstacktop=0;
	char Codein[300],code[1000][20],data[1000];
	int label[100]={0};
	char lno[4];
	FILE *fin;
	/*printf("请输入目标文件名(包括路径):");
	scanf("%s",Codein);*/
	if((fin=fopen("3.txt","r"))==NULL){					
		printf("\n打开%s是错误!\n",code);
		es=10;
		return es;
	}
	codecount=0;
	i=fscanf(fin,"%s",&code[codecount]);
	while(!feof(fin)){
		printf("----|  %d  %s  \n",codecount,code[codecount]);
		i=strlen(code[codecount])-1;
		if(code[codecount][i]==':'){
			i=i-5;
			strncpy(lno,&code[codecount][5],i);
			lno[i]='\0';
			label[atoi(lno)]=codecount;							//???			用label数组记住每一个标号的地址 
			//printf("label[%d]=  %d  \n",atoi(lno),label[atoi(lno)]);
			code[codecount][0]=':';
			code[codecount][1]='\0';
			strcat(code[codecount],lno);
			k++;
		}
		codecount++;
		i=fscanf(fin,"%s",&code[codecount]);
	}
	fclose(fin);
	for(i=0;i<codecount;i++){
		int l;
		l=strlen(code[i]);
		if((l>1)&&(code[i][1]=='A')){
			strncpy(lno,&code[i][5],l-5);
			lno[l-5]='\0';
			itoa(label[atoi(lno)],code[i],10);
		}
	}		
	i=0;
	while(i<codecount){								//执行每条指令 
		//printf("code %d %s \n",i,code[i]);
		if(strcmp(code[i],"JSR")==0){				//JSR LAB 无条件跳到LAB,并将JAR下一行的行标保存在函数栈中,便于执行完函数后继续执行主函数 
			i++;
			funstack[funstacktop]=i+1;
			funstacktop++;
			i=atoi(code[i]);
		}
		if(strcmp(code[i],"RET")==0){				//RET 表示当前函数执行完毕,返回调用处 
			i=funstack[funstacktop-1];
			funstacktop--;
		} 
		if(strcmp(code[i],"LOAD")==0){				//LOAD D 将D中的内容加载到操作数栈 
			i++;
			stack[stacktop]=data[atoi(code[i])];
			stacktop++;
		} 
		if(strcmp(code[i],"LOADI")==0){				//LOADI a 将常量a压入操作数栈 
			i++;
			stack[stacktop]=atoi(code[i]);
			stacktop++; 
		} 
		//STO D将操作数栈顶单元内容存入D,切栈顶单元内容保持不变 
		if(strcmp(code[i],"STO")==0){
			i++; 
			data[atoi(code[i])]=stack[stacktop-1];
			//printf("sto  stack %d\n",stack[stacktop-1]);
			//printf("sto  data %d\n",data[atoi(code[i])]); 
		} 
		//POP 栈顶内容出栈 
		if(strcmp(code[i],"POP")==0){
			stacktop--; 
		} 
		//ADD 将栈顶单元与次栈顶单元出栈并相加,和置于栈顶
		if(strcmp(code[i],"ADD")==0){
			stack[stacktop-2] = stack[stacktop-1]+stack[stacktop-2];
			//printf("add  %d\n",stack[stacktop-1]);
			stacktop--;
		}
		//SUB 将次栈顶单元减去栈顶单元并出栈,差置于栈顶
		if(strcmp(code[i],"SUB")==0){
		 	stack[stacktop-2] = stack[stacktop-2]-stack[stacktop-1];
		 	stacktop--; 
		} 
		//MULT 将次栈顶单元与栈顶单元相乘并出栈,积置于栈顶
		if(strcmp(code[i],"MULT")==0){
		 	stack[stacktop-2] = stack[stacktop-2]*stack[stacktop-1];
		 	stacktop--; 
		} 
	 	//DIV 将次栈顶单元与栈顶单元相除并出栈,商置于栈顶 
		if(strcmp(code[i],"DIV")==0){
		 	stack[stacktop-2] = stack[stacktop-2]/stack[stacktop-1];
		 	stacktop--; 
		} 
		//BR	lab 无条件转移到lab 
		if(strcmp(code[i],"BR")==0){
		 	i++;
		 	i=atoi(code[i]);
		} 
		//BRF lab 	检查栈顶单元逻辑值并出栈,若为假则转移到lab 
		if(strcmp(code[i],"BRF")==0){
		 	i++;
			if(stack[stacktop-1]==0)
				i=atoi(code[i]);
			i--; 
		} 
		//EQ 将栈顶两单元做等于比较并出栈,并将结果真或假(1或0),置于栈顶 
		if(strcmp(code[i],"EQ")==0){
		 	stack[stacktop-2] = stack[stacktop-2]==stack[stacktop-1];
		 	stacktop--; 
		} 
		//NOTEQ 将栈顶两单元做不等于比较并出栈,并将结果真或假(1或0),置于栈顶 
		if(strcmp(code[i],"NOTEQ")==0){
		 	stack[stacktop-2] = stack[stacktop-2]!=stack[stacktop-1];
		 	stacktop--; 
		} 
		//GT 次栈顶大于栈顶操作数并出栈,则栈顶置1,否则置0 
		if(strcmp(code[i],"GT")==0){
		 	stack[stacktop-2] = stack[stacktop-2]>stack[stacktop-1];
		 	stacktop--; 
		} 
		//LES 次栈顶小于栈顶操作数并出栈,则栈顶置1,否则置0 
		if(strcmp(code[i],"LES")==0){
		 	stack[stacktop-2] = stack[stacktop-2]<stack[stacktop-1];
		 	stacktop--; 
		} 
		//GE 次栈顶大于等于栈顶操作数并出栈,则栈顶置1,否则置0 
		if(strcmp(code[i],"GE")==0){
		 	stack[stacktop-2] = stack[stacktop-2]>=stack[stacktop-1];
		 	stacktop--; 
		} 
		//LE 次栈顶小于等于栈顶操作数并出栈,则栈顶置1,否则置0 
		if(strcmp(code[i],"LE")==0){
		 	stack[stacktop-2] = stack[stacktop-2]<=stack[stacktop-1];
		 	stacktop--; 
		} 
		//AND 将栈顶两单元做逻辑与运算并出战,并将结果真或假(1或0)置于栈顶
		if(strcmp(code[i],"AND")==0){
		 	stack[stacktop-2] = stack[stacktop-2]&&stack[stacktop-1];
		 	stacktop--; 
		} 
		//OR 将栈顶两单元做逻辑或运算并出战,并将结果真或假(1或0)置于栈顶
		if(strcmp(code[i],"OR")==0){
		 	stack[stacktop-2] = stack[stacktop-2]||stack[stacktop-1];
		 	stacktop--; 
		} 
		//NOT 将栈顶逻辑值取反
		if(strcmp(code[i],"NOT")==0){
		 	stack[stacktop-1]=!stack[stacktop-1];
		} 
		//IN 从标准输入设备读入一个整型数据,并入栈
		if(strcmp(code[i],"IN")==0){
			printf("请输入数据:");
			scanf("%d",&stack[stacktop]);
			stacktop++; 
		} 
		//OUT 将栈顶内容出栈,并输出到标准输出设备上 
		if(strcmp(code[i],"OUT")==0){
		 	printf("程序输出%d\n",stack[stacktop-1]);
			stacktop--; 
		} 
		//STOP 停止执行
		if(strcmp(code[i],"STOP")==0){
			break;
		} 
		i++;
		//显示栈内容
		/*for(k=stacktop-1;k>=0;k--)
		 	printf("%d  ",stack[k]);
		printf("\n");*/
		//printf("	%d		%d\n",data[0],data[1]);
	} 
	return es;
} 
int main(){
	int es=0;
	es = TESTmachine();
}

 


'; ch=getc(fin); } else{ //否则为单分界符 token[1]='
//词法分析
#include<stdio.h>
#include<ctype.h>
#include<string.h>

//保留字数目与保留字数组 
#define keywordSum 10
char *keyword[keywordSum] = {"if","else","for","while","read","write","do","int","call","function"};

//纯单分界符
char singleword[50] = "+-*(){};,:";

//双分界符首字符
char doubleword[10] = "<>=!";

//用于接收输入输出文件名 
extern char Scanin[300],Scanout[300]; 

//用于指向输入输出文件的指针 
extern FILE *fin,*fout; 

//用于对保留字数组进行冒泡排序函数(为折半查找做准备)
void sort(char *KW[]){
	int i,j;
	char *temp;
	for(i=0;i<keywordSum;i++){
		for(j=0;j<keywordSum-1;j++){
			if(strcmp(KW[j],KW[j+1])>0){
				temp = KW[j];
				KW[j] = KW[j+1];
				KW[j+1] = temp;
			}
		}
	}
}

//用于查找保留字表的折半查找函数(保留字不区分大小写)
int Search_Bin(char *KW[],char *keyword){
	sort(KW);
	int low=0,high=keywordSum-1;
	int mid;
	while(low<=high){
		mid = (low+high)/2;
		if(stricmp(keyword,KW[mid])==0) return 1;		//stricmp比较不区分大小写 返回1表示查找到 
		else if(stricmp(keyword,KW[mid])>0) low=mid+1;
		else high=mid-1; 
	}
	return 0;											//返回0表示查找失败 
} 

int TESTscan(){
	char ch,token[40];									//ch用于保存当前读出的字符,token用于保存识别出的单词
	int es=0,j,n;										//es为错误识别代码,0表示没有错误。
	int linenum=1;										//用于保存行号 
	printf("请输入源程序文件名(包括路径):");
	scanf("%s",Scanin);
	printf("请输入词法分析输出文件名(包括路径):");
	scanf("%s",Scanout);
	if((fin = fopen(Scanin,"r"))==NULL){
		printf("\n打开词法分析输入文件出错!\n");
		return 1;										//输入文件出错返回错误代码1 
	}
	if((fout = fopen(Scanout,"w"))==NULL){
		printf("\n打开词法分析1输出文件出错!\n");
		return 2; 										//输出文件出错返回错误代码2 
	}
	ch = getc(fin);
	while(ch!=EOF){
		while(ch==' '||ch=='\n'||ch=='\t'){
			if(ch=='\n')								//记录行号 
				linenum++; 
			ch=getc(fin);
		} 
		if(isalpha(ch)){								//如果ch是字母的话,进行标识符处理 
			token[0]=ch;
			j=1;
			ch=getc(fin);
			while(isalnum(ch)){							//如果ch是字母或者数字的话 
				token[j++]=ch;							//组合的标识符保存在token中 
				ch=getc(fin);							//读下一个字符 
			}
			token[j]='\0';								//标识符组合结束 
			//查保留字 
			n=Search_Bin(keyword,token);
			if(n==1)									//是保留字 
				fprintf(fout,"%s\t%s\n",token,token);
			else
				fprintf(fout,"%s\t%s\n","ID",token);	//不是保留字 
		}
		else if(isdigit(ch)){							//如果ch是数字的话,对数字进行处理 
			token[0]=ch;
			j=1;
			ch=getc(fin);
			while(isdigit(ch)){							//如果是数字则整合整数,否则退出 
				token[j++]=ch;
				ch=getc(fin);
			}
			token[j]='\0';
			fprintf(fout,"%s\t%s\n","NUM",token);
		}
		else if(strchr(singleword,ch)!=NULL){			//strchr用于查找某字符是否存在于某字符数组中,是则返回指针,不是则返回NULL 
			token[0]=ch;
			token[1]='\0';
			ch=getc(fin);								//读下一个符号以便识别单词 
			fprintf(fout,"%s\t%s\n",token,token);
		}
		else if(strchr(doubleword,ch)!=NULL){
			token[0]=ch;
			ch=getc(fin);								//读下一个字符判断是否是双分界符 
			if((token[0]!='&'&&token[0]!='|'&&ch=='=')||(token[0]=='|'&&ch=='|')||(token[0]=='&'&&ch=='&')){				//如果是=,|,&则组合双分界符 
				token[1]=ch;
				token[2]='\0';
				ch=getc(fin);
			}
			else{										//否则为单分界符 
				token[1]='\0';
			}
			if(token[0]=='!'||token[0]=='<'||token[0]=='>'||token[0]=='='){
				fprintf(fout,"%s\t%s\n",token,token);
			}
			else{
				printf("%d行发生错误",linenum);
				fprintf(fout,"\n%s\t%s\n","ERROR",token);
				fprintf(fout,"%s  %d\n\n","错误行号为:",linenum);
			} 
		}
		else if(ch=='/'){								//注释处理 
			ch=getc(fin);
			if(ch=='*'){								//如果下一个字符是*则开始进行注释处理 
				char ch1;
				ch1=getc(fin);
				do{
					if(ch1=='\n'){
						linenum++;
					}
					ch=ch1;
					ch1=getc(fin);
				}while((ch!='*'||ch1!='/')&&ch1!=EOF);	//删除注释 
				ch=getc(fin);
			}
			else{										//不是*则输出单分界符 
				token[0]=ch;
				token[1]='\0';
				fprintf(fout,"%s\t%s\n",token,token);
			}
		} 
		else{
			token[0]=ch;								//处理错误 
			token[1]='\0';
			ch=getc(fin);
			es=3;										//设置错误代码 
			printf("%d行发生错误",linenum);
			fprintf(fout,"\n%s\t%s\n","ERROR",token);
			fprintf(fout,"%s  %d\n\n","错误行号为:",linenum);
		}
	}
	fclose(fin);
	fclose(fout);
	return es;	
}
//语法及语义分析
#include<stdio.h>
#include<ctype.h>
#include<conio.h>
#include<string.h>

#define maxvartablep 500				//定义符号表的容量


struct vartable{
	char name[8];
	int address;
};								//符号表最多容纳maxvartablep个记录 

struct fun_table{
	char name[30];
	int address;
	int can_num;
	int first_address;			//记录第一个参数的地址 
}fun_table[maxvartablep];

int program();
int fun_declaration();
int canshu(struct vartable table[maxvartablep],int &num,int &can_num);
int main_declaration();
int function_body(struct vartable table[maxvartablep],int &num);
int declaration_list(struct vartable table[maxvartablep],int &num);
int declaration_stat(struct vartable table[maxvartablep],int &num);
int statement_list(struct vartable table[maxvartablep],int &num);
int statement(struct vartable table[maxvartablep],int &num);
int if_stat(struct vartable table[maxvartablep],int &num);
int while_stat(struct vartable table[maxvartablep],int &num);
int for_stat(struct vartable table[maxvartablep],int &num);
int write_stat(struct vartable table[maxvartablep],int &num);
int read_stat(struct vartable table[maxvartablep],int &num);
int compound_stat(struct vartable table[maxvartablep],int &num);
int expression_stat(struct vartable table[maxvartablep],int &num);
int call_stat(struct vartable table[maxvartablep],int &num);
int expression(struct vartable table[maxvartablep],int &num);
int bool_expr(struct vartable table[maxvartablep],int &num);
int additive_expr(struct vartable table[maxvartablep],int &num);
int term(struct vartable table[maxvartablep],int &num);
int factor(struct vartable table[maxvartablep],int &num);

int name_def(char *name,int vartablep,int datap);
char token[10],token1[40];
extern char Scanout[300],Codeout[300];
FILE *fp,*fout1;
int labelp = 1,datap=0;					//labelp用于记录当前标记,防止重复
int fun_var=0;
//插入符号表@name_def(↓n,t)的程序如下:
int name_def(char *name,vartable table[],int vartablep){
	int i,es = 0;
	if(vartablep>maxvartablep)
		return 21;
	for(i=vartablep-1;i>=0;i--){
		if(strcmp(table[i].name,name)==0){
			es=22;
			break;
		}
	} 
	if(es>0){
		return es;
	}
	strcpy(table[vartablep].name,name);
	table[vartablep].address = datap;
	datap++;
	return es;
}
int fun_def(char *name,int datap,int can_num,int first){
	int i,es = 0;
	if(fun_var>maxvartablep)
		return 31;
	for(i=fun_var-1;i>=0;i--){
		if(strcmp(fun_table[i].name,name)==0&&fun_table[i].can_num==can_num){
			es=32;
			break;
		}
	}
	strcpy(fun_table[fun_var].name,name);
	fun_table[fun_var].address = datap;
	fun_table[fun_var].can_num=can_num;
	fun_table[fun_var].first_address=first;
	fun_var++;
	return es; 
}
//查询符号表返回地址 
int lookup(struct vartable table[],char *name,int *paddress,int num){
	int i,es = 0;
	for(i=0;i<num;i++){
		if(strcmp(table[i].name,name)==0){
			*paddress = table[i].address;
			return es;
		}
	}
	es = 23;
	return es;
} 
int fun_lookup(char *name,int *paddress,int num){
	int i,es = 0;
	for(i=0;i<fun_var;i++){
		if(strcmp(fun_table[i].name,name)==0&&fun_table[i].can_num==num){
			*paddress = fun_table[i].address;
			return es;
		}
	}
	es = 33;
	return es;
} 
void cha(char *name,int &first){
	int i;
	for(i=0;i<fun_var;i++){
		if(strcmp(fun_table[i].name,name)==0){
			first=fun_table[i].first_address;
		}
	}
}
//语义语法分析及代码生成程序
int TESTparse(){
	int es = 0;
	if((fp=fopen(Scanout,"r"))==NULL){
		printf("打开%s错误!\n",Scanout);
		es = 10;
		return es;
	}
	printf("请输入目标文件名(包括路径):");
	char Codeout[20];
	scanf("%s",Codeout);
	if((fout1=fopen(Codeout,"w"))==NULL){
		printf("\n创建%s错误!\n",Codeout);
		es=10;
		return es;
	}
	if(es==0)
		es = program();
	printf("==语法,语义分析及代码生成程序结果==\n");
	switch(es){
		case 0: printf("语法分析成功!\n"); break;
		case 10: printf("打开文件%s失败!\n"); break;
		case 1: printf("缺少{\n"); break;
		case 2: printf("缺少}\n"); break;
		case 3: printf("缺少标识符\n"); break;
		case 4: printf("缺少分号\n"); break;
		case 5: printf("缺少(\n"); break;
		case 6: printf("缺少)\n"); break;
		case 7: printf("缺少操作数\n"); break;
		case 21:printf("符号表溢出\n");break;
		case 22:printf("变量重复定义\n");break;
		case 23:printf("变量未声明\n");break;
		case 31:printf("函数名符号表溢出\n");break;
		case 32:printf("函数重复定义");break; 
		case 33:printf("函数未定义");break; 
		case 41:printf("参数定义出错");break;
	}
	fclose(fp);
	fclose(fout1);
	return es;
} 

int program(){
	int es = 0;
	fscanf(fp,"%s %s\n",&token,&token1);
	fprintf(fout1,"	BR	LABEL0\n");					//产生停止指令
	while(!strcmp(token,"function")){
		es = fun_declaration();
		if(es>0)
			return es;
		fscanf(fp,"%s %s\n",&token,&token1);
	}	
	if(strcmp(token1,"main")){				 
		es = 8;
		return es;
	}
	else{
		es = main_declaration();
		if(es>0)
			return es;
	}
	fprintf(fout1,"	STOP\n");					//产生停止指令
	return es;
}
int fun_declaration(){
	int es = 0;
	struct vartable table[maxvartablep];
	int num = 0; 
	char fun_name[20];
	int can_num=0;	
	int first=0;	
	fprintf(fout1,"LABEL%d:\n",labelp++);
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"ID")){
		es = 9;
		return es;
	}
	strcpy(fun_name,token1);
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"(")){
		es = 5;
		return es;
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"int")==0){
		first=datap;
		es = canshu(table,num,can_num);
		if(es>0)
			return (es=41);
	}
	fun_def(fun_name,labelp-1,can_num,first);
	if(strcmp(token,")")){
		es = 6;
		return es;
	}	
	es = function_body(table,num);
	fprintf(fout1,"LABEL%d:\n",labelp++);
	fprintf(fout1,"	RET\n");
	return es;
}
int canshu(struct vartable table[maxvartablep],int &num,int &can_num){
	int es=0;
	while(strcmp(token,"int")==0){
		can_num++;
		fscanf(fp,"%s %s\n",&token,&token1);
		if(strcmp(token,"ID"))
			return (es = 3);			//不是标识符
		es = name_def(token1,table,num);
		num++;
		if(es>0)
			return es;
		fscanf(fp,"%s %s\n",&token,&token1);
		if(strcmp(token,")")==0){
			break;
		}
		else{
			fscanf(fp,"%s %s\n",&token,&token1);
		}	
	}
	return es;
}
int main_declaration(){
	int es = 0;
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"(")){
		es = 5;
		return es;
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,")")){
		es = 6;
		return es;
	}
	fprintf(fout1,"LABEL0:\n");
	struct vartable table[maxvartablep];
	int num = 0; 			
	es = function_body(table,num);
	return es;
}
int function_body(struct vartable table[maxvartablep],int &num){
	int es=0,i;
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"{")){
		es = 1;
		return es;
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	es = declaration_list(table,num);
	if(es>0)
		return es;
	printf("	符号表\n");
	printf("	变量名	地址\n");
	for(i=0;i<num;i++){
		printf("	%s	%d\n",table[i].name,table[i].address);
	}
	es = statement_list(table,num);
	if(es>0)
		return es;
	if(strcmp(token,"}")){
		es = 2;
		return es;
	} 
	return es;
}
int declaration_list(struct vartable table[maxvartablep],int &num){
	int es = 0;
	while(strcmp(token,"int")==0){
		es = declaration_stat(table,num);
		num++;
		if(es>0)
			return es;
	}
	return es;
}
int declaration_stat(struct vartable table[maxvartablep],int &num){
	int es=0;
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"ID"))
		return (es = 3);			//不是标识符
	es = name_def(token1,table,num);
	if(es>0)
		return es;
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,";")){
		es = 4;
		return es;
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	return es;
} 
int statement_list(struct vartable table[maxvartablep],int &num){
	int es = 0;
	while(strcmp(token,"}")){
		es = statement(table,num);
		if(es>0)
			return es; 
	}
	if(strcmp(token,"}")&&(feof(fp)||strcmp(token,"function")==0||strcmp(token1,"main")==0)){
			es=2;
			return es;
		}
	return es;	
}
int statement(struct vartable table[maxvartablep],int &num){
	int es = 0;
	if(es==0 && strcmp(token,"if")==0)
		es = if_stat(table,num);
	else if(es==0 && strcmp(token,"while")==0)
		es = while_stat(table,num);
	else if(es==0 && strcmp(token,"for")==0)
		es = for_stat(table,num);
	else if(es==0 && strcmp(token,"read")==0)
		es = read_stat(table,num);
	else if(es==0 && strcmp(token,"write")==0)
		es = write_stat(table,num);
	else if(es==0 && strcmp(token,"{")==0)
		es = compound_stat(table,num);
	else if(es==0 && (strcmp(token,"ID")==0)||strcmp(token,"NUM")==0||strcmp(token,"(")==0)
		es = expression_stat(table,num);
	else if(es==0 && strcmp(token,"call")==0)
		es = call_stat(table,num);
	return es;
}
/*if(<expression>)@BRF(↑label1)<statement>@BR(↑label2)@SETlabel(↓label1)
				  [else<statement>]@SETlabel(↓label2)
其中动作符号定义为
	@BRF(↑label1) 输出BRF label1
	@BR(↑label2) 输出BR label2
	@SETlabel(↓label1) 设置标号label1
	@SETlabel(↓label2) 设置标号label2*/
int if_stat(struct vartable table[maxvartablep],int &num){
	int es = 0,label1,label2;
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"(")){
		es = 5;
		return es;
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	es = expression(table,num);
	if(es>0)
		return es;
	if(strcmp(token,")")){
		es = 6;
		return es;
	}
	label1 = labelp++;						//用label1记住当条件为假时要转向的标号
	fprintf(fout1,"	BRF	LABEL%d\n",label1); //输出假转移指令 
	fscanf(fp,"%s %s\n",&token,&token1);
	es = statement(table,num);
	if(es>0)
		return es;
	label2 = labelp++;						//用label2记住要转向的标号 
	fprintf(fout1,"	BR	LABEL%d\n",label2);//输出无条件转移指令 
	fprintf(fout1,"LABEL%d:\n",label1);		//设置label1记住的符号 
	if(strcmp(token,"else")==0){
	fscanf(fp,"%s %s\n",&token,&token1);
	es = statement(table,num);
	if(es>0)
		return es;	
	}
	fprintf(fout1,"LABEL%d:\n",label2); 		//设置label2记住的标号 
	return es;	
}
/*<while_stat>::[email protected](↑label)(<expression>)@BRF(↑label2)
				<statement>@BR(↓label1)@SETlabel(↓label2)
	动作解释为
	@SETlabel(↑label):设置标号label1 
	@BRF(↑label2):输出BRF label2 
	@BR(↓label1):输出BR label1 
	@SETlabel(↓label2):设置标号 label2*/
int while_stat(struct vartable table[maxvartablep],int &num){
	int es = 0,label1,label2;
	label1 = labelp++;							//设置label1标号 
	fprintf(fout1,"LABEL%d:\n",label1);
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"(")){
		es = 5;
		return es;
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	es = expression(table,num);
	if(es>0)
		return es;
	if(strcmp(token,")")){
		es = 6;
		return es;
	}
	label2 = labelp++;
	fprintf(fout1,"	BRF	LABEL%d",label2);			//输出假转移指令 
	fscanf(fp,"%s %s\n",&token,&token1);
	es = statement(table,num);
	if(es>0){
		return es;
	} 
	fprintf(fout1,"	BR	LABEL%d\n",label1);		//输出无条件转移指令 
	fprintf(fout1,"LABEL%d:\n",label2);				//设置label2标号 
	return es;
}
/*<for_stat>::=for(<expression>@POP;
				@SETlabel(label1)<expression>@BRF(label2)@BR(label3)
				@SETlabel(label4)<expression>@[email protected](label1))
				@SETlabel(label3)<语句>@BR(label4)@SETlabel(label2)*/
int for_stat(struct vartable table[maxvartablep],int &num){
	int es = 0,label1,label2,label3,label4;
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"(")){						//少左括号 
		es = 5;
		return es;
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	es = expression(table,num);
	if(es>0)
		return es;
	fprintf(fout1,"	POP\n");				//设置出栈指令 
	if(strcmp(token,";")){
		es = 4;
		return es;
	}
	label1 = labelp++;
	fprintf(fout1,"LABEL%d:\n",label1);		//设置label1标号 
	fscanf(fp,"%s %s\n",&token,&token1);
	es = expression(table,num);
	if(es>0)
		return es;
	label2 = labelp++;
	fprintf(fout1,"	BRF	LABEL%d\n",label2);
	label3 = labelp++;
	fprintf(fout1,"	BR	LABEL%d\n",label3);
	if(strcmp(token,";")){
		es = 4;
		return es;
	}
	label4 = labelp++;
	fprintf(fout1,"LABEL%d:\n",label4);
	fscanf(fp,"%s %s\n",&token,&token1);
	es = expression(table,num);
	if(es>0)
		return es;
	fprintf(fout1,"	POP\n");	
	fprintf(fout1,"	BR	LABEL%d\n",label1);
	if(strcmp(token,")")){
		es = 6;
		return es;
	}
	fprintf(fout1,"LABEL%d:\n",label3);	
	fscanf(fp,"%s %s\n",&token,&token1);
	es = statement(table,num);
	if(es>0)
		return es;
	fprintf(fout1,"	BR	LABEL%d\n",label4);
	fprintf(fout1,"LABEL%d:\n",label2);	
	return es;	
}
int write_stat(struct vartable table[maxvartablep],int &num){									 
	int es = 0;
	fscanf(fp,"%s %s\n",&token,&token1);
	es = expression(table,num);
	if(es>0)
		return es;
	if(strcmp(token,";")){
		es = 4;
		return es;
	}
	fprintf(fout1,"	OUT\n"); 
	fscanf(fp,"%s %s\n",&token,&token1);
	return es;
}
//<read_stat>→read ID								read <标识符>
int read_stat(struct vartable table[],int &num){
	int es = 0,address;
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"ID")){
		es = 3;
		return es;
	}						//缺少标识符 
	es = lookup(table,token1,&address,num);
	if(es>0)	return es;
	fprintf(fout1,"	IN	\n");
	fprintf(fout1,"	STO	%d\n",address);
	fprintf(fout1,"	POP\n");
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,";")){
		es = 4;
		return es;							//缺少分号 
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	return es;
}
int compound_stat(struct vartable table[maxvartablep],int &num){
	int es = 0;
	fscanf(fp,"%s %s\n",&token,&token1);
	es = statement_list(table,num);
	if(es>0){
		return es;
	}
	if(strcmp(token,"}")){
		es=2;
		return es;
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	return es; 
}
//<expression_stat>→< expression >;|; 
int expression_stat(struct vartable table[maxvartablep],int &num){
	int es = 0;
	if(strcmp(token,";")==0){
		fscanf(fp,"%s %s\n",&token,&token1);
		return es;
	} 
	es = expression(table,num);
	if(es>0)
		return es;
	fprintf(fout1,"	POP\n");
	if(es==0 && strcmp(token,";")==0){ 
		fscanf(fp,"%s %s\n",&token,&token1);
		return es;
	}
	else{											//少分号 
		es = 4;
		return es;
	}
}
//< call _stat>→ call ID‘(’ ‘)’
int call_stat(struct vartable table[maxvartablep],int &num){
	int es = 0;
	int address;
	int address1;
	int canshunum=0;
	char fun_name[20];
	int first=0;
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"ID")){					//缺少函数名 
		es = 9;					
		return es; 
	}
	strcpy(fun_name,token1);	
	cha(fun_name,first);
	if(es>0){
		return es;
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"(")){
		es = 5;
		return es;
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	while(strcmp(token,"ID")==0){
		es=lookup(table,token1,&address1,num);
		if(es>0)	return es;
		fprintf(fout1,"	LOAD	%d\n",address1);
		fprintf(fout1,"	STO	%d\n",first+canshunum);
		fprintf(fout1,"	POP\n");
		canshunum++;
		fscanf(fp,"%s %s\n",&token,&token1);
		if(strcmp(token,")")==0)
			break;
		else{
			fscanf(fp,"%s %s\n",&token,&token1);
		} 
	}
	if(strcmp(token,")")){
		es = 6;
		return es;
	}
	es=fun_lookup(fun_name,&address,canshunum);
	fprintf(fout1,"	JSR LABEL%d\n",address);
	
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,";")){
		es = 4;
		return es;
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	return es;
}
//< expression >→ ID=<bool_expr>|<bool_expr> 
int expression(struct vartable table[maxvartablep],int &num){
	int es = 0;
	int fileadd;										//用于保存文件位置
	char token2[20],token3[40];
	if(strcmp(token,"ID")==0){
		fileadd = ftell(fp);							//记录文件位置
		fscanf(fp,"%s %s\n",&token2,&token3);
		if(strcmp(token2,"=")==0){
			int address;
			es=lookup(table,token1,&address,num);
			if(es>0)	return es;
			fscanf(fp,"%s %s\n",&token,&token1);
			es = bool_expr(table,num);
			if(es>0)
				return es; 
			fprintf(fout1,"	STO	%d\n",address);
		}
		else{											//如果不是等号,则指针返回等号之前的标识符 
			fseek(fp,fileadd,0); 
			es = bool_expr(table,num);
			if(es>0)
				return es;
		}
	}
	else{
		es = bool_expr(table,num);
	}
	return es;
}
//<bool_expr>-><additive_expr> |< additive_expr >(>|<|>=|<=|==|!=)< additive_expr > 
//<bool_expr>→<additive_expr>{(>|<|>=|<=|==|!=)<additive_expr>}
int bool_expr(struct vartable table[maxvartablep],int &num){
	int es = 0;
	es = additive_expr(table,num);
	if(es>0)
		return es;
	if(strcmp(token,">")==0||strcmp(token,">=")==0||strcmp(token,"<")==0||strcmp(token,"<=")==0||strcmp(token,"==")==0||strcmp(token,"!=")==0){
		char token2[20];
		strcpy(token2,token);
		fscanf(fp,"%s %s\n",&token,&token1);
		es = additive_expr(table,num);
		if(es>0)
			return es;
		if(strcmp(token2,">")==0)	fprintf(fout1,"	GT\n");
		if(strcmp(token2,">=")==0)	fprintf(fout1,"	GE\n");
		if(strcmp(token2,"<")==0)	fprintf(fout1,"	LES\n");
		if(strcmp(token2,"<=")==0)	fprintf(fout1,"	LE\n");
		if(strcmp(token2,"==")==0)	fprintf(fout1,"	EQ\n");
		if(strcmp(token2,"!=")==0)	fprintf(fout1,"	NOTEQ\n");
	}
	return es;
}
//< additive_expr>→<term>{(+|-)< term >}				算数表达式定义为项或者项加减项
int additive_expr(struct vartable table[maxvartablep],int &num){
	int es = 0;
	es = term(table,num);
	if(es>0)
		return es;
	while(strcmp(token,"+")==0||strcmp(token,"-")==0){
		char token2[20];
		strcpy(token2,token);
		fscanf(fp,"%s %s\n",&token,&token1);
		es = term(table,num);
		if(es>0)
			return es;
		if(strcmp(token2,"+")==0)	fprintf(fout1,"	ADD\n");
		if(strcmp(token2,"-")==0)	fprintf(fout1,"	SUB\n");
	}
	return es;
}
//< term >→<factor>{(*| /)< factor >}					项定义为因子或因子乘或除因子
int term(struct vartable table[maxvartablep],int &num){
	int es = 0;
	es = factor(table,num);
	if(es>0)
		return es;	
	while(strcmp(token,"*")==0||strcmp(token,"/")==0){
		char token2[20];
		strcpy(token2,token);
		fscanf(fp,"%s %s\n",&token,&token1);
		es = factor(table,num);
		if(es>0)
			return es;
		if(strcmp(token2,"*")==0)	fprintf(fout1,"	MULT\n");
		if(strcmp(token2,"/")==0)	fprintf(fout1,"	DIV\n");
	}
	return es;
}
//< factor >→’(‘< additive_expr >’)’|ID|NUM		因子定义为表达式或者标识符或者数字
int factor(struct vartable table[maxvartablep],int &num){
	int es = 0;
	if(strcmp(token,"(")==0){										//因子定义成表达式,根据左括号进行判断
		fscanf(fp,"%s %s\n",&token,&token1);
		es = expression(table,num);
		if(es>0)
			return es;
		if(strcmp(token,")")){										//当缺少右括号时
			es = 6;
			return es;
		}
		fscanf(fp,"%s %s\n",&token,&token1);
	}
	else{															//因子定义成标识符或数字
		if(strcmp(token,"ID")==0){
			int address;
			int flag=1;
			es=lookup(table,token1,&address,num);
			if(es>0)	return es;
			fprintf(fout1,"	LOAD	%d\n",address);
			fscanf(fp,"%s %s\n",&token,&token1);
			return es;
		}
		else if(strcmp(token,"NUM")==0){
			fprintf(fout1,"	LOADI	%s\n",token1);
			fscanf(fp,"%s %s\n",&token,&token1);
		}
		else{
			es = 7;												//缺少操作数
			return es;
		}
	}
	return es; 
}
//词法语法语义分析主函数
#include<stdio.h>
#include<ctype.h>

extern int TESTscan();
extern int TESTparse();

char Scanin[300],Scanout[300];
FILE *fin,*fout;

int main(){
	int es=0;
	es = TESTscan();
	if(es>0)
		printf("词法分析有错,编译停止!\n");
	else
		printf("词法分析成功!\n");
	if(es==0){
		es = TESTparse();
		if(es==0)
			printf("语法分析成功!\n");
		else
			printf("语法语义分析错误!\n");
	}
	return 0; 
}
//虚拟机生成
#include<stdio.h>
#include<ctype.h>
#include<stdlib.h>
#include<string.h>

int TESTmachine();

int TESTmachine(){
	int es=0,i,k=0,codecount,stack[1000],stacktop=0;
	int funstack[100],funstacktop=0;
	char Codein[300],code[1000][20],data[1000];
	int label[100]={0};
	char lno[4];
	FILE *fin;
	/*printf("请输入目标文件名(包括路径):");
	scanf("%s",Codein);*/
	if((fin=fopen("3.txt","r"))==NULL){					
		printf("\n打开%s是错误!\n",code);
		es=10;
		return es;
	}
	codecount=0;
	i=fscanf(fin,"%s",&code[codecount]);
	while(!feof(fin)){
		printf("----|  %d  %s  \n",codecount,code[codecount]);
		i=strlen(code[codecount])-1;
		if(code[codecount][i]==':'){
			i=i-5;
			strncpy(lno,&code[codecount][5],i);
			lno[i]='\0';
			label[atoi(lno)]=codecount;							//???			用label数组记住每一个标号的地址 
			//printf("label[%d]=  %d  \n",atoi(lno),label[atoi(lno)]);
			code[codecount][0]=':';
			code[codecount][1]='\0';
			strcat(code[codecount],lno);
			k++;
		}
		codecount++;
		i=fscanf(fin,"%s",&code[codecount]);
	}
	fclose(fin);
	for(i=0;i<codecount;i++){
		int l;
		l=strlen(code[i]);
		if((l>1)&&(code[i][1]=='A')){
			strncpy(lno,&code[i][5],l-5);
			lno[l-5]='\0';
			itoa(label[atoi(lno)],code[i],10);
		}
	}		
	i=0;
	while(i<codecount){								//执行每条指令 
		//printf("code %d %s \n",i,code[i]);
		if(strcmp(code[i],"JSR")==0){				//JSR LAB 无条件跳到LAB,并将JAR下一行的行标保存在函数栈中,便于执行完函数后继续执行主函数 
			i++;
			funstack[funstacktop]=i+1;
			funstacktop++;
			i=atoi(code[i]);
		}
		if(strcmp(code[i],"RET")==0){				//RET 表示当前函数执行完毕,返回调用处 
			i=funstack[funstacktop-1];
			funstacktop--;
		} 
		if(strcmp(code[i],"LOAD")==0){				//LOAD D 将D中的内容加载到操作数栈 
			i++;
			stack[stacktop]=data[atoi(code[i])];
			stacktop++;
		} 
		if(strcmp(code[i],"LOADI")==0){				//LOADI a 将常量a压入操作数栈 
			i++;
			stack[stacktop]=atoi(code[i]);
			stacktop++; 
		} 
		//STO D将操作数栈顶单元内容存入D,切栈顶单元内容保持不变 
		if(strcmp(code[i],"STO")==0){
			i++; 
			data[atoi(code[i])]=stack[stacktop-1];
			//printf("sto  stack %d\n",stack[stacktop-1]);
			//printf("sto  data %d\n",data[atoi(code[i])]); 
		} 
		//POP 栈顶内容出栈 
		if(strcmp(code[i],"POP")==0){
			stacktop--; 
		} 
		//ADD 将栈顶单元与次栈顶单元出栈并相加,和置于栈顶
		if(strcmp(code[i],"ADD")==0){
			stack[stacktop-2] = stack[stacktop-1]+stack[stacktop-2];
			//printf("add  %d\n",stack[stacktop-1]);
			stacktop--;
		}
		//SUB 将次栈顶单元减去栈顶单元并出栈,差置于栈顶
		if(strcmp(code[i],"SUB")==0){
		 	stack[stacktop-2] = stack[stacktop-2]-stack[stacktop-1];
		 	stacktop--; 
		} 
		//MULT 将次栈顶单元与栈顶单元相乘并出栈,积置于栈顶
		if(strcmp(code[i],"MULT")==0){
		 	stack[stacktop-2] = stack[stacktop-2]*stack[stacktop-1];
		 	stacktop--; 
		} 
	 	//DIV 将次栈顶单元与栈顶单元相除并出栈,商置于栈顶 
		if(strcmp(code[i],"DIV")==0){
		 	stack[stacktop-2] = stack[stacktop-2]/stack[stacktop-1];
		 	stacktop--; 
		} 
		//BR	lab 无条件转移到lab 
		if(strcmp(code[i],"BR")==0){
		 	i++;
		 	i=atoi(code[i]);
		} 
		//BRF lab 	检查栈顶单元逻辑值并出栈,若为假则转移到lab 
		if(strcmp(code[i],"BRF")==0){
		 	i++;
			if(stack[stacktop-1]==0)
				i=atoi(code[i]);
			i--; 
		} 
		//EQ 将栈顶两单元做等于比较并出栈,并将结果真或假(1或0),置于栈顶 
		if(strcmp(code[i],"EQ")==0){
		 	stack[stacktop-2] = stack[stacktop-2]==stack[stacktop-1];
		 	stacktop--; 
		} 
		//NOTEQ 将栈顶两单元做不等于比较并出栈,并将结果真或假(1或0),置于栈顶 
		if(strcmp(code[i],"NOTEQ")==0){
		 	stack[stacktop-2] = stack[stacktop-2]!=stack[stacktop-1];
		 	stacktop--; 
		} 
		//GT 次栈顶大于栈顶操作数并出栈,则栈顶置1,否则置0 
		if(strcmp(code[i],"GT")==0){
		 	stack[stacktop-2] = stack[stacktop-2]>stack[stacktop-1];
		 	stacktop--; 
		} 
		//LES 次栈顶小于栈顶操作数并出栈,则栈顶置1,否则置0 
		if(strcmp(code[i],"LES")==0){
		 	stack[stacktop-2] = stack[stacktop-2]<stack[stacktop-1];
		 	stacktop--; 
		} 
		//GE 次栈顶大于等于栈顶操作数并出栈,则栈顶置1,否则置0 
		if(strcmp(code[i],"GE")==0){
		 	stack[stacktop-2] = stack[stacktop-2]>=stack[stacktop-1];
		 	stacktop--; 
		} 
		//LE 次栈顶小于等于栈顶操作数并出栈,则栈顶置1,否则置0 
		if(strcmp(code[i],"LE")==0){
		 	stack[stacktop-2] = stack[stacktop-2]<=stack[stacktop-1];
		 	stacktop--; 
		} 
		//AND 将栈顶两单元做逻辑与运算并出战,并将结果真或假(1或0)置于栈顶
		if(strcmp(code[i],"AND")==0){
		 	stack[stacktop-2] = stack[stacktop-2]&&stack[stacktop-1];
		 	stacktop--; 
		} 
		//OR 将栈顶两单元做逻辑或运算并出战,并将结果真或假(1或0)置于栈顶
		if(strcmp(code[i],"OR")==0){
		 	stack[stacktop-2] = stack[stacktop-2]||stack[stacktop-1];
		 	stacktop--; 
		} 
		//NOT 将栈顶逻辑值取反
		if(strcmp(code[i],"NOT")==0){
		 	stack[stacktop-1]=!stack[stacktop-1];
		} 
		//IN 从标准输入设备读入一个整型数据,并入栈
		if(strcmp(code[i],"IN")==0){
			printf("请输入数据:");
			scanf("%d",&stack[stacktop]);
			stacktop++; 
		} 
		//OUT 将栈顶内容出栈,并输出到标准输出设备上 
		if(strcmp(code[i],"OUT")==0){
		 	printf("程序输出%d\n",stack[stacktop-1]);
			stacktop--; 
		} 
		//STOP 停止执行
		if(strcmp(code[i],"STOP")==0){
			break;
		} 
		i++;
		//显示栈内容
		/*for(k=stacktop-1;k>=0;k--)
		 	printf("%d  ",stack[k]);
		printf("\n");*/
		//printf("	%d		%d\n",data[0],data[1]);
	} 
	return es;
} 
int main(){
	int es=0;
	es = TESTmachine();
}

 


'; } if(token[0]=='!'||token[0]=='<'||token[0]=='>'||token[0]=='='){ fprintf(fout,"%s\t%s\n",token,token); } else{ printf("%d行发生错误",linenum); fprintf(fout,"\n%s\t%s\n","ERROR",token); fprintf(fout,"%s %d\n\n","错误行号为:",linenum); } } else if(ch=='/'){ //注释处理 ch=getc(fin); if(ch=='*'){ //如果下一个字符是*则开始进行注释处理 char ch1; ch1=getc(fin); do{ if(ch1=='\n'){ linenum++; } ch=ch1; ch1=getc(fin); }while((ch!='*'||ch1!='/')&&ch1!=EOF); //删除注释 ch=getc(fin); } else{ //不是*则输出单分界符 token[0]=ch; token[1]='
//词法分析
#include<stdio.h>
#include<ctype.h>
#include<string.h>

//保留字数目与保留字数组 
#define keywordSum 10
char *keyword[keywordSum] = {"if","else","for","while","read","write","do","int","call","function"};

//纯单分界符
char singleword[50] = "+-*(){};,:";

//双分界符首字符
char doubleword[10] = "<>=!";

//用于接收输入输出文件名 
extern char Scanin[300],Scanout[300]; 

//用于指向输入输出文件的指针 
extern FILE *fin,*fout; 

//用于对保留字数组进行冒泡排序函数(为折半查找做准备)
void sort(char *KW[]){
	int i,j;
	char *temp;
	for(i=0;i<keywordSum;i++){
		for(j=0;j<keywordSum-1;j++){
			if(strcmp(KW[j],KW[j+1])>0){
				temp = KW[j];
				KW[j] = KW[j+1];
				KW[j+1] = temp;
			}
		}
	}
}

//用于查找保留字表的折半查找函数(保留字不区分大小写)
int Search_Bin(char *KW[],char *keyword){
	sort(KW);
	int low=0,high=keywordSum-1;
	int mid;
	while(low<=high){
		mid = (low+high)/2;
		if(stricmp(keyword,KW[mid])==0) return 1;		//stricmp比较不区分大小写 返回1表示查找到 
		else if(stricmp(keyword,KW[mid])>0) low=mid+1;
		else high=mid-1; 
	}
	return 0;											//返回0表示查找失败 
} 

int TESTscan(){
	char ch,token[40];									//ch用于保存当前读出的字符,token用于保存识别出的单词
	int es=0,j,n;										//es为错误识别代码,0表示没有错误。
	int linenum=1;										//用于保存行号 
	printf("请输入源程序文件名(包括路径):");
	scanf("%s",Scanin);
	printf("请输入词法分析输出文件名(包括路径):");
	scanf("%s",Scanout);
	if((fin = fopen(Scanin,"r"))==NULL){
		printf("\n打开词法分析输入文件出错!\n");
		return 1;										//输入文件出错返回错误代码1 
	}
	if((fout = fopen(Scanout,"w"))==NULL){
		printf("\n打开词法分析1输出文件出错!\n");
		return 2; 										//输出文件出错返回错误代码2 
	}
	ch = getc(fin);
	while(ch!=EOF){
		while(ch==' '||ch=='\n'||ch=='\t'){
			if(ch=='\n')								//记录行号 
				linenum++; 
			ch=getc(fin);
		} 
		if(isalpha(ch)){								//如果ch是字母的话,进行标识符处理 
			token[0]=ch;
			j=1;
			ch=getc(fin);
			while(isalnum(ch)){							//如果ch是字母或者数字的话 
				token[j++]=ch;							//组合的标识符保存在token中 
				ch=getc(fin);							//读下一个字符 
			}
			token[j]='\0';								//标识符组合结束 
			//查保留字 
			n=Search_Bin(keyword,token);
			if(n==1)									//是保留字 
				fprintf(fout,"%s\t%s\n",token,token);
			else
				fprintf(fout,"%s\t%s\n","ID",token);	//不是保留字 
		}
		else if(isdigit(ch)){							//如果ch是数字的话,对数字进行处理 
			token[0]=ch;
			j=1;
			ch=getc(fin);
			while(isdigit(ch)){							//如果是数字则整合整数,否则退出 
				token[j++]=ch;
				ch=getc(fin);
			}
			token[j]='\0';
			fprintf(fout,"%s\t%s\n","NUM",token);
		}
		else if(strchr(singleword,ch)!=NULL){			//strchr用于查找某字符是否存在于某字符数组中,是则返回指针,不是则返回NULL 
			token[0]=ch;
			token[1]='\0';
			ch=getc(fin);								//读下一个符号以便识别单词 
			fprintf(fout,"%s\t%s\n",token,token);
		}
		else if(strchr(doubleword,ch)!=NULL){
			token[0]=ch;
			ch=getc(fin);								//读下一个字符判断是否是双分界符 
			if((token[0]!='&'&&token[0]!='|'&&ch=='=')||(token[0]=='|'&&ch=='|')||(token[0]=='&'&&ch=='&')){				//如果是=,|,&则组合双分界符 
				token[1]=ch;
				token[2]='\0';
				ch=getc(fin);
			}
			else{										//否则为单分界符 
				token[1]='\0';
			}
			if(token[0]=='!'||token[0]=='<'||token[0]=='>'||token[0]=='='){
				fprintf(fout,"%s\t%s\n",token,token);
			}
			else{
				printf("%d行发生错误",linenum);
				fprintf(fout,"\n%s\t%s\n","ERROR",token);
				fprintf(fout,"%s  %d\n\n","错误行号为:",linenum);
			} 
		}
		else if(ch=='/'){								//注释处理 
			ch=getc(fin);
			if(ch=='*'){								//如果下一个字符是*则开始进行注释处理 
				char ch1;
				ch1=getc(fin);
				do{
					if(ch1=='\n'){
						linenum++;
					}
					ch=ch1;
					ch1=getc(fin);
				}while((ch!='*'||ch1!='/')&&ch1!=EOF);	//删除注释 
				ch=getc(fin);
			}
			else{										//不是*则输出单分界符 
				token[0]=ch;
				token[1]='\0';
				fprintf(fout,"%s\t%s\n",token,token);
			}
		} 
		else{
			token[0]=ch;								//处理错误 
			token[1]='\0';
			ch=getc(fin);
			es=3;										//设置错误代码 
			printf("%d行发生错误",linenum);
			fprintf(fout,"\n%s\t%s\n","ERROR",token);
			fprintf(fout,"%s  %d\n\n","错误行号为:",linenum);
		}
	}
	fclose(fin);
	fclose(fout);
	return es;	
}
//语法及语义分析
#include<stdio.h>
#include<ctype.h>
#include<conio.h>
#include<string.h>

#define maxvartablep 500				//定义符号表的容量


struct vartable{
	char name[8];
	int address;
};								//符号表最多容纳maxvartablep个记录 

struct fun_table{
	char name[30];
	int address;
	int can_num;
	int first_address;			//记录第一个参数的地址 
}fun_table[maxvartablep];

int program();
int fun_declaration();
int canshu(struct vartable table[maxvartablep],int &num,int &can_num);
int main_declaration();
int function_body(struct vartable table[maxvartablep],int &num);
int declaration_list(struct vartable table[maxvartablep],int &num);
int declaration_stat(struct vartable table[maxvartablep],int &num);
int statement_list(struct vartable table[maxvartablep],int &num);
int statement(struct vartable table[maxvartablep],int &num);
int if_stat(struct vartable table[maxvartablep],int &num);
int while_stat(struct vartable table[maxvartablep],int &num);
int for_stat(struct vartable table[maxvartablep],int &num);
int write_stat(struct vartable table[maxvartablep],int &num);
int read_stat(struct vartable table[maxvartablep],int &num);
int compound_stat(struct vartable table[maxvartablep],int &num);
int expression_stat(struct vartable table[maxvartablep],int &num);
int call_stat(struct vartable table[maxvartablep],int &num);
int expression(struct vartable table[maxvartablep],int &num);
int bool_expr(struct vartable table[maxvartablep],int &num);
int additive_expr(struct vartable table[maxvartablep],int &num);
int term(struct vartable table[maxvartablep],int &num);
int factor(struct vartable table[maxvartablep],int &num);

int name_def(char *name,int vartablep,int datap);
char token[10],token1[40];
extern char Scanout[300],Codeout[300];
FILE *fp,*fout1;
int labelp = 1,datap=0;					//labelp用于记录当前标记,防止重复
int fun_var=0;
//插入符号表@name_def(↓n,t)的程序如下:
int name_def(char *name,vartable table[],int vartablep){
	int i,es = 0;
	if(vartablep>maxvartablep)
		return 21;
	for(i=vartablep-1;i>=0;i--){
		if(strcmp(table[i].name,name)==0){
			es=22;
			break;
		}
	} 
	if(es>0){
		return es;
	}
	strcpy(table[vartablep].name,name);
	table[vartablep].address = datap;
	datap++;
	return es;
}
int fun_def(char *name,int datap,int can_num,int first){
	int i,es = 0;
	if(fun_var>maxvartablep)
		return 31;
	for(i=fun_var-1;i>=0;i--){
		if(strcmp(fun_table[i].name,name)==0&&fun_table[i].can_num==can_num){
			es=32;
			break;
		}
	}
	strcpy(fun_table[fun_var].name,name);
	fun_table[fun_var].address = datap;
	fun_table[fun_var].can_num=can_num;
	fun_table[fun_var].first_address=first;
	fun_var++;
	return es; 
}
//查询符号表返回地址 
int lookup(struct vartable table[],char *name,int *paddress,int num){
	int i,es = 0;
	for(i=0;i<num;i++){
		if(strcmp(table[i].name,name)==0){
			*paddress = table[i].address;
			return es;
		}
	}
	es = 23;
	return es;
} 
int fun_lookup(char *name,int *paddress,int num){
	int i,es = 0;
	for(i=0;i<fun_var;i++){
		if(strcmp(fun_table[i].name,name)==0&&fun_table[i].can_num==num){
			*paddress = fun_table[i].address;
			return es;
		}
	}
	es = 33;
	return es;
} 
void cha(char *name,int &first){
	int i;
	for(i=0;i<fun_var;i++){
		if(strcmp(fun_table[i].name,name)==0){
			first=fun_table[i].first_address;
		}
	}
}
//语义语法分析及代码生成程序
int TESTparse(){
	int es = 0;
	if((fp=fopen(Scanout,"r"))==NULL){
		printf("打开%s错误!\n",Scanout);
		es = 10;
		return es;
	}
	printf("请输入目标文件名(包括路径):");
	char Codeout[20];
	scanf("%s",Codeout);
	if((fout1=fopen(Codeout,"w"))==NULL){
		printf("\n创建%s错误!\n",Codeout);
		es=10;
		return es;
	}
	if(es==0)
		es = program();
	printf("==语法,语义分析及代码生成程序结果==\n");
	switch(es){
		case 0: printf("语法分析成功!\n"); break;
		case 10: printf("打开文件%s失败!\n"); break;
		case 1: printf("缺少{\n"); break;
		case 2: printf("缺少}\n"); break;
		case 3: printf("缺少标识符\n"); break;
		case 4: printf("缺少分号\n"); break;
		case 5: printf("缺少(\n"); break;
		case 6: printf("缺少)\n"); break;
		case 7: printf("缺少操作数\n"); break;
		case 21:printf("符号表溢出\n");break;
		case 22:printf("变量重复定义\n");break;
		case 23:printf("变量未声明\n");break;
		case 31:printf("函数名符号表溢出\n");break;
		case 32:printf("函数重复定义");break; 
		case 33:printf("函数未定义");break; 
		case 41:printf("参数定义出错");break;
	}
	fclose(fp);
	fclose(fout1);
	return es;
} 

int program(){
	int es = 0;
	fscanf(fp,"%s %s\n",&token,&token1);
	fprintf(fout1,"	BR	LABEL0\n");					//产生停止指令
	while(!strcmp(token,"function")){
		es = fun_declaration();
		if(es>0)
			return es;
		fscanf(fp,"%s %s\n",&token,&token1);
	}	
	if(strcmp(token1,"main")){				 
		es = 8;
		return es;
	}
	else{
		es = main_declaration();
		if(es>0)
			return es;
	}
	fprintf(fout1,"	STOP\n");					//产生停止指令
	return es;
}
int fun_declaration(){
	int es = 0;
	struct vartable table[maxvartablep];
	int num = 0; 
	char fun_name[20];
	int can_num=0;	
	int first=0;	
	fprintf(fout1,"LABEL%d:\n",labelp++);
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"ID")){
		es = 9;
		return es;
	}
	strcpy(fun_name,token1);
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"(")){
		es = 5;
		return es;
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"int")==0){
		first=datap;
		es = canshu(table,num,can_num);
		if(es>0)
			return (es=41);
	}
	fun_def(fun_name,labelp-1,can_num,first);
	if(strcmp(token,")")){
		es = 6;
		return es;
	}	
	es = function_body(table,num);
	fprintf(fout1,"LABEL%d:\n",labelp++);
	fprintf(fout1,"	RET\n");
	return es;
}
int canshu(struct vartable table[maxvartablep],int &num,int &can_num){
	int es=0;
	while(strcmp(token,"int")==0){
		can_num++;
		fscanf(fp,"%s %s\n",&token,&token1);
		if(strcmp(token,"ID"))
			return (es = 3);			//不是标识符
		es = name_def(token1,table,num);
		num++;
		if(es>0)
			return es;
		fscanf(fp,"%s %s\n",&token,&token1);
		if(strcmp(token,")")==0){
			break;
		}
		else{
			fscanf(fp,"%s %s\n",&token,&token1);
		}	
	}
	return es;
}
int main_declaration(){
	int es = 0;
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"(")){
		es = 5;
		return es;
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,")")){
		es = 6;
		return es;
	}
	fprintf(fout1,"LABEL0:\n");
	struct vartable table[maxvartablep];
	int num = 0; 			
	es = function_body(table,num);
	return es;
}
int function_body(struct vartable table[maxvartablep],int &num){
	int es=0,i;
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"{")){
		es = 1;
		return es;
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	es = declaration_list(table,num);
	if(es>0)
		return es;
	printf("	符号表\n");
	printf("	变量名	地址\n");
	for(i=0;i<num;i++){
		printf("	%s	%d\n",table[i].name,table[i].address);
	}
	es = statement_list(table,num);
	if(es>0)
		return es;
	if(strcmp(token,"}")){
		es = 2;
		return es;
	} 
	return es;
}
int declaration_list(struct vartable table[maxvartablep],int &num){
	int es = 0;
	while(strcmp(token,"int")==0){
		es = declaration_stat(table,num);
		num++;
		if(es>0)
			return es;
	}
	return es;
}
int declaration_stat(struct vartable table[maxvartablep],int &num){
	int es=0;
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"ID"))
		return (es = 3);			//不是标识符
	es = name_def(token1,table,num);
	if(es>0)
		return es;
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,";")){
		es = 4;
		return es;
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	return es;
} 
int statement_list(struct vartable table[maxvartablep],int &num){
	int es = 0;
	while(strcmp(token,"}")){
		es = statement(table,num);
		if(es>0)
			return es; 
	}
	if(strcmp(token,"}")&&(feof(fp)||strcmp(token,"function")==0||strcmp(token1,"main")==0)){
			es=2;
			return es;
		}
	return es;	
}
int statement(struct vartable table[maxvartablep],int &num){
	int es = 0;
	if(es==0 && strcmp(token,"if")==0)
		es = if_stat(table,num);
	else if(es==0 && strcmp(token,"while")==0)
		es = while_stat(table,num);
	else if(es==0 && strcmp(token,"for")==0)
		es = for_stat(table,num);
	else if(es==0 && strcmp(token,"read")==0)
		es = read_stat(table,num);
	else if(es==0 && strcmp(token,"write")==0)
		es = write_stat(table,num);
	else if(es==0 && strcmp(token,"{")==0)
		es = compound_stat(table,num);
	else if(es==0 && (strcmp(token,"ID")==0)||strcmp(token,"NUM")==0||strcmp(token,"(")==0)
		es = expression_stat(table,num);
	else if(es==0 && strcmp(token,"call")==0)
		es = call_stat(table,num);
	return es;
}
/*if(<expression>)@BRF(↑label1)<statement>@BR(↑label2)@SETlabel(↓label1)
				  [else<statement>]@SETlabel(↓label2)
其中动作符号定义为
	@BRF(↑label1) 输出BRF label1
	@BR(↑label2) 输出BR label2
	@SETlabel(↓label1) 设置标号label1
	@SETlabel(↓label2) 设置标号label2*/
int if_stat(struct vartable table[maxvartablep],int &num){
	int es = 0,label1,label2;
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"(")){
		es = 5;
		return es;
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	es = expression(table,num);
	if(es>0)
		return es;
	if(strcmp(token,")")){
		es = 6;
		return es;
	}
	label1 = labelp++;						//用label1记住当条件为假时要转向的标号
	fprintf(fout1,"	BRF	LABEL%d\n",label1); //输出假转移指令 
	fscanf(fp,"%s %s\n",&token,&token1);
	es = statement(table,num);
	if(es>0)
		return es;
	label2 = labelp++;						//用label2记住要转向的标号 
	fprintf(fout1,"	BR	LABEL%d\n",label2);//输出无条件转移指令 
	fprintf(fout1,"LABEL%d:\n",label1);		//设置label1记住的符号 
	if(strcmp(token,"else")==0){
	fscanf(fp,"%s %s\n",&token,&token1);
	es = statement(table,num);
	if(es>0)
		return es;	
	}
	fprintf(fout1,"LABEL%d:\n",label2); 		//设置label2记住的标号 
	return es;	
}
/*<while_stat>::[email protected](↑label)(<expression>)@BRF(↑label2)
				<statement>@BR(↓label1)@SETlabel(↓label2)
	动作解释为
	@SETlabel(↑label):设置标号label1 
	@BRF(↑label2):输出BRF label2 
	@BR(↓label1):输出BR label1 
	@SETlabel(↓label2):设置标号 label2*/
int while_stat(struct vartable table[maxvartablep],int &num){
	int es = 0,label1,label2;
	label1 = labelp++;							//设置label1标号 
	fprintf(fout1,"LABEL%d:\n",label1);
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"(")){
		es = 5;
		return es;
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	es = expression(table,num);
	if(es>0)
		return es;
	if(strcmp(token,")")){
		es = 6;
		return es;
	}
	label2 = labelp++;
	fprintf(fout1,"	BRF	LABEL%d",label2);			//输出假转移指令 
	fscanf(fp,"%s %s\n",&token,&token1);
	es = statement(table,num);
	if(es>0){
		return es;
	} 
	fprintf(fout1,"	BR	LABEL%d\n",label1);		//输出无条件转移指令 
	fprintf(fout1,"LABEL%d:\n",label2);				//设置label2标号 
	return es;
}
/*<for_stat>::=for(<expression>@POP;
				@SETlabel(label1)<expression>@BRF(label2)@BR(label3)
				@SETlabel(label4)<expression>@[email protected](label1))
				@SETlabel(label3)<语句>@BR(label4)@SETlabel(label2)*/
int for_stat(struct vartable table[maxvartablep],int &num){
	int es = 0,label1,label2,label3,label4;
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"(")){						//少左括号 
		es = 5;
		return es;
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	es = expression(table,num);
	if(es>0)
		return es;
	fprintf(fout1,"	POP\n");				//设置出栈指令 
	if(strcmp(token,";")){
		es = 4;
		return es;
	}
	label1 = labelp++;
	fprintf(fout1,"LABEL%d:\n",label1);		//设置label1标号 
	fscanf(fp,"%s %s\n",&token,&token1);
	es = expression(table,num);
	if(es>0)
		return es;
	label2 = labelp++;
	fprintf(fout1,"	BRF	LABEL%d\n",label2);
	label3 = labelp++;
	fprintf(fout1,"	BR	LABEL%d\n",label3);
	if(strcmp(token,";")){
		es = 4;
		return es;
	}
	label4 = labelp++;
	fprintf(fout1,"LABEL%d:\n",label4);
	fscanf(fp,"%s %s\n",&token,&token1);
	es = expression(table,num);
	if(es>0)
		return es;
	fprintf(fout1,"	POP\n");	
	fprintf(fout1,"	BR	LABEL%d\n",label1);
	if(strcmp(token,")")){
		es = 6;
		return es;
	}
	fprintf(fout1,"LABEL%d:\n",label3);	
	fscanf(fp,"%s %s\n",&token,&token1);
	es = statement(table,num);
	if(es>0)
		return es;
	fprintf(fout1,"	BR	LABEL%d\n",label4);
	fprintf(fout1,"LABEL%d:\n",label2);	
	return es;	
}
int write_stat(struct vartable table[maxvartablep],int &num){									 
	int es = 0;
	fscanf(fp,"%s %s\n",&token,&token1);
	es = expression(table,num);
	if(es>0)
		return es;
	if(strcmp(token,";")){
		es = 4;
		return es;
	}
	fprintf(fout1,"	OUT\n"); 
	fscanf(fp,"%s %s\n",&token,&token1);
	return es;
}
//<read_stat>→read ID								read <标识符>
int read_stat(struct vartable table[],int &num){
	int es = 0,address;
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"ID")){
		es = 3;
		return es;
	}						//缺少标识符 
	es = lookup(table,token1,&address,num);
	if(es>0)	return es;
	fprintf(fout1,"	IN	\n");
	fprintf(fout1,"	STO	%d\n",address);
	fprintf(fout1,"	POP\n");
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,";")){
		es = 4;
		return es;							//缺少分号 
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	return es;
}
int compound_stat(struct vartable table[maxvartablep],int &num){
	int es = 0;
	fscanf(fp,"%s %s\n",&token,&token1);
	es = statement_list(table,num);
	if(es>0){
		return es;
	}
	if(strcmp(token,"}")){
		es=2;
		return es;
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	return es; 
}
//<expression_stat>→< expression >;|; 
int expression_stat(struct vartable table[maxvartablep],int &num){
	int es = 0;
	if(strcmp(token,";")==0){
		fscanf(fp,"%s %s\n",&token,&token1);
		return es;
	} 
	es = expression(table,num);
	if(es>0)
		return es;
	fprintf(fout1,"	POP\n");
	if(es==0 && strcmp(token,";")==0){ 
		fscanf(fp,"%s %s\n",&token,&token1);
		return es;
	}
	else{											//少分号 
		es = 4;
		return es;
	}
}
//< call _stat>→ call ID‘(’ ‘)’
int call_stat(struct vartable table[maxvartablep],int &num){
	int es = 0;
	int address;
	int address1;
	int canshunum=0;
	char fun_name[20];
	int first=0;
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"ID")){					//缺少函数名 
		es = 9;					
		return es; 
	}
	strcpy(fun_name,token1);	
	cha(fun_name,first);
	if(es>0){
		return es;
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"(")){
		es = 5;
		return es;
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	while(strcmp(token,"ID")==0){
		es=lookup(table,token1,&address1,num);
		if(es>0)	return es;
		fprintf(fout1,"	LOAD	%d\n",address1);
		fprintf(fout1,"	STO	%d\n",first+canshunum);
		fprintf(fout1,"	POP\n");
		canshunum++;
		fscanf(fp,"%s %s\n",&token,&token1);
		if(strcmp(token,")")==0)
			break;
		else{
			fscanf(fp,"%s %s\n",&token,&token1);
		} 
	}
	if(strcmp(token,")")){
		es = 6;
		return es;
	}
	es=fun_lookup(fun_name,&address,canshunum);
	fprintf(fout1,"	JSR LABEL%d\n",address);
	
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,";")){
		es = 4;
		return es;
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	return es;
}
//< expression >→ ID=<bool_expr>|<bool_expr> 
int expression(struct vartable table[maxvartablep],int &num){
	int es = 0;
	int fileadd;										//用于保存文件位置
	char token2[20],token3[40];
	if(strcmp(token,"ID")==0){
		fileadd = ftell(fp);							//记录文件位置
		fscanf(fp,"%s %s\n",&token2,&token3);
		if(strcmp(token2,"=")==0){
			int address;
			es=lookup(table,token1,&address,num);
			if(es>0)	return es;
			fscanf(fp,"%s %s\n",&token,&token1);
			es = bool_expr(table,num);
			if(es>0)
				return es; 
			fprintf(fout1,"	STO	%d\n",address);
		}
		else{											//如果不是等号,则指针返回等号之前的标识符 
			fseek(fp,fileadd,0); 
			es = bool_expr(table,num);
			if(es>0)
				return es;
		}
	}
	else{
		es = bool_expr(table,num);
	}
	return es;
}
//<bool_expr>-><additive_expr> |< additive_expr >(>|<|>=|<=|==|!=)< additive_expr > 
//<bool_expr>→<additive_expr>{(>|<|>=|<=|==|!=)<additive_expr>}
int bool_expr(struct vartable table[maxvartablep],int &num){
	int es = 0;
	es = additive_expr(table,num);
	if(es>0)
		return es;
	if(strcmp(token,">")==0||strcmp(token,">=")==0||strcmp(token,"<")==0||strcmp(token,"<=")==0||strcmp(token,"==")==0||strcmp(token,"!=")==0){
		char token2[20];
		strcpy(token2,token);
		fscanf(fp,"%s %s\n",&token,&token1);
		es = additive_expr(table,num);
		if(es>0)
			return es;
		if(strcmp(token2,">")==0)	fprintf(fout1,"	GT\n");
		if(strcmp(token2,">=")==0)	fprintf(fout1,"	GE\n");
		if(strcmp(token2,"<")==0)	fprintf(fout1,"	LES\n");
		if(strcmp(token2,"<=")==0)	fprintf(fout1,"	LE\n");
		if(strcmp(token2,"==")==0)	fprintf(fout1,"	EQ\n");
		if(strcmp(token2,"!=")==0)	fprintf(fout1,"	NOTEQ\n");
	}
	return es;
}
//< additive_expr>→<term>{(+|-)< term >}				算数表达式定义为项或者项加减项
int additive_expr(struct vartable table[maxvartablep],int &num){
	int es = 0;
	es = term(table,num);
	if(es>0)
		return es;
	while(strcmp(token,"+")==0||strcmp(token,"-")==0){
		char token2[20];
		strcpy(token2,token);
		fscanf(fp,"%s %s\n",&token,&token1);
		es = term(table,num);
		if(es>0)
			return es;
		if(strcmp(token2,"+")==0)	fprintf(fout1,"	ADD\n");
		if(strcmp(token2,"-")==0)	fprintf(fout1,"	SUB\n");
	}
	return es;
}
//< term >→<factor>{(*| /)< factor >}					项定义为因子或因子乘或除因子
int term(struct vartable table[maxvartablep],int &num){
	int es = 0;
	es = factor(table,num);
	if(es>0)
		return es;	
	while(strcmp(token,"*")==0||strcmp(token,"/")==0){
		char token2[20];
		strcpy(token2,token);
		fscanf(fp,"%s %s\n",&token,&token1);
		es = factor(table,num);
		if(es>0)
			return es;
		if(strcmp(token2,"*")==0)	fprintf(fout1,"	MULT\n");
		if(strcmp(token2,"/")==0)	fprintf(fout1,"	DIV\n");
	}
	return es;
}
//< factor >→’(‘< additive_expr >’)’|ID|NUM		因子定义为表达式或者标识符或者数字
int factor(struct vartable table[maxvartablep],int &num){
	int es = 0;
	if(strcmp(token,"(")==0){										//因子定义成表达式,根据左括号进行判断
		fscanf(fp,"%s %s\n",&token,&token1);
		es = expression(table,num);
		if(es>0)
			return es;
		if(strcmp(token,")")){										//当缺少右括号时
			es = 6;
			return es;
		}
		fscanf(fp,"%s %s\n",&token,&token1);
	}
	else{															//因子定义成标识符或数字
		if(strcmp(token,"ID")==0){
			int address;
			int flag=1;
			es=lookup(table,token1,&address,num);
			if(es>0)	return es;
			fprintf(fout1,"	LOAD	%d\n",address);
			fscanf(fp,"%s %s\n",&token,&token1);
			return es;
		}
		else if(strcmp(token,"NUM")==0){
			fprintf(fout1,"	LOADI	%s\n",token1);
			fscanf(fp,"%s %s\n",&token,&token1);
		}
		else{
			es = 7;												//缺少操作数
			return es;
		}
	}
	return es; 
}
//词法语法语义分析主函数
#include<stdio.h>
#include<ctype.h>

extern int TESTscan();
extern int TESTparse();

char Scanin[300],Scanout[300];
FILE *fin,*fout;

int main(){
	int es=0;
	es = TESTscan();
	if(es>0)
		printf("词法分析有错,编译停止!\n");
	else
		printf("词法分析成功!\n");
	if(es==0){
		es = TESTparse();
		if(es==0)
			printf("语法分析成功!\n");
		else
			printf("语法语义分析错误!\n");
	}
	return 0; 
}
//虚拟机生成
#include<stdio.h>
#include<ctype.h>
#include<stdlib.h>
#include<string.h>

int TESTmachine();

int TESTmachine(){
	int es=0,i,k=0,codecount,stack[1000],stacktop=0;
	int funstack[100],funstacktop=0;
	char Codein[300],code[1000][20],data[1000];
	int label[100]={0};
	char lno[4];
	FILE *fin;
	/*printf("请输入目标文件名(包括路径):");
	scanf("%s",Codein);*/
	if((fin=fopen("3.txt","r"))==NULL){					
		printf("\n打开%s是错误!\n",code);
		es=10;
		return es;
	}
	codecount=0;
	i=fscanf(fin,"%s",&code[codecount]);
	while(!feof(fin)){
		printf("----|  %d  %s  \n",codecount,code[codecount]);
		i=strlen(code[codecount])-1;
		if(code[codecount][i]==':'){
			i=i-5;
			strncpy(lno,&code[codecount][5],i);
			lno[i]='\0';
			label[atoi(lno)]=codecount;							//???			用label数组记住每一个标号的地址 
			//printf("label[%d]=  %d  \n",atoi(lno),label[atoi(lno)]);
			code[codecount][0]=':';
			code[codecount][1]='\0';
			strcat(code[codecount],lno);
			k++;
		}
		codecount++;
		i=fscanf(fin,"%s",&code[codecount]);
	}
	fclose(fin);
	for(i=0;i<codecount;i++){
		int l;
		l=strlen(code[i]);
		if((l>1)&&(code[i][1]=='A')){
			strncpy(lno,&code[i][5],l-5);
			lno[l-5]='\0';
			itoa(label[atoi(lno)],code[i],10);
		}
	}		
	i=0;
	while(i<codecount){								//执行每条指令 
		//printf("code %d %s \n",i,code[i]);
		if(strcmp(code[i],"JSR")==0){				//JSR LAB 无条件跳到LAB,并将JAR下一行的行标保存在函数栈中,便于执行完函数后继续执行主函数 
			i++;
			funstack[funstacktop]=i+1;
			funstacktop++;
			i=atoi(code[i]);
		}
		if(strcmp(code[i],"RET")==0){				//RET 表示当前函数执行完毕,返回调用处 
			i=funstack[funstacktop-1];
			funstacktop--;
		} 
		if(strcmp(code[i],"LOAD")==0){				//LOAD D 将D中的内容加载到操作数栈 
			i++;
			stack[stacktop]=data[atoi(code[i])];
			stacktop++;
		} 
		if(strcmp(code[i],"LOADI")==0){				//LOADI a 将常量a压入操作数栈 
			i++;
			stack[stacktop]=atoi(code[i]);
			stacktop++; 
		} 
		//STO D将操作数栈顶单元内容存入D,切栈顶单元内容保持不变 
		if(strcmp(code[i],"STO")==0){
			i++; 
			data[atoi(code[i])]=stack[stacktop-1];
			//printf("sto  stack %d\n",stack[stacktop-1]);
			//printf("sto  data %d\n",data[atoi(code[i])]); 
		} 
		//POP 栈顶内容出栈 
		if(strcmp(code[i],"POP")==0){
			stacktop--; 
		} 
		//ADD 将栈顶单元与次栈顶单元出栈并相加,和置于栈顶
		if(strcmp(code[i],"ADD")==0){
			stack[stacktop-2] = stack[stacktop-1]+stack[stacktop-2];
			//printf("add  %d\n",stack[stacktop-1]);
			stacktop--;
		}
		//SUB 将次栈顶单元减去栈顶单元并出栈,差置于栈顶
		if(strcmp(code[i],"SUB")==0){
		 	stack[stacktop-2] = stack[stacktop-2]-stack[stacktop-1];
		 	stacktop--; 
		} 
		//MULT 将次栈顶单元与栈顶单元相乘并出栈,积置于栈顶
		if(strcmp(code[i],"MULT")==0){
		 	stack[stacktop-2] = stack[stacktop-2]*stack[stacktop-1];
		 	stacktop--; 
		} 
	 	//DIV 将次栈顶单元与栈顶单元相除并出栈,商置于栈顶 
		if(strcmp(code[i],"DIV")==0){
		 	stack[stacktop-2] = stack[stacktop-2]/stack[stacktop-1];
		 	stacktop--; 
		} 
		//BR	lab 无条件转移到lab 
		if(strcmp(code[i],"BR")==0){
		 	i++;
		 	i=atoi(code[i]);
		} 
		//BRF lab 	检查栈顶单元逻辑值并出栈,若为假则转移到lab 
		if(strcmp(code[i],"BRF")==0){
		 	i++;
			if(stack[stacktop-1]==0)
				i=atoi(code[i]);
			i--; 
		} 
		//EQ 将栈顶两单元做等于比较并出栈,并将结果真或假(1或0),置于栈顶 
		if(strcmp(code[i],"EQ")==0){
		 	stack[stacktop-2] = stack[stacktop-2]==stack[stacktop-1];
		 	stacktop--; 
		} 
		//NOTEQ 将栈顶两单元做不等于比较并出栈,并将结果真或假(1或0),置于栈顶 
		if(strcmp(code[i],"NOTEQ")==0){
		 	stack[stacktop-2] = stack[stacktop-2]!=stack[stacktop-1];
		 	stacktop--; 
		} 
		//GT 次栈顶大于栈顶操作数并出栈,则栈顶置1,否则置0 
		if(strcmp(code[i],"GT")==0){
		 	stack[stacktop-2] = stack[stacktop-2]>stack[stacktop-1];
		 	stacktop--; 
		} 
		//LES 次栈顶小于栈顶操作数并出栈,则栈顶置1,否则置0 
		if(strcmp(code[i],"LES")==0){
		 	stack[stacktop-2] = stack[stacktop-2]<stack[stacktop-1];
		 	stacktop--; 
		} 
		//GE 次栈顶大于等于栈顶操作数并出栈,则栈顶置1,否则置0 
		if(strcmp(code[i],"GE")==0){
		 	stack[stacktop-2] = stack[stacktop-2]>=stack[stacktop-1];
		 	stacktop--; 
		} 
		//LE 次栈顶小于等于栈顶操作数并出栈,则栈顶置1,否则置0 
		if(strcmp(code[i],"LE")==0){
		 	stack[stacktop-2] = stack[stacktop-2]<=stack[stacktop-1];
		 	stacktop--; 
		} 
		//AND 将栈顶两单元做逻辑与运算并出战,并将结果真或假(1或0)置于栈顶
		if(strcmp(code[i],"AND")==0){
		 	stack[stacktop-2] = stack[stacktop-2]&&stack[stacktop-1];
		 	stacktop--; 
		} 
		//OR 将栈顶两单元做逻辑或运算并出战,并将结果真或假(1或0)置于栈顶
		if(strcmp(code[i],"OR")==0){
		 	stack[stacktop-2] = stack[stacktop-2]||stack[stacktop-1];
		 	stacktop--; 
		} 
		//NOT 将栈顶逻辑值取反
		if(strcmp(code[i],"NOT")==0){
		 	stack[stacktop-1]=!stack[stacktop-1];
		} 
		//IN 从标准输入设备读入一个整型数据,并入栈
		if(strcmp(code[i],"IN")==0){
			printf("请输入数据:");
			scanf("%d",&stack[stacktop]);
			stacktop++; 
		} 
		//OUT 将栈顶内容出栈,并输出到标准输出设备上 
		if(strcmp(code[i],"OUT")==0){
		 	printf("程序输出%d\n",stack[stacktop-1]);
			stacktop--; 
		} 
		//STOP 停止执行
		if(strcmp(code[i],"STOP")==0){
			break;
		} 
		i++;
		//显示栈内容
		/*for(k=stacktop-1;k>=0;k--)
		 	printf("%d  ",stack[k]);
		printf("\n");*/
		//printf("	%d		%d\n",data[0],data[1]);
	} 
	return es;
} 
int main(){
	int es=0;
	es = TESTmachine();
}

 


'; fprintf(fout,"%s\t%s\n",token,token); } } else{ token[0]=ch; //处理错误 token[1]='
//词法分析
#include<stdio.h>
#include<ctype.h>
#include<string.h>

//保留字数目与保留字数组 
#define keywordSum 10
char *keyword[keywordSum] = {"if","else","for","while","read","write","do","int","call","function"};

//纯单分界符
char singleword[50] = "+-*(){};,:";

//双分界符首字符
char doubleword[10] = "<>=!";

//用于接收输入输出文件名 
extern char Scanin[300],Scanout[300]; 

//用于指向输入输出文件的指针 
extern FILE *fin,*fout; 

//用于对保留字数组进行冒泡排序函数(为折半查找做准备)
void sort(char *KW[]){
	int i,j;
	char *temp;
	for(i=0;i<keywordSum;i++){
		for(j=0;j<keywordSum-1;j++){
			if(strcmp(KW[j],KW[j+1])>0){
				temp = KW[j];
				KW[j] = KW[j+1];
				KW[j+1] = temp;
			}
		}
	}
}

//用于查找保留字表的折半查找函数(保留字不区分大小写)
int Search_Bin(char *KW[],char *keyword){
	sort(KW);
	int low=0,high=keywordSum-1;
	int mid;
	while(low<=high){
		mid = (low+high)/2;
		if(stricmp(keyword,KW[mid])==0) return 1;		//stricmp比较不区分大小写 返回1表示查找到 
		else if(stricmp(keyword,KW[mid])>0) low=mid+1;
		else high=mid-1; 
	}
	return 0;											//返回0表示查找失败 
} 

int TESTscan(){
	char ch,token[40];									//ch用于保存当前读出的字符,token用于保存识别出的单词
	int es=0,j,n;										//es为错误识别代码,0表示没有错误。
	int linenum=1;										//用于保存行号 
	printf("请输入源程序文件名(包括路径):");
	scanf("%s",Scanin);
	printf("请输入词法分析输出文件名(包括路径):");
	scanf("%s",Scanout);
	if((fin = fopen(Scanin,"r"))==NULL){
		printf("\n打开词法分析输入文件出错!\n");
		return 1;										//输入文件出错返回错误代码1 
	}
	if((fout = fopen(Scanout,"w"))==NULL){
		printf("\n打开词法分析1输出文件出错!\n");
		return 2; 										//输出文件出错返回错误代码2 
	}
	ch = getc(fin);
	while(ch!=EOF){
		while(ch==' '||ch=='\n'||ch=='\t'){
			if(ch=='\n')								//记录行号 
				linenum++; 
			ch=getc(fin);
		} 
		if(isalpha(ch)){								//如果ch是字母的话,进行标识符处理 
			token[0]=ch;
			j=1;
			ch=getc(fin);
			while(isalnum(ch)){							//如果ch是字母或者数字的话 
				token[j++]=ch;							//组合的标识符保存在token中 
				ch=getc(fin);							//读下一个字符 
			}
			token[j]='\0';								//标识符组合结束 
			//查保留字 
			n=Search_Bin(keyword,token);
			if(n==1)									//是保留字 
				fprintf(fout,"%s\t%s\n",token,token);
			else
				fprintf(fout,"%s\t%s\n","ID",token);	//不是保留字 
		}
		else if(isdigit(ch)){							//如果ch是数字的话,对数字进行处理 
			token[0]=ch;
			j=1;
			ch=getc(fin);
			while(isdigit(ch)){							//如果是数字则整合整数,否则退出 
				token[j++]=ch;
				ch=getc(fin);
			}
			token[j]='\0';
			fprintf(fout,"%s\t%s\n","NUM",token);
		}
		else if(strchr(singleword,ch)!=NULL){			//strchr用于查找某字符是否存在于某字符数组中,是则返回指针,不是则返回NULL 
			token[0]=ch;
			token[1]='\0';
			ch=getc(fin);								//读下一个符号以便识别单词 
			fprintf(fout,"%s\t%s\n",token,token);
		}
		else if(strchr(doubleword,ch)!=NULL){
			token[0]=ch;
			ch=getc(fin);								//读下一个字符判断是否是双分界符 
			if((token[0]!='&'&&token[0]!='|'&&ch=='=')||(token[0]=='|'&&ch=='|')||(token[0]=='&'&&ch=='&')){				//如果是=,|,&则组合双分界符 
				token[1]=ch;
				token[2]='\0';
				ch=getc(fin);
			}
			else{										//否则为单分界符 
				token[1]='\0';
			}
			if(token[0]=='!'||token[0]=='<'||token[0]=='>'||token[0]=='='){
				fprintf(fout,"%s\t%s\n",token,token);
			}
			else{
				printf("%d行发生错误",linenum);
				fprintf(fout,"\n%s\t%s\n","ERROR",token);
				fprintf(fout,"%s  %d\n\n","错误行号为:",linenum);
			} 
		}
		else if(ch=='/'){								//注释处理 
			ch=getc(fin);
			if(ch=='*'){								//如果下一个字符是*则开始进行注释处理 
				char ch1;
				ch1=getc(fin);
				do{
					if(ch1=='\n'){
						linenum++;
					}
					ch=ch1;
					ch1=getc(fin);
				}while((ch!='*'||ch1!='/')&&ch1!=EOF);	//删除注释 
				ch=getc(fin);
			}
			else{										//不是*则输出单分界符 
				token[0]=ch;
				token[1]='\0';
				fprintf(fout,"%s\t%s\n",token,token);
			}
		} 
		else{
			token[0]=ch;								//处理错误 
			token[1]='\0';
			ch=getc(fin);
			es=3;										//设置错误代码 
			printf("%d行发生错误",linenum);
			fprintf(fout,"\n%s\t%s\n","ERROR",token);
			fprintf(fout,"%s  %d\n\n","错误行号为:",linenum);
		}
	}
	fclose(fin);
	fclose(fout);
	return es;	
}
//语法及语义分析
#include<stdio.h>
#include<ctype.h>
#include<conio.h>
#include<string.h>

#define maxvartablep 500				//定义符号表的容量


struct vartable{
	char name[8];
	int address;
};								//符号表最多容纳maxvartablep个记录 

struct fun_table{
	char name[30];
	int address;
	int can_num;
	int first_address;			//记录第一个参数的地址 
}fun_table[maxvartablep];

int program();
int fun_declaration();
int canshu(struct vartable table[maxvartablep],int &num,int &can_num);
int main_declaration();
int function_body(struct vartable table[maxvartablep],int &num);
int declaration_list(struct vartable table[maxvartablep],int &num);
int declaration_stat(struct vartable table[maxvartablep],int &num);
int statement_list(struct vartable table[maxvartablep],int &num);
int statement(struct vartable table[maxvartablep],int &num);
int if_stat(struct vartable table[maxvartablep],int &num);
int while_stat(struct vartable table[maxvartablep],int &num);
int for_stat(struct vartable table[maxvartablep],int &num);
int write_stat(struct vartable table[maxvartablep],int &num);
int read_stat(struct vartable table[maxvartablep],int &num);
int compound_stat(struct vartable table[maxvartablep],int &num);
int expression_stat(struct vartable table[maxvartablep],int &num);
int call_stat(struct vartable table[maxvartablep],int &num);
int expression(struct vartable table[maxvartablep],int &num);
int bool_expr(struct vartable table[maxvartablep],int &num);
int additive_expr(struct vartable table[maxvartablep],int &num);
int term(struct vartable table[maxvartablep],int &num);
int factor(struct vartable table[maxvartablep],int &num);

int name_def(char *name,int vartablep,int datap);
char token[10],token1[40];
extern char Scanout[300],Codeout[300];
FILE *fp,*fout1;
int labelp = 1,datap=0;					//labelp用于记录当前标记,防止重复
int fun_var=0;
//插入符号表@name_def(↓n,t)的程序如下:
int name_def(char *name,vartable table[],int vartablep){
	int i,es = 0;
	if(vartablep>maxvartablep)
		return 21;
	for(i=vartablep-1;i>=0;i--){
		if(strcmp(table[i].name,name)==0){
			es=22;
			break;
		}
	} 
	if(es>0){
		return es;
	}
	strcpy(table[vartablep].name,name);
	table[vartablep].address = datap;
	datap++;
	return es;
}
int fun_def(char *name,int datap,int can_num,int first){
	int i,es = 0;
	if(fun_var>maxvartablep)
		return 31;
	for(i=fun_var-1;i>=0;i--){
		if(strcmp(fun_table[i].name,name)==0&&fun_table[i].can_num==can_num){
			es=32;
			break;
		}
	}
	strcpy(fun_table[fun_var].name,name);
	fun_table[fun_var].address = datap;
	fun_table[fun_var].can_num=can_num;
	fun_table[fun_var].first_address=first;
	fun_var++;
	return es; 
}
//查询符号表返回地址 
int lookup(struct vartable table[],char *name,int *paddress,int num){
	int i,es = 0;
	for(i=0;i<num;i++){
		if(strcmp(table[i].name,name)==0){
			*paddress = table[i].address;
			return es;
		}
	}
	es = 23;
	return es;
} 
int fun_lookup(char *name,int *paddress,int num){
	int i,es = 0;
	for(i=0;i<fun_var;i++){
		if(strcmp(fun_table[i].name,name)==0&&fun_table[i].can_num==num){
			*paddress = fun_table[i].address;
			return es;
		}
	}
	es = 33;
	return es;
} 
void cha(char *name,int &first){
	int i;
	for(i=0;i<fun_var;i++){
		if(strcmp(fun_table[i].name,name)==0){
			first=fun_table[i].first_address;
		}
	}
}
//语义语法分析及代码生成程序
int TESTparse(){
	int es = 0;
	if((fp=fopen(Scanout,"r"))==NULL){
		printf("打开%s错误!\n",Scanout);
		es = 10;
		return es;
	}
	printf("请输入目标文件名(包括路径):");
	char Codeout[20];
	scanf("%s",Codeout);
	if((fout1=fopen(Codeout,"w"))==NULL){
		printf("\n创建%s错误!\n",Codeout);
		es=10;
		return es;
	}
	if(es==0)
		es = program();
	printf("==语法,语义分析及代码生成程序结果==\n");
	switch(es){
		case 0: printf("语法分析成功!\n"); break;
		case 10: printf("打开文件%s失败!\n"); break;
		case 1: printf("缺少{\n"); break;
		case 2: printf("缺少}\n"); break;
		case 3: printf("缺少标识符\n"); break;
		case 4: printf("缺少分号\n"); break;
		case 5: printf("缺少(\n"); break;
		case 6: printf("缺少)\n"); break;
		case 7: printf("缺少操作数\n"); break;
		case 21:printf("符号表溢出\n");break;
		case 22:printf("变量重复定义\n");break;
		case 23:printf("变量未声明\n");break;
		case 31:printf("函数名符号表溢出\n");break;
		case 32:printf("函数重复定义");break; 
		case 33:printf("函数未定义");break; 
		case 41:printf("参数定义出错");break;
	}
	fclose(fp);
	fclose(fout1);
	return es;
} 

int program(){
	int es = 0;
	fscanf(fp,"%s %s\n",&token,&token1);
	fprintf(fout1,"	BR	LABEL0\n");					//产生停止指令
	while(!strcmp(token,"function")){
		es = fun_declaration();
		if(es>0)
			return es;
		fscanf(fp,"%s %s\n",&token,&token1);
	}	
	if(strcmp(token1,"main")){				 
		es = 8;
		return es;
	}
	else{
		es = main_declaration();
		if(es>0)
			return es;
	}
	fprintf(fout1,"	STOP\n");					//产生停止指令
	return es;
}
int fun_declaration(){
	int es = 0;
	struct vartable table[maxvartablep];
	int num = 0; 
	char fun_name[20];
	int can_num=0;	
	int first=0;	
	fprintf(fout1,"LABEL%d:\n",labelp++);
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"ID")){
		es = 9;
		return es;
	}
	strcpy(fun_name,token1);
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"(")){
		es = 5;
		return es;
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"int")==0){
		first=datap;
		es = canshu(table,num,can_num);
		if(es>0)
			return (es=41);
	}
	fun_def(fun_name,labelp-1,can_num,first);
	if(strcmp(token,")")){
		es = 6;
		return es;
	}	
	es = function_body(table,num);
	fprintf(fout1,"LABEL%d:\n",labelp++);
	fprintf(fout1,"	RET\n");
	return es;
}
int canshu(struct vartable table[maxvartablep],int &num,int &can_num){
	int es=0;
	while(strcmp(token,"int")==0){
		can_num++;
		fscanf(fp,"%s %s\n",&token,&token1);
		if(strcmp(token,"ID"))
			return (es = 3);			//不是标识符
		es = name_def(token1,table,num);
		num++;
		if(es>0)
			return es;
		fscanf(fp,"%s %s\n",&token,&token1);
		if(strcmp(token,")")==0){
			break;
		}
		else{
			fscanf(fp,"%s %s\n",&token,&token1);
		}	
	}
	return es;
}
int main_declaration(){
	int es = 0;
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"(")){
		es = 5;
		return es;
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,")")){
		es = 6;
		return es;
	}
	fprintf(fout1,"LABEL0:\n");
	struct vartable table[maxvartablep];
	int num = 0; 			
	es = function_body(table,num);
	return es;
}
int function_body(struct vartable table[maxvartablep],int &num){
	int es=0,i;
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"{")){
		es = 1;
		return es;
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	es = declaration_list(table,num);
	if(es>0)
		return es;
	printf("	符号表\n");
	printf("	变量名	地址\n");
	for(i=0;i<num;i++){
		printf("	%s	%d\n",table[i].name,table[i].address);
	}
	es = statement_list(table,num);
	if(es>0)
		return es;
	if(strcmp(token,"}")){
		es = 2;
		return es;
	} 
	return es;
}
int declaration_list(struct vartable table[maxvartablep],int &num){
	int es = 0;
	while(strcmp(token,"int")==0){
		es = declaration_stat(table,num);
		num++;
		if(es>0)
			return es;
	}
	return es;
}
int declaration_stat(struct vartable table[maxvartablep],int &num){
	int es=0;
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"ID"))
		return (es = 3);			//不是标识符
	es = name_def(token1,table,num);
	if(es>0)
		return es;
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,";")){
		es = 4;
		return es;
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	return es;
} 
int statement_list(struct vartable table[maxvartablep],int &num){
	int es = 0;
	while(strcmp(token,"}")){
		es = statement(table,num);
		if(es>0)
			return es; 
	}
	if(strcmp(token,"}")&&(feof(fp)||strcmp(token,"function")==0||strcmp(token1,"main")==0)){
			es=2;
			return es;
		}
	return es;	
}
int statement(struct vartable table[maxvartablep],int &num){
	int es = 0;
	if(es==0 && strcmp(token,"if")==0)
		es = if_stat(table,num);
	else if(es==0 && strcmp(token,"while")==0)
		es = while_stat(table,num);
	else if(es==0 && strcmp(token,"for")==0)
		es = for_stat(table,num);
	else if(es==0 && strcmp(token,"read")==0)
		es = read_stat(table,num);
	else if(es==0 && strcmp(token,"write")==0)
		es = write_stat(table,num);
	else if(es==0 && strcmp(token,"{")==0)
		es = compound_stat(table,num);
	else if(es==0 && (strcmp(token,"ID")==0)||strcmp(token,"NUM")==0||strcmp(token,"(")==0)
		es = expression_stat(table,num);
	else if(es==0 && strcmp(token,"call")==0)
		es = call_stat(table,num);
	return es;
}
/*if(<expression>)@BRF(↑label1)<statement>@BR(↑label2)@SETlabel(↓label1)
				  [else<statement>]@SETlabel(↓label2)
其中动作符号定义为
	@BRF(↑label1) 输出BRF label1
	@BR(↑label2) 输出BR label2
	@SETlabel(↓label1) 设置标号label1
	@SETlabel(↓label2) 设置标号label2*/
int if_stat(struct vartable table[maxvartablep],int &num){
	int es = 0,label1,label2;
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"(")){
		es = 5;
		return es;
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	es = expression(table,num);
	if(es>0)
		return es;
	if(strcmp(token,")")){
		es = 6;
		return es;
	}
	label1 = labelp++;						//用label1记住当条件为假时要转向的标号
	fprintf(fout1,"	BRF	LABEL%d\n",label1); //输出假转移指令 
	fscanf(fp,"%s %s\n",&token,&token1);
	es = statement(table,num);
	if(es>0)
		return es;
	label2 = labelp++;						//用label2记住要转向的标号 
	fprintf(fout1,"	BR	LABEL%d\n",label2);//输出无条件转移指令 
	fprintf(fout1,"LABEL%d:\n",label1);		//设置label1记住的符号 
	if(strcmp(token,"else")==0){
	fscanf(fp,"%s %s\n",&token,&token1);
	es = statement(table,num);
	if(es>0)
		return es;	
	}
	fprintf(fout1,"LABEL%d:\n",label2); 		//设置label2记住的标号 
	return es;	
}
/*<while_stat>::[email protected](↑label)(<expression>)@BRF(↑label2)
				<statement>@BR(↓label1)@SETlabel(↓label2)
	动作解释为
	@SETlabel(↑label):设置标号label1 
	@BRF(↑label2):输出BRF label2 
	@BR(↓label1):输出BR label1 
	@SETlabel(↓label2):设置标号 label2*/
int while_stat(struct vartable table[maxvartablep],int &num){
	int es = 0,label1,label2;
	label1 = labelp++;							//设置label1标号 
	fprintf(fout1,"LABEL%d:\n",label1);
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"(")){
		es = 5;
		return es;
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	es = expression(table,num);
	if(es>0)
		return es;
	if(strcmp(token,")")){
		es = 6;
		return es;
	}
	label2 = labelp++;
	fprintf(fout1,"	BRF	LABEL%d",label2);			//输出假转移指令 
	fscanf(fp,"%s %s\n",&token,&token1);
	es = statement(table,num);
	if(es>0){
		return es;
	} 
	fprintf(fout1,"	BR	LABEL%d\n",label1);		//输出无条件转移指令 
	fprintf(fout1,"LABEL%d:\n",label2);				//设置label2标号 
	return es;
}
/*<for_stat>::=for(<expression>@POP;
				@SETlabel(label1)<expression>@BRF(label2)@BR(label3)
				@SETlabel(label4)<expression>@[email protected](label1))
				@SETlabel(label3)<语句>@BR(label4)@SETlabel(label2)*/
int for_stat(struct vartable table[maxvartablep],int &num){
	int es = 0,label1,label2,label3,label4;
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"(")){						//少左括号 
		es = 5;
		return es;
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	es = expression(table,num);
	if(es>0)
		return es;
	fprintf(fout1,"	POP\n");				//设置出栈指令 
	if(strcmp(token,";")){
		es = 4;
		return es;
	}
	label1 = labelp++;
	fprintf(fout1,"LABEL%d:\n",label1);		//设置label1标号 
	fscanf(fp,"%s %s\n",&token,&token1);
	es = expression(table,num);
	if(es>0)
		return es;
	label2 = labelp++;
	fprintf(fout1,"	BRF	LABEL%d\n",label2);
	label3 = labelp++;
	fprintf(fout1,"	BR	LABEL%d\n",label3);
	if(strcmp(token,";")){
		es = 4;
		return es;
	}
	label4 = labelp++;
	fprintf(fout1,"LABEL%d:\n",label4);
	fscanf(fp,"%s %s\n",&token,&token1);
	es = expression(table,num);
	if(es>0)
		return es;
	fprintf(fout1,"	POP\n");	
	fprintf(fout1,"	BR	LABEL%d\n",label1);
	if(strcmp(token,")")){
		es = 6;
		return es;
	}
	fprintf(fout1,"LABEL%d:\n",label3);	
	fscanf(fp,"%s %s\n",&token,&token1);
	es = statement(table,num);
	if(es>0)
		return es;
	fprintf(fout1,"	BR	LABEL%d\n",label4);
	fprintf(fout1,"LABEL%d:\n",label2);	
	return es;	
}
int write_stat(struct vartable table[maxvartablep],int &num){									 
	int es = 0;
	fscanf(fp,"%s %s\n",&token,&token1);
	es = expression(table,num);
	if(es>0)
		return es;
	if(strcmp(token,";")){
		es = 4;
		return es;
	}
	fprintf(fout1,"	OUT\n"); 
	fscanf(fp,"%s %s\n",&token,&token1);
	return es;
}
//<read_stat>→read ID								read <标识符>
int read_stat(struct vartable table[],int &num){
	int es = 0,address;
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"ID")){
		es = 3;
		return es;
	}						//缺少标识符 
	es = lookup(table,token1,&address,num);
	if(es>0)	return es;
	fprintf(fout1,"	IN	\n");
	fprintf(fout1,"	STO	%d\n",address);
	fprintf(fout1,"	POP\n");
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,";")){
		es = 4;
		return es;							//缺少分号 
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	return es;
}
int compound_stat(struct vartable table[maxvartablep],int &num){
	int es = 0;
	fscanf(fp,"%s %s\n",&token,&token1);
	es = statement_list(table,num);
	if(es>0){
		return es;
	}
	if(strcmp(token,"}")){
		es=2;
		return es;
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	return es; 
}
//<expression_stat>→< expression >;|; 
int expression_stat(struct vartable table[maxvartablep],int &num){
	int es = 0;
	if(strcmp(token,";")==0){
		fscanf(fp,"%s %s\n",&token,&token1);
		return es;
	} 
	es = expression(table,num);
	if(es>0)
		return es;
	fprintf(fout1,"	POP\n");
	if(es==0 && strcmp(token,";")==0){ 
		fscanf(fp,"%s %s\n",&token,&token1);
		return es;
	}
	else{											//少分号 
		es = 4;
		return es;
	}
}
//< call _stat>→ call ID‘(’ ‘)’
int call_stat(struct vartable table[maxvartablep],int &num){
	int es = 0;
	int address;
	int address1;
	int canshunum=0;
	char fun_name[20];
	int first=0;
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"ID")){					//缺少函数名 
		es = 9;					
		return es; 
	}
	strcpy(fun_name,token1);	
	cha(fun_name,first);
	if(es>0){
		return es;
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,"(")){
		es = 5;
		return es;
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	while(strcmp(token,"ID")==0){
		es=lookup(table,token1,&address1,num);
		if(es>0)	return es;
		fprintf(fout1,"	LOAD	%d\n",address1);
		fprintf(fout1,"	STO	%d\n",first+canshunum);
		fprintf(fout1,"	POP\n");
		canshunum++;
		fscanf(fp,"%s %s\n",&token,&token1);
		if(strcmp(token,")")==0)
			break;
		else{
			fscanf(fp,"%s %s\n",&token,&token1);
		} 
	}
	if(strcmp(token,")")){
		es = 6;
		return es;
	}
	es=fun_lookup(fun_name,&address,canshunum);
	fprintf(fout1,"	JSR LABEL%d\n",address);
	
	fscanf(fp,"%s %s\n",&token,&token1);
	if(strcmp(token,";")){
		es = 4;
		return es;
	}
	fscanf(fp,"%s %s\n",&token,&token1);
	return es;
}
//< expression >→ ID=<bool_expr>|<bool_expr> 
int expression(struct vartable table[maxvartablep],int &num){
	int es = 0;
	int fileadd;										//用于保存文件位置
	char token2[20],token3[40];
	if(strcmp(token,"ID")==0){
		fileadd = ftell(fp);							//记录文件位置
		fscanf(fp,"%s %s\n",&token2,&token3);
		if(strcmp(token2,"=")==0){
			int address;
			es=lookup(table,token1,&address,num);
			if(es>0)	return es;
			fscanf(fp,"%s %s\n",&token,&token1);
			es = bool_expr(table,num);
			if(es>0)
				return es; 
			fprintf(fout1,"	STO	%d\n",address);
		}
		else{											//如果不是等号,则指针返回等号之前的标识符 
			fseek(fp,fileadd,0); 
			es = bool_expr(table,num);
			if(es>0)
				return es;
		}
	}
	else{
		es = bool_expr(table,num);
	}
	return es;
}
//<bool_expr>-><additive_expr> |< additive_expr >(>|<|>=|<=|==|!=)< additive_expr > 
//<bool_expr>→<additive_expr>{(>|<|>=|<=|==|!=)<additive_expr>}
int bool_expr(struct vartable table[maxvartablep],int &num){
	int es = 0;
	es = additive_expr(table,num);
	if(es>0)
		return es;
	if(strcmp(token,">")==0||strcmp(token,">=")==0||strcmp(token,"<")==0||strcmp(token,"<=")==0||strcmp(token,"==")==0||strcmp(token,"!=")==0){
		char token2[20];
		strcpy(token2,token);
		fscanf(fp,"%s %s\n",&token,&token1);
		es = additive_expr(table,num);
		if(es>0)
			return es;
		if(strcmp(token2,">")==0)	fprintf(fout1,"	GT\n");
		if(strcmp(token2,">=")==0)	fprintf(fout1,"	GE\n");
		if(strcmp(token2,"<")==0)	fprintf(fout1,"	LES\n");
		if(strcmp(token2,"<=")==0)	fprintf(fout1,"	LE\n");
		if(strcmp(token2,"==")==0)	fprintf(fout1,"	EQ\n");
		if(strcmp(token2,"!=")==0)	fprintf(fout1,"	NOTEQ\n");
	}
	return es;
}
//< additive_expr>→<term>{(+|-)< term >}				算数表达式定义为项或者项加减项
int additive_expr(struct vartable table[maxvartablep],int &num){
	int es = 0;
	es = term(table,num);
	if(es>0)
		return es;
	while(strcmp(token,"+")==0||strcmp(token,"-")==0){
		char token2[20];
		strcpy(token2,token);
		fscanf(fp,"%s %s\n",&token,&token1);
		es = term(table,num);
		if(es>0)
			return es;
		if(strcmp(token2,"+")==0)	fprintf(fout1,"	ADD\n");
		if(strcmp(token2,"-")==0)	fprintf(fout1,"	SUB\n");
	}
	return es;
}
//< term >→<factor>{(*| /)< factor >}					项定义为因子或因子乘或除因子
int term(struct vartable table[maxvartablep],int &num){
	int es = 0;
	es = factor(table,num);
	if(es>0)
		return es;	
	while(strcmp(token,"*")==0||strcmp(token,"/")==0){
		char token2[20];
		strcpy(token2,token);
		fscanf(fp,"%s %s\n",&token,&token1);
		es = factor(table,num);
		if(es>0)
			return es;
		if(strcmp(token2,"*")==0)	fprintf(fout1,"	MULT\n");
		if(strcmp(token2,"/")==0)	fprintf(fout1,"	DIV\n");
	}
	return es;
}
//< factor >→’(‘< additive_expr >’)’|ID|NUM		因子定义为表达式或者标识符或者数字
int factor(struct vartable table[maxvartablep],int &num){
	int es = 0;
	if(strcmp(token,"(")==0){										//因子定义成表达式,根据左括号进行判断
		fscanf(fp,"%s %s\n",&token,&token1);
		es = expression(table,num);
		if(es>0)
			return es;
		if(strcmp(token,")")){										//当缺少右括号时
			es = 6;
			return es;
		}
		fscanf(fp,"%s %s\n",&token,&token1);
	}
	else{															//因子定义成标识符或数字
		if(strcmp(token,"ID")==0){
			int address;
			int flag=1;
			es=lookup(table,token1,&address,num);
			if(es>0)	return es;
			fprintf(fout1,"	LOAD	%d\n",address);
			fscanf(fp,"%s %s\n",&token,&token1);
			return es;
		}
		else if(strcmp(token,"NUM")==0){
			fprintf(fout1,"	LOADI	%s\n",token1);
			fscanf(fp,"%s %s\n",&token,&token1);
		}
		else{
			es = 7;												//缺少操作数
			return es;
		}
	}
	return es; 
}
//词法语法语义分析主函数
#include<stdio.h>
#include<ctype.h>

extern int TESTscan();
extern int TESTparse();

char Scanin[300],Scanout[300];
FILE *fin,*fout;

int main(){
	int es=0;
	es = TESTscan();
	if(es>0)
		printf("词法分析有错,编译停止!\n");
	else
		printf("词法分析成功!\n");
	if(es==0){
		es = TESTparse();
		if(es==0)
			printf("语法分析成功!\n");
		else
			printf("语法语义分析错误!\n");
	}
	return 0; 
}
//虚拟机生成
#include<stdio.h>
#include<ctype.h>
#include<stdlib.h>
#include<string.h>

int TESTmachine();

int TESTmachine(){
	int es=0,i,k=0,codecount,stack[1000],stacktop=0;
	int funstack[100],funstacktop=0;
	char Codein[300],code[1000][20],data[1000];
	int label[100]={0};
	char lno[4];
	FILE *fin;
	/*printf("请输入目标文件名(包括路径):");
	scanf("%s",Codein);*/
	if((fin=fopen("3.txt","r"))==NULL){					
		printf("\n打开%s是错误!\n",code);
		es=10;
		return es;
	}
	codecount=0;
	i=fscanf(fin,"%s",&code[codecount]);
	while(!feof(fin)){
		printf("----|  %d  %s  \n",codecount,code[codecount]);
		i=strlen(code[codecount])-1;
		if(code[codecount][i]==':'){
			i=i-5;
			strncpy(lno,&code[codecount][5],i);
			lno[i]='\0';
			label[atoi(lno)]=codecount;							//???			用label数组记住每一个标号的地址 
			//printf("label[%d]=  %d  \n",atoi(lno),label[atoi(lno)]);
			code[codecount][0]=':';
			code[codecount][1]='\0';
			strcat(code[codecount],lno);
			k++;
		}
		codecount++;
		i=fscanf(fin,"%s",&code[codecount]);
	}
	fclose(fin);
	for(i=0;i<codecount;i++){
		int l;
		l=strlen(code[i]);
		if((l>1)&&(code[i][1]=='A')){
			strncpy(lno,&code[i][5],l-5);
			lno[l-5]='\0';
			itoa(label[atoi(lno)],code[i],10);
		}
	}		
	i=0;
	while(i<codecount){								//执行每条指令 
		//printf("code %d %s \n",i,code[i]);
		if(strcmp(code[i],"JSR")==0){				//JSR LAB 无条件跳到LAB,并将JAR下一行的行标保存在函数栈中,便于执行完函数后继续执行主函数 
			i++;
			funstack[funstacktop]=i+1;
			funstacktop++;
			i=atoi(code[i]);
		}
		if(strcmp(code[i],"RET")==0){				//RET 表示当前函数执行完毕,返回调用处 
			i=funstack[funstacktop-1];
			funstacktop--;
		} 
		if(strcmp(code[i],"LOAD")==0){				//LOAD D 将D中的内容加载到操作数栈 
			i++;
			stack[stacktop]=data[atoi(code[i])];
			stacktop++;
		} 
		if(strcmp(code[i],"LOADI")==0){				//LOADI a 将常量a压入操作数栈 
			i++;
			stack[stacktop]=atoi(code[i]);
			stacktop++; 
		} 
		//STO D将操作数栈顶单元内容存入D,切栈顶单元内容保持不变 
		if(strcmp(code[i],"STO")==0){
			i++; 
			data[atoi(code[i])]=stack[stacktop-1];
			//printf("sto  stack %d\n",stack[stacktop-1]);
			//printf("sto  data %d\n",data[atoi(code[i])]); 
		} 
		//POP 栈顶内容出栈 
		if(strcmp(code[i],"POP")==0){
			stacktop--; 
		} 
		//ADD 将栈顶单元与次栈顶单元出栈并相加,和置于栈顶
		if(strcmp(code[i],"ADD")==0){
			stack[stacktop-2] = stack[stacktop-1]+stack[stacktop-2];
			//printf("add  %d\n",stack[stacktop-1]);
			stacktop--;
		}
		//SUB 将次栈顶单元减去栈顶单元并出栈,差置于栈顶
		if(strcmp(code[i],"SUB")==0){
		 	stack[stacktop-2] = stack[stacktop-2]-stack[stacktop-1];
		 	stacktop--; 
		} 
		//MULT 将次栈顶单元与栈顶单元相乘并出栈,积置于栈顶
		if(strcmp(code[i],"MULT")==0){
		 	stack[stacktop-2] = stack[stacktop-2]*stack[stacktop-1];
		 	stacktop--; 
		} 
	 	//DIV 将次栈顶单元与栈顶单元相除并出栈,商置于栈顶 
		if(strcmp(code[i],"DIV")==0){
		 	stack[stacktop-2] = stack[stacktop-2]/stack[stacktop-1];
		 	stacktop--; 
		} 
		//BR	lab 无条件转移到lab 
		if(strcmp(code[i],"BR")==0){
		 	i++;
		 	i=atoi(code[i]);
		} 
		//BRF lab 	检查栈顶单元逻辑值并出栈,若为假则转移到lab 
		if(strcmp(code[i],"BRF")==0){
		 	i++;
			if(stack[stacktop-1]==0)
				i=atoi(code[i]);
			i--; 
		} 
		//EQ 将栈顶两单元做等于比较并出栈,并将结果真或假(1或0),置于栈顶 
		if(strcmp(code[i],"EQ")==0){
		 	stack[stacktop-2] = stack[stacktop-2]==stack[stacktop-1];
		 	stacktop--; 
		} 
		//NOTEQ 将栈顶两单元做不等于比较并出栈,并将结果真或假(1或0),置于栈顶 
		if(strcmp(code[i],"NOTEQ")==0){
		 	stack[stacktop-2] = stack[stacktop-2]!=stack[stacktop-1];
		 	stacktop--; 
		} 
		//GT 次栈顶大于栈顶操作数并出栈,则栈顶置1,否则置0 
		if(strcmp(code[i],"GT")==0){
		 	stack[stacktop-2] = stack[stacktop-2]>stack[stacktop-1];
		 	stacktop--; 
		} 
		//LES 次栈顶小于栈顶操作数并出栈,则栈顶置1,否则置0 
		if(strcmp(code[i],"LES")==0){
		 	stack[stacktop-2] = stack[stacktop-2]<stack[stacktop-1];
		 	stacktop--; 
		} 
		//GE 次栈顶大于等于栈顶操作数并出栈,则栈顶置1,否则置0 
		if(strcmp(code[i],"GE")==0){
		 	stack[stacktop-2] = stack[stacktop-2]>=stack[stacktop-1];
		 	stacktop--; 
		} 
		//LE 次栈顶小于等于栈顶操作数并出栈,则栈顶置1,否则置0 
		if(strcmp(code[i],"LE")==0){
		 	stack[stacktop-2] = stack[stacktop-2]<=stack[stacktop-1];
		 	stacktop--; 
		} 
		//AND 将栈顶两单元做逻辑与运算并出战,并将结果真或假(1或0)置于栈顶
		if(strcmp(code[i],"AND")==0){
		 	stack[stacktop-2] = stack[stacktop-2]&&stack[stacktop-1];
		 	stacktop--; 
		} 
		//OR 将栈顶两单元做逻辑或运算并出战,并将结果真或假(1或0)置于栈顶
		if(strcmp(code[i],"OR")==0){
		 	stack[stacktop-2] = stack[stacktop-2]||stack[stacktop-1];
		 	stacktop--; 
		} 
		//NOT 将栈顶逻辑值取反
		if(strcmp(code[i],"NOT")==0){
		 	stack[stacktop-1]=!stack[stacktop-1];
		} 
		//IN 从标准输入设备读入一个整型数据,并入栈
		if(strcmp(code[i],"IN")==0){
			printf("请输入数据:");
			scanf("%d",&stack[stacktop]);
			stacktop++; 
		} 
		//OUT 将栈顶内容出栈,并输出到标准输出设备上 
		if(strcmp(code[i],"OUT")==0){
		 	printf("程序输出%d\n",stack[stacktop-1]);
			stacktop--; 
		} 
		//STOP 停止执行
		if(strcmp(code[i],"STOP")==0){
			break;
		} 
		i++;
		//显示栈内容
		/*for(k=stacktop-1;k>=0;k--)
		 	printf("%d  ",stack[k]);
		printf("\n");*/
		//printf("	%d		%d\n",data[0],data[1]);
	} 
	return es;
} 
int main(){
	int es=0;
	es = TESTmachine();
}

 


'; ch=getc(fin); es=3; //设置错误代码 printf("%d行发生错误",linenum); fprintf(fout,"\n%s\t%s\n","ERROR",token); fprintf(fout,"%s %d\n\n","错误行号为:",linenum); } } fclose(fin); fclose(fout); return es; } //语法及语义分析 #include<stdio.h> #include<ctype.h> #include<conio.h> #include<string.h> #define maxvartablep 500 //定义符号表的容量 struct vartable{ char name[8]; int address; }; //符号表最多容纳maxvartablep个记录 struct fun_table{ char name[30]; int address; int can_num; int first_address; //记录第一个参数的地址 }fun_table[maxvartablep]; int program(); int fun_declaration(); int canshu(struct vartable table[maxvartablep],int &num,int &can_num); int main_declaration(); int function_body(struct vartable table[maxvartablep],int &num); int declaration_list(struct vartable table[maxvartablep],int &num); int declaration_stat(struct vartable table[maxvartablep],int &num); int statement_list(struct vartable table[maxvartablep],int &num); int statement(struct vartable table[maxvartablep],int &num); int if_stat(struct vartable table[maxvartablep],int &num); int while_stat(struct vartable table[maxvartablep],int &num); int for_stat(struct vartable table[maxvartablep],int &num); int write_stat(struct vartable table[maxvartablep],int &num); int read_stat(struct vartable table[maxvartablep],int &num); int compound_stat(struct vartable table[maxvartablep],int &num); int expression_stat(struct vartable table[maxvartablep],int &num); int call_stat(struct vartable table[maxvartablep],int &num); int expression(struct vartable table[maxvartablep],int &num); int bool_expr(struct vartable table[maxvartablep],int &num); int additive_expr(struct vartable table[maxvartablep],int &num); int term(struct vartable table[maxvartablep],int &num); int factor(struct vartable table[maxvartablep],int &num); int name_def(char *name,int vartablep,int datap); char token[10],token1[40]; extern char Scanout[300],Codeout[300]; FILE *fp,*fout1; int labelp = 1,datap=0; //labelp用于记录当前标记,防止重复 int fun_var=0; //插入符号表@name_def(↓n,t)的程序如下: int name_def(char *name,vartable table[],int vartablep){ int i,es = 0; if(vartablep>maxvartablep) return 21; for(i=vartablep-1;i>=0;i--){ if(strcmp(table[i].name,name)==0){ es=22; break; } } if(es>0){ return es; } strcpy(table[vartablep].name,name); table[vartablep].address = datap; datap++; return es; } int fun_def(char *name,int datap,int can_num,int first){ int i,es = 0; if(fun_var>maxvartablep) return 31; for(i=fun_var-1;i>=0;i--){ if(strcmp(fun_table[i].name,name)==0&&fun_table[i].can_num==can_num){ es=32; break; } } strcpy(fun_table[fun_var].name,name); fun_table[fun_var].address = datap; fun_table[fun_var].can_num=can_num; fun_table[fun_var].first_address=first; fun_var++; return es; } //查询符号表返回地址 int lookup(struct vartable table[],char *name,int *paddress,int num){ int i,es = 0; for(i=0;i<num;i++){ if(strcmp(table[i].name,name)==0){ *paddress = table[i].address; return es; } } es = 23; return es; } int fun_lookup(char *name,int *paddress,int num){ int i,es = 0; for(i=0;i<fun_var;i++){ if(strcmp(fun_table[i].name,name)==0&&fun_table[i].can_num==num){ *paddress = fun_table[i].address; return es; } } es = 33; return es; } void cha(char *name,int &first){ int i; for(i=0;i<fun_var;i++){ if(strcmp(fun_table[i].name,name)==0){ first=fun_table[i].first_address; } } } //语义语法分析及代码生成程序 int TESTparse(){ int es = 0; if((fp=fopen(Scanout,"r"))==NULL){ printf("打开%s错误!\n",Scanout); es = 10; return es; } printf("请输入目标文件名(包括路径):"); char Codeout[20]; scanf("%s",Codeout); if((fout1=fopen(Codeout,"w"))==NULL){ printf("\n创建%s错误!\n",Codeout); es=10; return es; } if(es==0) es = program(); printf("==语法,语义分析及代码生成程序结果==\n"); switch(es){ case 0: printf("语法分析成功!\n"); break; case 10: printf("打开文件%s失败!\n"); break; case 1: printf("缺少{\n"); break; case 2: printf("缺少}\n"); break; case 3: printf("缺少标识符\n"); break; case 4: printf("缺少分号\n"); break; case 5: printf("缺少(\n"); break; case 6: printf("缺少)\n"); break; case 7: printf("缺少操作数\n"); break; case 21:printf("符号表溢出\n");break; case 22:printf("变量重复定义\n");break; case 23:printf("变量未声明\n");break; case 31:printf("函数名符号表溢出\n");break; case 32:printf("函数重复定义");break; case 33:printf("函数未定义");break; case 41:printf("参数定义出错");break; } fclose(fp); fclose(fout1); return es; } int program(){ int es = 0; fscanf(fp,"%s %s\n",&token,&token1); fprintf(fout1," BR LABEL0\n"); //产生停止指令 while(!strcmp(token,"function")){ es = fun_declaration(); if(es>0) return es; fscanf(fp,"%s %s\n",&token,&token1); } if(strcmp(token1,"main")){ es = 8; return es; } else{ es = main_declaration(); if(es>0) return es; } fprintf(fout1," STOP\n"); //产生停止指令 return es; } int fun_declaration(){ int es = 0; struct vartable table[maxvartablep]; int num = 0; char fun_name[20]; int can_num=0; int first=0; fprintf(fout1,"LABEL%d:\n",labelp++); fscanf(fp,"%s %s\n",&token,&token1); if(strcmp(token,"ID")){ es = 9; return es; } strcpy(fun_name,token1); fscanf(fp,"%s %s\n",&token,&token1); if(strcmp(token,"(")){ es = 5; return es; } fscanf(fp,"%s %s\n",&token,&token1); if(strcmp(token,"int")==0){ first=datap; es = canshu(table,num,can_num); if(es>0) return (es=41); } fun_def(fun_name,labelp-1,can_num,first); if(strcmp(token,")")){ es = 6; return es; } es = function_body(table,num); fprintf(fout1,"LABEL%d:\n",labelp++); fprintf(fout1," RET\n"); return es; } int canshu(struct vartable table[maxvartablep],int &num,int &can_num){ int es=0; while(strcmp(token,"int")==0){ can_num++; fscanf(fp,"%s %s\n",&token,&token1); if(strcmp(token,"ID")) return (es = 3); //不是标识符 es = name_def(token1,table,num); num++; if(es>0) return es; fscanf(fp,"%s %s\n",&token,&token1); if(strcmp(token,")")==0){ break; } else{ fscanf(fp,"%s %s\n",&token,&token1); } } return es; } int main_declaration(){ int es = 0; fscanf(fp,"%s %s\n",&token,&token1); if(strcmp(token,"(")){ es = 5; return es; } fscanf(fp,"%s %s\n",&token,&token1); if(strcmp(token,")")){ es = 6; return es; } fprintf(fout1,"LABEL0:\n"); struct vartable table[maxvartablep]; int num = 0; es = function_body(table,num); return es; } int function_body(struct vartable table[maxvartablep],int &num){ int es=0,i; fscanf(fp,"%s %s\n",&token,&token1); if(strcmp(token,"{")){ es = 1; return es; } fscanf(fp,"%s %s\n",&token,&token1); es = declaration_list(table,num); if(es>0) return es; printf(" 符号表\n"); printf(" 变量名 地址\n"); for(i=0;i<num;i++){ printf(" %s %d\n",table[i].name,table[i].address); } es = statement_list(table,num); if(es>0) return es; if(strcmp(token,"}")){ es = 2; return es; } return es; } int declaration_list(struct vartable table[maxvartablep],int &num){ int es = 0; while(strcmp(token,"int")==0){ es = declaration_stat(table,num); num++; if(es>0) return es; } return es; } int declaration_stat(struct vartable table[maxvartablep],int &num){ int es=0; fscanf(fp,"%s %s\n",&token,&token1); if(strcmp(token,"ID")) return (es = 3); //不是标识符 es = name_def(token1,table,num); if(es>0) return es; fscanf(fp,"%s %s\n",&token,&token1); if(strcmp(token,";")){ es = 4; return es; } fscanf(fp,"%s %s\n",&token,&token1); return es; } int statement_list(struct vartable table[maxvartablep],int &num){ int es = 0; while(strcmp(token,"}")){ es = statement(table,num); if(es>0) return es; } if(strcmp(token,"}")&&(feof(fp)||strcmp(token,"function")==0||strcmp(token1,"main")==0)){ es=2; return es; } return es; } int statement(struct vartable table[maxvartablep],int &num){ int es = 0; if(es==0 && strcmp(token,"if")==0) es = if_stat(table,num); else if(es==0 && strcmp(token,"while")==0) es = while_stat(table,num); else if(es==0 && strcmp(token,"for")==0) es = for_stat(table,num); else if(es==0 && strcmp(token,"read")==0) es = read_stat(table,num); else if(es==0 && strcmp(token,"write")==0) es = write_stat(table,num); else if(es==0 && strcmp(token,"{")==0) es = compound_stat(table,num); else if(es==0 && (strcmp(token,"ID")==0)||strcmp(token,"NUM")==0||strcmp(token,"(")==0) es = expression_stat(table,num); else if(es==0 && strcmp(token,"call")==0) es = call_stat(table,num); return es; } /*if(<expression>)@BRF(↑label1)<statement>@BR(↑label2)@SETlabel(↓label1) [else<statement>]@SETlabel(↓label2) 其中动作符号定义为 @BRF(↑label1) 输出BRF label1 @BR(↑label2) 输出BR label2 @SETlabel(↓label1) 设置标号label1 @SETlabel(↓label2) 设置标号label2*/ int if_stat(struct vartable table[maxvartablep],int &num){ int es = 0,label1,label2; fscanf(fp,"%s %s\n",&token,&token1); if(strcmp(token,"(")){ es = 5; return es; } fscanf(fp,"%s %s\n",&token,&token1); es = expression(table,num); if(es>0) return es; if(strcmp(token,")")){ es = 6; return es; } label1 = labelp++; //用label1记住当条件为假时要转向的标号 fprintf(fout1," BRF LABEL%d\n",label1); //输出假转移指令 fscanf(fp,"%s %s\n",&token,&token1); es = statement(table,num); if(es>0) return es; label2 = labelp++; //用label2记住要转向的标号 fprintf(fout1," BR LABEL%d\n",label2);//输出无条件转移指令 fprintf(fout1,"LABEL%d:\n",label1); //设置label1记住的符号 if(strcmp(token,"else")==0){ fscanf(fp,"%s %s\n",&token,&token1); es = statement(table,num); if(es>0) return es; } fprintf(fout1,"LABEL%d:\n",label2); //设置label2记住的标号 return es; } /*<while_stat>:://词法分析 #include<stdio.h> #include<ctype.h> #



你的当前访问异常,请进行认证后继续阅读剩余内容。

分享到: