编译原理实验三-语义分析
一、实验目的
采用递归下降语法制导翻译法,对算术表达式、赋值语句进行语义分析并生成四元式序列。
二、实验要求
采用递归下降语法制导翻译法,对算术表达式,赋值语句进行语义分析并生成四元式序列。
1.实验的输入和输出
输入是语法分析提供的正确的单词串,输出为三地址指令形式的四元式序列。
例如:对于语句串
begin a:=2+3*4;x:=(a+b)/c end#
输出的三地址指令如下:
(1) t1=3*4
(2) t2=2+t1
(3) a=t2
(4) t3=a+b
(5) t4=t3/c
(6) x=t4
三、源程序
#include<stdio.h>
#include <stdlib.h>
#include<string.h>
#include <conio.h>
char prog[80],token[6];
int count=0;
char ch; /*当前读入单词*/
int syn,p,m,n,sum,kk=0,k=0; //p/*输入缓冲区指针*/
int length=0; //输入字符长度
int mark=0; /*标记注释//*/
int mark2;// 用于/* */ 注释
char * rwtab[6]={"begin","if","then","while","do","end"};
char *expression(void);
struct {
char result[8];
char ag1[8];
char op[8];
char ag2[8];
}quad[20];
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;
}
/*词法扫描程序:*/
scaner()
{
for(n=0;n<8;n++)
token[n]=NULL;
m=0;
ch=prog[p++];
while(ch==' ')ch=prog[p++];
if((ch<='z'&&ch>='a')||(ch<='Z'&&ch>='A'))
{
while((ch<='z'&&ch>='a')||(ch<='Z'&&ch>='A')||(ch<='9'&&ch>='0'))
{
token[m++]=ch;
ch=prog[p++];
}
token[m++]='\0';
ch=prog[--p];
syn=10;
for(n=0;n<6;n++)
if(strcmp(token,rwtab[n])==0)
{
syn=n+1;
break;
}
//break;
}
else
if((ch<='9'&&ch>='0'))
{
sum=0;
while((ch<='9'&&ch>='0'))
{
sum=sum*10+ch-'0';
ch=prog[p++];
}
ch=prog[--p];
syn=11;
}
else
switch(ch)
{
case '<':m=0;token[m++]=ch;
ch=prog[p++];
if(ch=='>')
{
syn=21;
token[m++]=ch;
}
else
if(ch=='=')
{
syn=22;
token[m++]=ch;
}
else
{
syn=20;
ch=prog[--p];
}
break;
case '>':token[m++]=ch;
ch=prog[p++];
if(ch=='=')
{
syn=24;
token[m++]=ch;
}
else
{
syn=23;
ch=prog[--p];
}
break;
case ':':token[m++]=ch;
ch=prog[p++];
if(ch=='=')
{
syn=18;
token[m++]=ch;
}
else
{
syn=17;
ch=prog[--p];
}
break;
case '+':syn=13;token[0]=ch;break;
case '-':syn=14;token[0]=ch;break;
case '*':
syn=15;
token[m++]=ch;
ch=prog[p++];
if (ch=='/')
{
mark2=1;
return scaner();
}
ch=prog[--p];
break;
case '/':
syn=16;
token[m++]=ch;
ch=prog[p++];
if (ch=='/')
{
mark=0;
while (mark==0)
{
scaner();
}
p++;
//mark=0;
}else if (ch=='*')
{
mark=1;
syn=30; ///**/
token[m++]='*';
mark2=0;
while(mark2==0)
{
scaner();
}
p++;
//mark2=0;
}
ch=prog[--p];
break;
case ':=':syn=18;token[0]=ch;break;
case '<>':syn=21;token[0]=ch;break;
case '<=':syn=22;token[0]=ch;break;
case '>=':syn=24;token[0]=ch;break;
case '=':syn=25;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 '\n':
syn = 29;
token[0] = ch;
mark = 1;
return scaner();
break;
case '#':syn=0;token[0]=ch;break;
case '\0':syn=1000;token[0]='\0';break;
default:syn=-1;
}
}
char *newtemp(void)
{
char *p;
char m[8];
p=(char *)malloc(8);
k++;
itoa(k,m,10);
strcpy(p+1,m);
p[0]='t';
return(p);
}
//factor分析函数
char * factor()
{
char *fplace;
fplace=(char *)malloc(12);
strcpy(fplace, " ");
if(syn==10)
{
strcpy(fplace,token);
scaner();
}
else if (syn==11)
{
itoa(sum,fplace,10);
scaner();
}
else
if(syn==27) //( 27
{
scaner();
fplace=expression();
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());
while(syn==15||syn==16)
{
if(syn==15)
{
tt[0]='*';
tt[1]='\0';
}
else if(syn==16)
{
tt[0]='/';
tt[1]='\0';
}
scaner();
strcpy(ep2,factor());
strcpy(tp,newtemp()); //tp为临时变量
emit(tp,eplace,tt,ep2); //将三地址代码送到四元式表
strcpy(eplace,tp);
//factor();
}
return (eplace);
}
//expression表达式分析函数
char * expression()
{
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());/*/调用term分析产生表达式计算的第二项ep2/*/
strcpy(tp,newtemp());/*/调用newtemp产生临时变量tp存储计算结果/*/
emit(tp,eplace,tt,ep2);/*/生成四元式送入四元式表/*/
strcpy(eplace,tp);
}
return (eplace);
}
//statement语句分析函数
statement()
{
//scaner();
int schain=0;
char tt[8],eplace[8];
if(syn==10)
{
strcpy(tt,token);
scaner();
if(syn==18) //:= 18
{
scaner();
strcpy(eplace,expression());
emit(tt,eplace," "," ");
schain=0;
//expression();
}
else
{
printf("赋号值错误!\n");
kk=1;
}
}
else
{
printf("语句错误\n");
//kk=1;
}
return (schain);
}
//语句串分析
yucu()
{
int schain=0;
schain=statement();
while(syn!=6&&p!=length-1&&syn!=0)
{
if(syn!=26)
scaner();
while(syn==26) //26==;
{
scaner();
if (syn!=0&&syn!=6)
{
schain=statement();
}
}
}
return (schain);
}
//递归下降分析程序
lrparser()
{
int schain=0;
scaner();
if(syn!=1)
{
printf("begin错误\n");
kk=1;
}else
scaner();
schain=yucu();
if (syn==6)
{
scaner();
if(kk==0)
printf("sucess");
}else{
if(kk!=1)
kk=1;
printf("缺少end\n");
}
return (schain);
}
void readFile(){
int i = 0;
char temp[255];
/*ifstream fin("data.txt");*/
FILE *fp=fopen("data.txt","r");
while ((temp[i]=fgetc(fp))!=EOF)
{
prog[i++]=temp[i];
}
length = i;
}
int main()
{
int i;
p=0;
readFile();
printf("\nplease intput string:");
do
{
ch=getchar();
prog[p++]=ch;
}while(ch!='#');
length=p;
//将程序保存在prog字符数组中
p=0;
printf("词法分析:\n");
do
{
scaner();
if (syn<1000/*&&syn!=100&&syn!=101*/)
{
printf("(%d,%s)\n",syn,token);
}
} while (syn<1000);
printf("\n\n");
printf("语法分析:\n");
p=0;
//scaner();
lrparser();
printf("\n");
printf("\n三地址指令如下:\n");
for(i=0;i<count;i++)
{
printf("%s=",quad[i].result); //t1= //x=
printf("%s",quad[i].ag1); //a //t1
printf("%s",quad[i].op); //+
printf("%s ",quad[i].ag2); //b
printf("\n");
}
getch();
}