语义分析实验报告(实验三).doc
《语义分析实验报告(实验三).doc》由会员分享,可在线阅读,更多相关《语义分析实验报告(实验三).doc(13页珍藏版)》请在冰豆网上搜索。
编译原理语义分析实验报告
软工082班
兰洁
200831104044
一、实验内容
二、实验目的
三、实验要求
四、程序流程图
五、程序代码与主要过程说明
六、测试用例
七、输出结果
八、实验心得
一、实验内容
定义模拟的简单语言的语义成分,将语义分析程序编制成一个子程序,在实验2分析出个语法单位后,分析其含义,并将可执行语句或表达式翻译成四元式输出,并将错误信息输出。
二、实验目的
通过上机实验,加深对语义制导翻译原理的理解,掌握将语法分析所识别的语法成分变换成为中间代码的语义翻译方法。
三、实验要求
采用递归下降语法制导翻译方法,对算术表达式、赋值语句进行语义分析并生成四元式序列。
例如:
对于语句串
Function
a=2+3*4;
x=(a+b)/c;
endfunc
#
输出的三地址指令如下
lt1=3*4
lt2=2+t1
la=t2
lt3=a+b
lt4=t3/c
lx=t4
四、程序流程图
由于语义分析的的方法就是在语法分析过程中,根据每个产生式所对应的语义子程序进行翻译,为每个产生式配上一个翻译子程序,并在语法分析的同时执行这些子程序。
所有对应的流程图与语法分析流程图大同小异,关于各类函数的流程图我已经在词法分析报告与语法分析报告中详细画出,所以这里只说明程序主要流程。
五、程序代码与主要过程说明
/*语义分析源代码*/
#include
#include
#include
#include
#include
structquad//四元式表
{ charresult[12];
charag1[12];
charop[12];
charag2[12];
};
structquadquad[30];
intcount=0;
char*expression(void);
charprog[200],token[9];
charch;
intsyn,p,m,n,sum=0;
intkk=0,k=0;
char*rwtab[6]={"function","if","then","while","do","endfunc"};
voidscaner()
{ m=0;
for(n=0;n<8;n++)
token[n]='\0';
ch=prog[p++];
while(ch=='')
ch=prog[p++];
if((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z'))
{
while((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')||(ch>='0'&&ch<='9'))
{ token[m++]=ch;
ch=prog[p++];
}//endofwhile
token[m++]='\0';
p--;
syn=10;
for(n=0;n<6;n++){
if(strcmp(token,rwtab[n])==0)
{ syn=n+1;
break;}
}//endoffor
}
elseif(ch>='0'&&ch<='9')
{ sum=0;
while(ch>='0'&&ch<='9')
{sum=sum*10+ch-'0';
ch=prog[p++];
}
p--;
syn=11;
}
else
{ switch(ch)
{ case'<':
m=0;token[m++]=ch;
ch=prog[++p];
if(ch=='=')
{ syn=22;
token[m+1]=ch;
}
else
{ syn=20;
ch=prog[--p];}
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+1]=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;
}
}//endofscaner
}
voidemit(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;
}
char*newtemp()//返回临时变量t1,t2...
{char*p;
charm[8];
p=(char*)malloc(8);
k++;
itoa(k,m,10);//功能将整数装换为字符串。
并将值保存在m中。
10是基数表示将k的值转化为10进制数。
strcpy(p+1,m);
p[0]='t';
return(p);
}
char*factor()
{ char*fplace;
fplace=(char*)malloc(12);
strcpy(fplace,"");
if(syn==10)
{ strcpy(fplace,token);
scaner();
}
elseif(syn==11)
{ itoa(sum,fplace,10);
scaner();
}
elseif(syn==27)
{ scaner();
fplace=expression();
if(syn==28)
scaner();
else
{ printf("\n')'ERROR");
kk=1;
}
}
else
{ printf("\n'('ERROR");
kk=1;
}
return(fplace);
}
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';}
elseif(syn==16)
{ tt[0]='/';
tt[1]='\0';}
scaner();
strcpy(ep2,factor());
strcpy(tp,newtemp());//tp为临时变量
emit(tp,eplace,tt,ep2);//将三地址代码送到四元式表
strcpy(eplace,tp);
}
return(eplace);
}
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());
while(syn==13||syn==14)
{ if(syn==13)
{ tt[0]='+';
tt[1]='\0';
}
elseif(syn==14)
{ tt[0]='-';
tt[1]='\0';
}
scaner();
strcpy(ep2,term());
strcpy(tp,newtemp());
emit(tp,eplace,tt,ep2);//
strcpy(eplace,tp);
}
return(eplace);
}
statement()
{ chartt[8],eplace[8];
intschain=0;
switch(syn)
{case10:
strcpy(tt,token);
scaner();
if(syn==18){
scaner();
strcpy(eplace,expression());
emit(tt,eplace,"","");
schain=0;}
else
{ printf("\n缺少赋值语句\n");
kk=1;}
break;
}
return(schain);}
yucu()
{ intschain=0;
schain=statement();//进行语句分析
while(syn==26)//一个语句识别结束,继续识别
{ scaner();
schain=statement();
}
return(schain);
}
irparser()//在原来语法分析的基础上插入相应的语义动作,据每个产生式所对应的语义子程序进行翻译,为每个产生式配上一个翻译子程序,并在语法分析的同时执行这些子程序即将输入串翻译成四元式序列。
{intschain=0;
kk=0;
if(syn==1)
{scaner();
schain=yucu();
if(syn==6)
{ 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);
}
voidmain()
{ inti;
p=0;
printf("请输入语句(以#结束,不要换行):
");
do
{ ch=getchar();
prog[p++]=ch;
}while(ch!
='#');
p=0;
printf("种别码单词符号\n");
do
{ scaner();
switch(syn)
{
case11:
printf("%-3d%d\n",syn,sum);break;
case-1:
printf("词法分析失败,程序终止!
\n");return;
default:
printf("%-3d%s\n",syn,token);
}
}while(syn!
=0);
printf("词法分析成功,按任意键进行语法,语义分析");
getch();p=0;
scaner();
irparser();
if(kk!
=0)
{ printf("词法分析失败,程序终止!
");
return;
}
printf("\n三地址指令如下:
\n");
for(i=0;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();
return;
}
六、测试用例
测试用例1
输出结果
测试用例2
输出结果
function
a=1;
b=2;
c=a+b;
endfunc
#
种别码单词符号
1function
10a
18=
111
26;
10b
18=
112
26;
10c
18=
10a
13+
10b
26;
6endfunc
0#
词法分析成功,按任意键进行语法,语义分析
语法,语义分析成功
三地址指令如下:
a=1b=2t1=a+bc=t1
function
x=(a+b)/c;
b=1+2*c;
endfunc#
种别码单词符号
1function
10x
18=
27(
10a
13+
10b
28)
16/
10c
26;
10b
18=
111
13+
112
15*
10c
26;
6endfunc
0#
词法分析成功,按任意键进行语法,语义分析
语法,语义分析成功
三地址指令如下:
t1=a+bt2=t1/cx=t2t3=2*ct4=1+t3b=t4
七、输出结果
用例一
用例二
八、实验心得
通过编译原理实验三语义分析实验,使得自己对语义分析的语法制导翻译以及三地址代码的四元式表现方式有了更深刻的了解,虽然源代码并非由自己设计,但是在调试程序的过程中,逐步理解程序递归下降语法制导思想,也掌握了将语法分析所识别的语法成分变换为中间代码的语义翻译方法,受益匪浅。
通过试验结果可以看出,这个程序实现了输出为三地址指令形式的四元式序列。