#include
#include
#include
#include
#include
struct quad
{
char result[12];
char ag1[12];
char op[12];
char ag2[12];
};
struct quad quad[30];
int count=0;
char *expression(void);
char prog[200],token[9];//function长度为8,加上'\0',所以数组最小大小应该为9
char ch;
int syn,p,m,n,sum=0;
int kk=0,k=0;
char *rwtab[6]={"function","if","then","while","do","endfunc"};
//数据单位:eg:123,ad,(,*,+,a1;
void scaner()
{
m=0;
ch=prog[p++];//ch为读入第一个数据(一个新的字符串中第一个数据,并不代表整个文本第一个数据)
for(n=0;n<8;n++)//初始化token数组
token[n]='\0';
while(ch==' ')
ch=prog[p++]; //跳过空格
if((ch>='a' && ch<='z')||(ch>='A' && ch<='Z'))//如果读入的第一个数据为字符 (字符串先存放在token数组中)
{
while((ch>='a' && ch<='z')||(ch>='A' && ch<='Z')||(ch>='0'&&ch<='9'))
{
token[m++]=ch;//暂时存放在token数组中
ch=prog[p++];
}//字符串
token[m++]='\0';
p--;//使得prog[p]被ch读入的最后一个字符
syn=10;//用来区分输入数据类型
for(n=0;n<6;n++)
{
if(strcmp(token,rwtab[n])==0)//判断读入字符串是否为程序中定义的特殊字符串
{
syn=n+1;//function:1,if:2,then:3,while:4,do:5,endfunc:6
break;
}
}
}
else if(ch>='0' && ch<='9')//读入第一个数据为数字(读入为数字,直接经过sum运算,结果存放在sum中)
{
sum=0;
while(ch>='0' && ch<='9')
{
sum=sum*10+ch-'0';//将输入数字转换成10进制数
ch=prog[p++];
}
p--;//使得prog[p]被ch读入的最后一个数字
syn=11;//若为数字,则,syn为11
}
else switch(ch)//读入第一个数据为运算符(运算符先存放在token数组中)
{
case '<':
m=0;token[m++]=ch;//token[0]='<',m=1
ch=prog[++p];//ch取下一个数据
if(ch=='=')//<=
{
syn=22;
//token[m+1]=ch;这一句的意思是token[2]=ch,错误,修改如下
token[m++]=ch;//token[1]='='
}
else//<
{
syn=20;
ch=prog[--p];//ch='<'
}
break;
case '>':
m=0;token[m++]=ch;
ch=prog[++p];
if(ch=='=')
{
syn=24; token[m++]=ch;
}
else
{
syn=23; ch=prog[--p];
}
break;
case '=':
m=0;token[m++]=ch;
ch=prog[++p];
if(ch=='=')
{
syn=25; token[m++]=ch;
}
else
{
syn=18; ch=prog[--p];
}
break;
case '!':
m=0;token[m++]=ch;
ch=prog[++p];
if(ch=='=')
{
syn=22; token[m++]=ch;
}
else syn=-1;
break;
case '+':syn=13;token[0]=ch;break;
case '-':syn=14;token[0]=ch;break;
case '*':syn=15;token[0]=ch;break;
case '/':syn=16;token[0]=ch;break;
case ';':syn=26;token[0]=ch;break;
case '(':syn=27;token[0]=ch;break;
case ')':syn=28;token[0]=ch;break;
case '#':syn=0;token[0]=ch;break;
default:syn=-1;
}
}
/*该函数的功能是生成一个三地址语句送到四元式表中。*/
void emit(char *result,char *ag1,char *op,char *ag2)
{
strcpy(quad[count].result,result);
strcpy(quad[count].ag1,ag1);
strcpy(quad[count].op,op);
strcpy(quad[count].ag2,ag2);
count++;
return;
}
/*该函数回送一个新的临时变量名,临时变量名产生的顺序为t1,t2,…*/
char *newtemp()
{
//k初值为0
char *p; char m[8];
p=(char *)malloc(8);
k++;//假设第一次调用该函数,此时k=1;
itoa(k,m,10);//m=1;
strcpy(p+1,m);//把m的值复制到p指针指向的地址后面一个字节开始的内存中,p[1]=1
p[0]='t';
return(p);
}
/*factor函数,检查是否标识符,如果是,调用scaner函数,
如果不是,检查是否是数值,
如果是,调用scaner函数,
如果不是,检查是否是'(',
如果不是,进行出错处理,
如果是,调用scaner函数,再调用expression()函数,返回后检查是否是')',
如果不是,进行出错处理,如果是,调用scaner函数,返回*/
char *factor(void)
{
char *fplace;
fplace=(char *)malloc(12);
strcpy(fplace," ");//初始化fplace
if(syn==10)//该数据单位为字符串
{
strcpy(fplace,token);//将该字符串赋值给fplace
scaner();//获取下一个数据单位
}
else if(syn==11)//该数据单位为数字
{
itoa(sum,fplace,10);//将sum的值以10进制的形式存放在fplace中
scaner();//获取下一个数据单位
}
else if(syn==27)//该数据单位为(
{
scaner();//获取下一个数据单位
fplace=expression();//调用expression(其实就是获取完下一个数据单位后,在factor函数中对其分析,当下一个数据单位不为(,获取下一个数据单位,且执行下一句)
if(syn==28)//如果下一个数据单位为')'
scaner();//直接获取下一个数据单位
else
{
printf("\n')'错误");
kk=1; //标志
}
}
else
{
printf("\n')'错误");
kk=1;
}
return (fplace);//返回数据单位的内容,如果是(,则返回(后面一个数据单位的内容
}
/*term()函数的作用是判断输入的是否是由'*''/'连接成的因式,并将对应的四元式保存并输出*/
char *term(void)
{
char *tp,*ep2,*eplace,*tt;
tp=(char *)malloc(12);
ep2=(char *)malloc(12);
eplace=(char *)malloc(12);
tt=(char *)malloc(12);
strcpy(eplace,factor());//调用factor,eplace为上一个数据单位的内容
while(syn==15||syn==16)//该数据单位为'*'或者'/'
{
if(syn==15)//如果为'*'
{
tt[0]='*'; tt[1]='\0';//tt存放该数据单位的内容
}
else if(syn==16)//如果为'/'
{
tt[0]='/'; tt[1]='\0';//tt存放该数据单位的内容
}
scaner();//获取下一个数据单位
strcpy(ep2,factor());//调用factor()函数,并将函数返回值赋值给ep2(字符串,数字,'(',出错)
strcpy(tp,newtemp());//调用newtemp()函数,将该函数返回值赋值给tp,tp为临时变量名
emit(tp,eplace,tt,ep2);//调用emit函数,生成一个三地址语句存放在四元式表中
strcpy(eplace,tp);//eplace为四元式
}
return(eplace);
}
char *expression(void)
{
char *tp,*ep2,*eplace,*tt;
tp=(char *)malloc(12);
ep2=(char *)malloc(12);
eplace=(char *)malloc(12);
tt=(char *)malloc(12);
strcpy(eplace,term());//调用term函数,将四元式的内容赋值给eplace
while(syn ==13 || syn==14) //当它不为*或者/时,接着判断是否为+或者-
{
if(syn==13)
{
tt[0]='+';
tt[1]='\0';
}
else if(syn==14)
{
tt[0]='-'; tt[1]='\0';
}
scaner();
strcpy(ep2,term());
strcpy(tp,newtemp());
emit(tp,eplace,tt,ep2);
strcpy(eplace,tp);
}
return(eplace);//返回对应四元式的值
}
int statement()
{
char tt[8],eplace[8];
int schain=0;
switch(syn)
{
case 10: strcpy(tt,token);//若第二个数据单位的syn为10,即字符串(as1),将第二个数据单位的内容复制给tt
scaner();//再取下一个数据单位,并获得该数据单位的syn
if(syn==18)//第三个数据单位为'='
{
scaner();//再取下一个数据单位,并获得该数据单位的syn(第四个数据单位)
strcpy(eplace,expression());//调用expression,如果为+或者-,返回对应四元式的值,如果为*或者/,则返回其四元式的值
emit(tt,eplace," "," ");
schain=0;
}
else
{
printf("\n缺少赋值句\n"); kk=1;
}
break;
}
return(schain);
}
int yucu()
{
int schain=0;
schain=statement();//调用statement()函数,
while(syn==26)//该数据单位为;
{
scaner();
schain=statement();
}
return(schain);
}
int lrparser()
{
int schain=0; kk=0;
if(syn==1)//输入数据为function
{
scaner();//因为p停留在上一次扫描结束的地方,所以再次调用该函数ch可以获取下一个数据单位,得到该数据单位的syn
schain=yucu();//调用yucu()函数
if(syn==6)//endfunc
{
scaner();
if(syn==0 && kk==0)//#
printf("\n语法,语义分析成功!");
}
else
{
if(kk!=1)
{
printf("\n缺endfunc\n"); kk=1;
}
}
}
else
{
printf("\n缺少function\n");
kk=1;
}
return(schain);
}
void main()
{
int i; p=0;
FILE *fp;
//if((fp=fopen("D:\\6.txt","r"))==NULL)
if((fp=fopen("E:\\编译原理期末代码\\36.txt","r"))==NULL)
{
printf("\n 文件打开失败:\n");
exit(0);
}
do{
ch=fgetc(fp);
prog[p++]=ch;
}while(ch!='#'); //将输入字符串赋值到prog数组
p=0; //使得ch从第一个字符开始获取
printf("种别码 单词符号\n");
do{
scaner(); //扫描输入的数据,并作出类型判断(以字符串为单位)
switch(syn)
{
case 11: printf("%-3d %d\n",syn,sum); break; //输入为数字,打印出它的syn与大小
case -1: printf("词法分析失败,程序终止!\n"); return; //输入数据不正确
default: printf("%-3d %s\n",syn,token); //字符串,运算符
}
}while(syn!=0);//读入所有输入的数据(只是判断输入数据是否正确,并没有进行语法,语义分析操作)
printf("词法分析成功,按任意键进行语法、语义分析");
getch();//按任意键,程序往下执行
p=0;//词法分析后,重新对ch赋值,使得ch从第一个字符开始获取
scaner();//扫描第一个单位,判断其类型
lrparser();//将将第一个输入字符串翻译为四元式
if(kk!=0)
{
printf("语法分析失败,程序终止!");
return;
}
printf("\n三地址指令如下:\n");
for(i=0;i {
printf("%s=",quad[i].result);
printf("%s",quad[i].ag1);
printf("%s",quad[i].op);
printf("%s\n",quad[i].ag2);
}
getch();
return;
}