编译原理第三次上机报告.docx
- 文档编号:23843729
- 上传时间:2023-05-21
- 格式:DOCX
- 页数:14
- 大小:29.28KB
编译原理第三次上机报告.docx
《编译原理第三次上机报告.docx》由会员分享,可在线阅读,更多相关《编译原理第三次上机报告.docx(14页珍藏版)》请在冰豆网上搜索。
编译原理第三次上机报告
一、实验题目:
语义分析
二、实验目的
通过上机实习巩固上课所学的语义分析方面的知识。
通过理论与实践结合的过程强化编程能力。
通过从词法分析->语法分析->语义分析(生成三地址码)的过程,进一步体会编译的原理。
加深对语法制导翻译原理的理解,掌握将语法分析说识别的语法成分变换为中间代码的语义翻译方法。
三、实验要求
采用递归下降语法制导翻译法,对算术表达式、赋值语句进行语义分析并生成是元式序列。
文法结构定义如下:
〈程序〉∷=main()〈语句块〉.
〈语句块〉∷=‘{’〈语句串〉’}’
〈语句串〉∷=〈语句〉{;〈语句〉};
〈语句〉∷=〈赋值语句〉
〈赋值语句〉∷=ID=〈表达式〉
〈表达式〉∷=〈项〉{+〈项〉|-〈项〉}
〈项〉∷=〈因子〉{*〈因子〉|/〈因子〉}
〈因子〉∷=ID|NUM|(〈表达式〉)
〈关系运算符〉∷=<|<=|>|>|>=|==|!
=
试验的输入和输出:
输入是语法分析后提供的正确的单词串,输出为三地址指令形式的四元式序列。
例如:
对于语句串
begina:
=2+3*4;x:
=(a+b)/cend#
输出的三地址指令如下:
(1)t1=3*4
(2)t2=2+t1
(3)a=t2
(4)t3=a+b
(5)t4=t3/c
(6)x=t4
算法思想:
(1)设置语义过程
①emit(char*result,char*ag1,char*op,char*ag2)
该函数的功能是生成一个三地址语句送到四元式表中。
四元式表的结构如下:
struct
{
char*result;
char*ag1;
char*op;
char*ag2;
}quad[20];
②char*newtemp()
该函数回送一个新的临时变量名,临时变量名产生的顺序为体T1,T2,...。
char*newtemp()
{
char*p;
charm[8];
p=(char*)malloc(8);
k++;
itoa(k,m,10);
strcpy(p+1,m);
p[0]='t';
return(p);
}
四、试验流程图
五.实验代码
#include"stdafx.h"
#include
#include
#include
struct{char*result;char*ag1;char*op;char*ag2;}
quad[20];charprog[80];chartoken[8];charch;
intsyn,p,m,n,sum,kk,k;
char*rwtab[6]={"begin","if","then","while","do","end"};
voidscaner();
intlrparser();intyucu();intstatement();
char*term();char*expression();char*factor();
voidemit(char*,char*,char*,char*);char*newtemp()
{
char*p;
charm[8];
p=(char*)malloc(8);
k++;
itoa(k,m,10);
strcpy(p+1,m);
p[0]='t';
return(p);
}
voidemit(char*result,char*ag1,char*op,char*ag2)
{
inti;i=0;
while(quad[i].result!
=NULL)
i++;
quad[i].result=result;
quad[i].ag1=ag1;
quad[i].op=op;
quad[i].ag2=ag2;
printf("%s=%s%s%s\n",quad[i].result,quad[i].ag1,quad[i].op,quad[i].ag2);
}
intmain()
{
p=0;
printf("请输入字符串(以begin开始):
\n");
do{
ch=getchar();
prog[p++]=ch;
}
while(ch!
='#');
p=0;
do
{
scaner();
lrparser();
switch(syn)
{
case11:
printf("%d%\n",syn);break;
case-1:
printf("输入错误!
\n");break;
default:
printf("%d%\n",syn);
}
}
while(syn!
=0);return(0);
}
voidscaner()
{
intm=0;
for(n=0;n<8;n++)token[n]=NULL;
ch=prog[p++];
while(ch=='')
ch=prog[p++];
if((ch>=65&&ch<=90)||(ch>=97&&ch<=122))
{
while((ch>=65&&ch<=90)||(ch>=97&&ch<=122)||(ch>=48&&ch<=57))
{
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;
}
}
elseif(ch>=48&&ch<=57){
sum=0;
while(ch>=48&&ch<=57){
sum=sum*10+(ch-48);
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;
}
elseif(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[0]=ch;break;
case'/':
syn=16;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'#':
syn=0;token[0]=ch;break;
default:
syn=-1;
}
}
intlrparser()
{
intschain=0;
kk=0;
if(syn==1)
{
scaner();
schain=yucu();
if(syn==6)
{
scaner();
if(syn==0&&(kk==0))
printf("success\n");
}
else{if(kk!
=1)printf("endyoucuo!
\n");kk=1;}
}
else{printf("beginerror\n");kk=1;}
return(schain);
}
intyucu()
{
intschain=0;
schain=statement();
while(syn==26){
scaner();
schain=statement();
}
return(schain);
}
intstatement()
{
chartt[10],eplace[10];
intschain=0;
switch(syn){
case10:
strcpy(tt,token);
scaner();
if(syn==18){
scaner();
strcpy(eplace,expression());
emit(tt,eplace,"","");
schain=0;
}else{
printf("lack'=:
'");
kk=1;
}
return(schain);
}
}
char*expression()
{
char*tp,*ep2,*eplace,*tt;
tp=(char*)malloc(10);
ep2=(char*)malloc(10);
eplace=(char*)malloc(10);
tt=(char*)malloc(10);
strcpy(eplace,term());
while(syn==13||syn==14)
{
if(syn==13)
tt="+";
else
tt="-";
scaner();
strcpy(ep2,term());
strcpy(tp,newtemp());
emit(tp,eplace,tt,ep2);
strcpy(eplace,tp);
}
return(eplace);
}
char*term()
{
char*tp,*ep2,*eplace,*tt;
tp=(char*)malloc(10);
ep2=(char*)malloc(10);
eplace=(char*)malloc(10);
tt=(char*)malloc(10);
strcpy(eplace,factor());
while((syn==15)||(syn==16))
{
if(syn==15)strcpy(tt,"*");
elsestrcpy(tt,"/");
scaner();
strcpy(ep2,factor());
strcpy(tp,newtemp());
emit(tp,eplace,tt,ep2);
strcpy(eplace,tp);
}
returneplace;
}
char*factor()
{
char*fplace;
char*expression();
fplace=(char*)malloc(10);
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("')'error");
kk=1;
}
}
else
{
printf("'('error");
kk=1;
}
return(fplace);
}
六、心得体会:
说到本次实验,在此之前,对于编译我们的理解程度是知道词法分析,语法分析,语义分析三者之间的关系,从宏观上大概了解一个编译器的工作过程和工作原理。
每堂课都认真听讲,对于所讲的内容基本都能明白。
然而,当真正面对实验时,我们真正才感到我们只是明白其大概的工作原理,而具体实现上几乎没有什么思路。
正因如此,我们更加下定决心要把实验做好,要借这个机会把这个学期所学的东西真正掌握。
在把书上相关内容仔细看过几遍后,我们慢慢开始回想起了课堂上的东西,并慢慢把他们联系到了一起。
词法分析程序相对容易一些,书上相关的知识也不是太多,我们觉得主要是把状态转换图设计好,剩下的就是编程实现的问题了。
因此我们在设计它时花了很多的时间,从健壮性方面考虑,我们在程序中尽可能的考虑了可能出现的异常情况,并设计了能够定位错误位置,进行续编译的出错处理程序。
现在回想起来,如果不是词法分析中的出错处理程序相对完善,在语法、语义分析程序中的出错处理程序将更难实现。
在语法、语义程序中的输入方式不在需要单独考虑,具体的实现已经完全被封装到了词法分析对象中。
实验中我们真正体会到了书本上的理论知识与具体程序实现相联系的灵活性,尤其是在实验二中,体会更为深刻。
实验二/三中,书上所学的知识发挥了很大的作用,对于同一个实验任务,书上面提到了不同的实现方法,此外同学们还可以利用课外的知识来完成,可以说没有一个定式。
而针对不同的方法,在具体实践中会遇到不同的问题,比如我们是利用LL1自顶向下的分析方法来做的,并且使用的是递归子程序的方法,在实验中主要遇到的问题是语义规则的设计问题。
即使是面对同一个问题,不同的人根据自己的知识水平和编程能力,也会有不同的解决方法。
例如,我们上面谈到的关于二义性的消除问题的多种解决方法。
总而言之,整个实验的灵活性越强,就给了我们们越多发挥的空间,每个人根据自己的情况走一条最适合自己的路,但最终基本上都是殊途同归。
我们体会很深的是,在我们定好自己程序的方向开始一步一步实现时,每当遇到问题,我们就会认真地结合所学的知识来思考解决方案。
当问题解决后,我们基本上是把所涉及的知识都弄明白了。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 编译 原理 第三次 上机 报告