#include
#include
#include
#define maxvartablep 500/*定义符号表达式*/
int TESTparse();
int program();
int compound_stat();
int statement();
int expression_stat();
int expression();
int bool_expr();
int additive_expr();
int term();
int factor();
int if_stat();
int while_stat();
int for_stat();
int write_stat();
int read_stat();
int declaration_stat();
int declaration_list();
int statement_list();
int compound_list();
int name_def(char *name);
char token[20],token1[40];/*token保存单词符号,token1保存单词组*/
extern char Scanout[300],Codeout[300];/*保存词法分析输出文件名*/
FILE *fp,*fout;/*用于指向输入输出文件的指针*/
struct /*定义符号表结构*/
{
char name[8];
int address;
}vartable[maxvartablep];/*改符号表最多容纳maxvartablep个记录*/
int vartablep=0,labelp=0,datap=0;/*插入符号表动作@name-def!n,t的程序如下*/
int name_def(char *name)
{
int i,es=0;
if(vartablep>=maxvartablep) return(21);
for(i=vartablep-1;i>=0;i--)/*查符号表*/
{
if(strcmp(vartable[i],name,name)==0)
{
es=22;/*22表示变量重复声明*/
break;
}
}
if(es>0) return(es);
strcpy(vartable[vartablep],name,name);
vartable[vartablep].address=datap;
printf("@\n");
printf(" %s %d\n",vartable[vartablep].name,vartable[vartablep].address);
printf("@\n");
datap++;/*分配一个单元,数据区指针加1*/
vartablep++;
return(es);
}
/*查询符号表返回地址*/
int lookup(char *name,int *paddress)
{
int i,es=0;
for(i=0;i {
if(strcmp(vartable[i],name,name)==0)
{
*paddress=vartable[i].address;
return(es);
}
}
es=23;/*变量没有声明*/
return(es);
}
/*语法、语义分析及代码生成程序*/
int TESTparse()
{
int es=0;
if((fp=fopen(Scanout,"r"))==NULL)
{
printf("\n open%serror!\n",Scanout);
es=10;
return(es);
}
printf("qing shu ru mu biao wen jian(bao kuo lu jing):");
scanf("%s",Codeout);
if((fout=fopen(Codeout,"w"))==NULL)
{
printf("\n create%serror!\n",Codeout);
es=10;
return(es);
}
if(es==0) es=program();
printf("==yu fa\yu yi fen xi ji dai ma sheng cheng cheng xu jie guo==\n");/*语法、语义分析及代码生成程序结果*/
switch(es)
{
case 0:printf("yu fa\yu yi fen xi cheng gong bing chou xiang ji hui bian sheng cheng dai ma!\n");break;/*语法、语义分析成功并抽象机汇编生成代码!*/
case 10:printf("open text%serror!\n",Scanout);break;
case 1:printf("lack of{!\n");break;
case 2:printf("lack of}!\n");break;
case 3:printf("lack of biao shi fu!\n");break;
case 4:printf("lack of fen hao!\n");break;
case 5:printf("lack of(!\n");break;
case 6:printf("lack of)!\n");break;
case 7:printf("lack of cao zuo shu!\n");break;
case 21:printf("fu hao biao yi chu!\n");break;/*符号表溢出*/
case 22:printf("bian liang chong fu ding yi!\n");break;/*变量重复定义*/
case 23:printf("bian liang wei sheng ming!\n");break;/*变量未声明*/
}
fclose(fp);
fclose(fout);
return(es);
}
/*<程序>::={<声明序列><语句序列>}*/
/*program::={}*/
int program()
{
int es=0,i;
fscanf(fp,"%s%s\n",token,token1);
printf("%s%s\n",token,token1);
if(strcmp(token,"{"))/*判断是否'{'*/
{
es=1;
return(es);
}
fscanf(fp,"%s%s\n",&token,&token1);
printf("%s%s\n",token,token1);
es=declaration_list();
if(es>0) return(es);
printf(" fu hao biao\n");
printf(" name address");
for(i=0;i printf(" %s %d\n",vartable[i].name,vartable[i].address);
es=statement_list();
if(es>0) return(es);/*判断是否'}'*/
if(strcmp(token,"}"))
{
es=2;
return(es);
}
fprintf(fout," STOP\n");/*生产停止指令*/
return(es);
}
/*<声明序列>::=<声明序列><声明语句>|<声明语句>*/
/*::=|*/
/*改成::={}*/
int declaration_list()
{
int es=0;
while(strcmp(token,"int")==0)
{
es=declaration_stat();
if(es>0) return(es);
}
return(es);
}
/*<声明语句>::=int<变量>*/
/*!vartablep,datap,codep->int if(strcmp(token,"ID")) return(es=3);/*不是标识符*/
es=name_def(token1);/*插入标识符*/
if(es>0) return(es);
fscanf(fp,"%s%s\n",&token,&token1);printf("%s%s\n",token,token1);
if(strcmp(token,";")) return(es=4);
fscanf(fp,"%s%s\n",&token,&token1);printf("%s%s\n",token,token1);
return(es);
}
/*<语句序列>::=<语句序列><语句>|<语句>*/
/*::=|*/
/*改成::={}*/
int statement_list()
{
int es=0;
while(strcmp(token,"}"))
{
es=statement();
if(es>0) return(es);
}
return(es);
}
/*<语句>::=|||||<复合语句>|<表达式语句>*/
/*::=||||*/
int statement()
{
int es=0;
if(es==0&&strcmp(token,"if")==0) es=if_stat();
if(es==0&&strcmp(token,"while")==0) es=while_stat();
if(es==0&&strcmp(token,"for")==0) es=for_stat();
/*可在此处添加do语句调用*/
if(es==0&&strcmp(token,"read")==0) es=read_stat();
if(es==0&&strcmp(token,"write")==0) es=write_stat();
if(es==0&&strcmp(token,"{")==0) es=compound_stat();/*复合语句*/
if(es==0&&strcmp(token,"ID")==0||strcmp(token,"NUM")==0) es=expression_stat();/*表达式语句*/
return(es);
}
/*::=if(<表达式>)<语句>[else<语句>]*/
/*::=if()[else]*/
/*if(<表达式>)@BRF!label1<语句>@BR!label2@SETlabel!label1[else<语句>]@SETlabel!label2
if()@BRF!label1@BR!label2@SETlabel!label1[else]@SETlabel!label2
其中动作符号的含义如下:
@BRF!label1:输出BRFlabel1
@BR!label2:输出BRlabel2
@SETlabel!label1:设置标号label1
@SETlabel!label2:设置标号label2*/
int if_stat()
{
int es=0,label1,label2;/*if*/
fscanf(fp,"%s%s\n",&token,&token1);printf("%s%s\n",token,token1);
if(strcmp(token,"(")) return(es=5);/*少左括号*/
fscanf(fp,"%s%s\n",&token,&token1);printf("%s%s\n",token,token1);
es=expression();
if(es>0) return(es);
if(strcmp(token,")")) return(es=6);/*少右括号*/
label1=labelp++;/*用label1记住条件为假时要转向的标号*/
fprintf(fout," BRF LABEL%d\n",label1);/*输出假转移指令*/
fscanf(fp,"%s%s\n",&token,&token1);printf("%s%s\n",token,token1);
es=statement();
if(es>0) return(es);
label2=labelp++;/*用label2记住要转向的标号*/
fprintf(fout," BR LABEL%d\n",label2);/*输出无条件转移指令*/
fprintf(fout,"LABEL%d:\n",label1);/*设置label1记住的标号*/
if(strcmp(token,"else")==0)/*else部分处理*/
{
fscanf(fp,"%s%s\n",&token,&token1);printf("%s%s\n",token,token1);
es=statement();
if(es>0) return(es);
}
fprintf(fout,"LABEL%d:\n",label2);/*设置label2记住的标号*/
return(es);
}
/*::=while(<表达式>)<语句>*/
/*::=while()*/
/*::=while@SETlabel!label1()@BRF!label2@BR!label@SETlabel!label2
动作解释:
@SETlabel!label1:设置标号label1
@BRF!label2:输出BRFlabel2
@BR!label1:输出BRlabel1
@SETlabel!label2:设置标号label2*/
int while_stat()
{
int es=0,label1,label2;
label1=labelp++;
fprintf(fout,"LABEL%d:\n",label1);/*设置label1记住的标号*/
fscanf(fp,"%s%s\n",&token,&token1);printf("%s%s\n",token,token1);
if(strcmp(token,"(")) return(es=5);/*少左括号*/
fscanf(fp,"%s%s\n",&token,&token1);printf("%s%s\n",token,token1);
es=expression();
if(es>0) return(es);
if(strcmp(token,")")) return(es=6);/*少右括号*/
label2=labelp++;
fprintf(fout," BRF LABEL%d\n",label2);/*输出无条件转移指令*/
fscanf(fp,"%s%s\n",&token,&token1);printf("%s%s\n",token,token1);
es=statement();
if(es>0) return(es);
fprintf(fout," BR LABEL%d\n",label1);/*输出假转移指令*/
fprintf(fout,"LABEL%d:\n",label2);/*设置label2记住的标号*/
return(es);
}
/*::=for(,,)*/
/*::=for(;
@SETlabel!label1@BRF!label2@BR!label3;
@SETlabel!label4@BR!label)
@SETlabel!label3@BR!label4@SETlabel!label2
动作解释:
1,@SETlabel!label1:设置标号label1
2,@BRF!label2:输出BRFlabel2
3,@BR!label3:输出BRlabel3
4,@SETlabel!label4:设置标号label4
5,@BR!label1:输出BRlabel1
6,@SETlabel!label3:设置标号label3
7,@BR!label4:输出BRlabel4
8,@SETlabel!label2:设置标号label2*/
int for_stat()
{
int es=0,label1,label2,label3,label4;
fscanf(fp,"%s%s\n",&token,&token1);printf("%s%s\n",token,token1);
if(strcmp(token,"(")) return(es=5);/*少左括号*/
fscanf(fp,"%s%s\n",&token,&token1);printf("%s%s\n",token,token1);
es=expression();
if(es>0) return(es);
if(strcmp(token,";")) return(es=4);/*少分号*/
label1=labelp++;
fprintf(fout,"LABEL%d:\n",label1);/*设置label1标号*/
fscanf(fp,"%s%s\n",&token,&token1);printf("%s%s\n",token,token1);
es=expression();
if(es>0) return(es);
label2=labelp++;
fprintf(fout," BRF LABEL%d\n",label2);/*输出无条件转移指令*/
label3=labelp++;
fprintf(fout," BR LABEL%d\n",label3);/*输出无条件转移指令*/
if(strcmp(token,";")) return(es=4);/*少分号*/
label4=labelp++;
fprintf(fout,"LABEL%d:\n",label4);/*设置label4标号*/
fscanf(fp,"%s%s\n",&token,&token1);printf("%s%s\n",token,token1);
es=expression();
if(es>0) return(es);
fprintf(fout," BR LABEL%d\n",label1);/*输出无条件转移指令*/
if(strcmp(token,")")) return(es=6);/*少右括号*/
fprintf(fout,"LABEL%d:\n",label3);/*设置label3标号*/
fscanf(fp,"%s%s\n",&token,&token1);printf("%s%s\n",token,token1);
es=statement();
if(es>0) return(es);
fprintf(fout," BR LABEL%d\n",label4);/*输出无条件转移指令*/
fprintf(fout,"LABEL%d:\n",label2);/*设置label2标号*/
return(es);
}
/*::=write*/
/*::=write@OUT*/
/*动作解释:
@OUT:输出OUT*/
int write_stat()
{
int es=0;
fscanf(fp,"%s%s\n",&token,&token1);printf("%s%s\n",token,token1);
es=expression();
if(es>0) return(es);
if(strcmp(token,";")) return(es=4);/*少分号*/
fprintf(fout," OUT\n");/*输出指令*/
fscanf(fp,"%s%s\n",&token,&token1);printf("%s%s\n",token,token1);
return(es);
}
/*::=read ID*/
/*::=read ID!n LOOK!n!d@IN@STI!d*/
/*动作解释
@LOOK!n!d查符号表n,给出变量地址d;没有,变量没定义
@IN:输出IN
@STI!d:输出指令代码STI d*/
int read_stat()
{
int es=0,address;
fscanf(fp,"%s%s\n",&token,&token1);printf("%s%s\n",token,token1);
if(strcmp(token,"ID")) return(es=3);/*少标识符*/
es=lookup(token1,&address);
if(es>0) return(es);
fprintf(fout," IN %d\n",address);/*输入指令*/
fscanf(fp,"%s%s\n",&token,&token1);printf("%s%s\n",token,token1);
if(strcmp(token,";")) return(es=4);/*少分号*/
fscanf(fp,"%s%s\n",&token,&token1);printf("%s%s\n",token,token1);
return(es);
}
/*::={}*/
int compound_stat()
{
int es=0;
fscanf(fp,"%s%s\n",&token,&token1);printf("%s%s\n",token,token1);
es=statement_list();
return(es);
}
/*::=*/
int expression_stat()
{
int es=0;
if(strcmp(token,";")==0)
{
fscanf(fp,"%s%s\n",&token,&token1);printf("%s%s\n",token,token1);
return(es);
}
es=expression();
if(es>0) return(es);
if(strcmp(token,";")==0)
{
fscanf(fp,"%s%s\n",&token,&token1);printf("%s%s\n",token,token1);
return(es);
}
else
{
es=4;
return(es);/*少分号*/
}
}
/*<表达式>::=<标识符>=<布尔表达式>|<布尔表达式>*/
int expression()
{
int es=0,fileadd;
char token2[20],token3[30];
if(strcmp(token,"ID")==0)
{
fileadd=ftell(fp);/*记住当前文件位置*/
fscanf(fp,"%s%s\n",&token2,&token3);printf("%s%s\n",token2,token3);
if(strcmp(token2,"=")==0)/*'='*/
{
int address;
es=lookup(token1,&address);
if(es>0) return(es);
fscanf(fp,"%s%s\n",&token,&token1);printf("%s%s\n",token,token1);
es=bool_expr();
if(es>0) return(es);
fprintf(fout," STO%d\n",address);
}
else
{
fseek(fp,fileadd,0);/*若非'='则文件指针回到'='前的标识符*/
printf("%s%s\n",token,token1);
es=bool_expr();
if(es>0) return(es);
}
}
return(es);
}
/*::=|(>|<|>=|<=|==|!=)*/
/*::=
|>@GT
|<@LES
|>=@GE
|<=@LE
|==@EQ
|!=@NOTEQ*/
int bool_expr()
{
int es=0;
es=additive_expr();
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);printf("%s%s\n",token,token1);
es=additive_expr();
if(es>0) return(es);
if(strcmp(token2,">")==0) fprintf(fout," GT\n");
if(strcmp(token2,">=")==0) fprintf(fout," GE\n");
if(strcmp(token2,"<")==0) fprintf(fout," LES\n");
if(strcmp(token2,"<=")==0) fprintf(fout," LE\n");
if(strcmp(token2,"==")==0) fprintf(fout," EQ\n");
if(strcmp(token2,"!=")==0) fprintf(fout," NOTEQ\n");
}
return(es);
}
/*::={(+|-)}*/
/*::={(+@ADD|-@SUB)}*/
int additive_expr()
{
int es=0;
es=term();
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);printf("%s%s\n",token,token1);
es=term();
if(es>0) return(es);
if(strcmp(token2,"+")==0) fprintf(fout," ADD\n");
if(strcmp(token2,"-")==0) fprintf(fout," SUB\n");
}
return(es);
}
/*::={(*|/)}*/
/*::={(*@MULT|/@DIV)}*/
int term()
{
int es=0;
es=factor();
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);printf("%s%s\n",token,token1);
es=factor();
if(es>0) return(es);
if(strcmp(token2,"*")==0) fprintf(fout," MULT\n");
if(strcmp(token2,"/")==0) fprintf(fout," DIV\n");
}
return(es);
}
/*::=()|ID|NUM*/
/*::=()|ID!n@LOOK!n!d@LOAD!d|NUM!i@LOAD!i*/
int factor()
{
int es=0;
if(strcmp(token,"(")==0)
{
fscanf(fp,"%s%s\n",&token,&token1);printf("%s%s\n",token,token1);
es=expression();
if(es>0) return(es);
if(strcmp(token,")")) return(es=6);/*少右括号*/
fscanf(fp,"%s%s\n",&token,&token1);printf("%s%s\n",token,token1);
}
else
{
if(strcmp(token,"ID")==0)
{
int address;
es=lookup(token1,&address);/*查符号表,获取变量地址*/
if(es>0) return(es);/*变量没声明*/
fprintf(fout," LOAD%d\n",address);
fscanf(fp,"%s%s\n",&token,&token1);printf("%s%s\n",token,token1);
return(es);
}
if(strcmp(token,"NUM")==0)
{
fprintf(fout," LOADI%d\n",token1);
fscanf(fp,"%s%s\n",&token,&token1);printf("%s%s\n",token,token1);
return(es);
}
else
{
es=7;/*缺少操作数*/
return(es);
}
}
return(es);
}
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/12993749/viewspace-353264/
,如需转载,请注明出处,否则将追究法律责任。