//词法分析
#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>
#