#include 《stdio.h》
#include 《ctype.h》
#include 《conio.h》
#include “stdio.h”
//下面定义保留,为简化程序,使用字符指针数组保存所有保留字。
//如果想增加保留字,可继续添加,并修改保留字数目
#define keywordSum 8
#define maxvartablep 500//定义符号表的容量
char *keyword[keywordSum]={ “if”,“else”,“for”,“while”,“do”,“int”,“read”,“write”};
//下面定义纯单分界符,如需要可添加
char singleword[50]=“+-*(){};,:”;
//下面定义双分界符的首字符
char doubleword[10]=“》《=!”;
//函数调用
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_stat();
int name_def(char *name);
char token[20],token1[40];//token保存单词符号,token1保存单词值
char Scanout[300],Codeout[300]; //保存词法分析输出文件名
FILE *fp,*fout; //用于指向输入输出文件的指针
struct{//定义符号表结构
char name[8];
int address;
}vartable[maxvartablep];//改符号表最多容纳maxvartablep个记录
int vartablep=0,labelp=0,datap=0;
int TESTscan();
char Scanin[300],Errorfile[300]; //用于接收输入输出以及错误文件名
FILE *fin; //用于指向输入输出文件的指针
int TESTscan()//词法分析函数
{
char ch,token[40]; //ch为每次读入的字符,token用于保存识别出的单词
int es=0,j,n; //es错误代码,0表示没有错误。j,n为临时变量,控制组合单词时的下标等
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创建词法分析输出文件出错!/n”);
return(2); //输出文件出错返回错误代码2
}
ch=getc(fin);
while(ch!=EOF)
{
while (ch==‘ ’||ch==‘/n’||ch==‘/t’) ch=getc(fin);
if (ch==EOF) break;
if (isalpha(ch)) //如果是字母,则进行标识符处理
{
token[0]=ch; j=1;
ch=getc(fin);
while(isalnum(ch)) //如果是字母数字则组合标识符;如果不是则标识符组合结束
{
token[j++]=ch; //组合的标识符保存在token中
ch=getc(fin); //读下一个字符
}
token[j]=‘/0’; //标识符组合结束
//查保留字
n=0;
while ((n《keywordSum) && strcmp(token,keyword[n])) n++;
if (n》=keywordSum) //不是保留字,输出标识符
fprintf(fout,“%s/t%s/n”,“ID”,token); //输出标识符符号
else//是保留字,输出保留字
fprintf(fout,“%s/t%s/n”,token,token); //输出保留字符号
} else if (isdigit(ch))//数字处理
{
token[0]=ch; j=1;
ch=getc(fin); //读下一个字符
while (isdigit(ch)) //如果是数字则组合整数;如果不是则整数组合结束
{
token[j++]=ch; //组合整数保存在token中
ch=getc(fin); //读下一个字符
}
token[j]=‘/0’; //整数组合结束
fprintf(fout,“%s/t%s/n”,“NUM”,token); //输出整数符号
} else if (strchr(singleword,ch)》0) //单分符处理
{
token[0]=ch; token[1]=‘/0’;
ch=getc(fin);//读下一个符号以便识别下一个单词
fprintf(fout,“%s/t%s/n”,token,token); //输出单分界符符号
}else if (strchr(doubleword,ch)》0) //双分界符处理
{
token[0]=ch;
ch=getc(fin); //读下一个字符判断是否为双分界符
if (ch==‘=’) //如果是=,组合双分界符
{
token[1]=ch;token[2]=‘/0’; //组合双分界符结束
ch=getc(fin); //读下一个符号以便识别下一个单词
} else//不是=则为单分界符
token[1]=‘/0’;
fprintf(fout,“%s/t%s/n”,token,token); //输出单或双分界符符号
} else if (ch==‘/’) //注释处理
{
ch=getc(fin); //读下一个字符
if (ch==‘*’) //如果是*,则开始处理注释
{ char ch1;
ch1=getc(fin); //读下一个字符
do
{ ch=ch1;ch1=getc(fin);} //删除注释
while ((ch!=‘*’ || ch1!=‘/’)&&ch1!=EOF); //直到遇到注释结束符*/或文件尾
ch=getc(fin);//读下一个符号以便识别下一个单词
} else //不是*则处理单分界符/
{
token[0]=‘/’; token[1]=‘/0’;
fprintf(fout,“%s/t%s/n”,token,token); //输出单分界符/
}
} else//错误处理
{
token[0]=ch;token[1]=‘/0’;
ch=getc(fin); //读下一个符号以便识别下一个单词
es=3; //设置错误代码
fprintf(fout,“%s/t%s/n”,“ERROR”,token); //输出错误符号
}
}
fclose(fin);//关闭输入输出文件
fclose(fout);
return(es); //返回主程序
}
//语法、语义分析及代码生成
//插入符号表动作@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;
datap++;//分配一个单元,数据区指针加1
vartablep++;
return(es);
}
//查询符号表返回地址
int lookup(char *name,int *paddress)
{
int i,es=0;
for(i=0;i《vartablep;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打开%s错误!/n”,Scanout);
es=10;
return(es);
}
printf(“请输入目标文件名(包括路径):”);
scanf(“%s”,Codeout);
if((fout=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”,Scanout);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;
}
fclose(fp);
fclose(fout);
return(es);
}
//program::={《declaration_list》《statement_list》}
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(“ 符号表/n”);
printf(“ 名字 地址/n”);
for(i=0;i《vartablep;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);
}
//《declaration_list》::=
//《declaration_list》《declaration_stat》|《declaration_stat》
//改成《declaration_list》::={《declaration_stat》}
int declaration_list()
{
int es=0;
while (strcmp(token,“int”)==0)
{
es=declaration_stat();
if (es》0) return(es);
}
return(es);
}
//《declaration_stat》↓vartablep,datap,codep -》int ID↑n@name-def↓n,t;
int declaration_stat()
{
int es=0;
fscanf(fp,“%s %s/n”,&token,&token1);printf(“%s %s/n”,token,token1);
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);
}
//《statement_list》::=《statement_list》《statement》|《statement》
//改成《statement_list》::={《statement》}
int statement_list()
{
int es=0;
while (strcmp(token,“}”))
{
es=statement();
if (es》0) return(es);
}
return(es);
}
//《statement》::= 《if_stat》|《while_stat》|《for_stat》
// |《compound_stat》 |《expression_stat》
int statement()
{
int es=0;
if (es==0 && strcmp(token,“if”)==0) es=if_stat();//《IF语句》
if (es==0 && strcmp(token,“while”)==0) es=while_stat();//《while语句》
if (es==0 && strcmp(token,“for”)==0) es=for_stat();//《for语句》
//可在此处添加do语句调用
if (es==0 && strcmp(token,“read”)==0) es=read_stat();//《read语句》
if (es==0 && strcmp(token,“write”)==0) es=write_stat();//《write语句》
if (es==0 && strcmp(token,“{”)==0) es=compound_stat();//《复合语句》
if (es==0 && (strcmp(token,“ID”)==0||strcmp(token,“NUM”)==0||strcmp(token,“(”)==0)) es=expression_stat();//《表达式语句》
return(es);
}
//《IF_stat》::= if (《expr》) 《statement 》 [else 《 statement 》]
/*
if (《expression》)@BRF↑label1 《statement 》 @BR↑label2 @SETlabel↓label1
[ else 《 statement 》] @SETlabel↓label2
评论
查看更多