语义分析实验报告Word格式文档下载.docx
《语义分析实验报告Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《语义分析实验报告Word格式文档下载.docx(9页珍藏版)》请在冰豆网上搜索。
五、结果及分析8
一、实验目的
进一步理解递归下降分析原理和实现方法,理解语义分析的基本机制,掌握语义子程序的构造方法。
二、实验内容
将带变量声明的表达式翻译为四元式序列,其中包括以下要求:
非终结符号D实现定义两种类型int,real变量的声明;
非终结符号S实现变量之间的*,+,:
=(赋值运算)
两个关键字int和real
变量之间的*,+,:
=(赋值)运算只能使用声明过的变量,所以要检查使用的变量是否声明过。
对每个*,+,:
=(赋值)运算生成一条四元式如(*,A,B,T1),其中T1是临时变量
*优先级别高于+,*满足左结合规则
三、源程序分析
这是一个简单的包含词法、语法、语义分析的程序:
语义分析.h和语义分析.cpp。
实现的基本原理是自顶向下分析,单遍扫描,以语法分析为核心,调用词法分析,并实现语义分析。
1、程序采用的BNF
P→DS.
D→B;
D
D→ε
B→intL|realL
L→id|L,id
S→V:
=EH
H→;
S|ε
E→E+T|T
T→T*F|F
F→(E)
F→id
V→id
消除左递归之后的等价文法
start→DS.
L→idA
A→,idA
A→ε
E→TR
R→+TR
R→ε
T→FP
P→*FP
P→ε
2、根据语义要求得到对应的翻译模式
D→B;
B→intL{L.type:
=int}|realL{L.type:
=real}
L→id{A.Type:
=L.typeenter(v.entry,L.type)}A
A→,idA{A1.Type:
=A.typeenter(v.entry,A.type)}
=E{gen("
:
="
E.place,0,V.place)}H
E→T{R.i:
=T.place}R{E.place:
=R.s}
R→+T{R1.i:
=newtemp;
gen("
+"
R.i,T.place,R1.i)}R{R.s:
=R1.s;
}
R→ε{Rs=R.i}
T→F{P.i:
=F.place}P{T.place:
=P.s}
P→*F{p1.i:
*"
P.i,F.place,T)}P{P.s:
=p1.s;
P→ε{P.s=P.i}
F→(E){F.place:
=E.place}
F→id{F.place:
=position(id)}
V→id{V.place:
=position(id)}
3、实现原理
基于翻译模式的自上而下语义处理(翻译)
1.对每个非终结符A,构造一个函数,以A的每个继承属性为形参,以A的综合属性为返回值(若有多个综合属性,可返回记录类型的值)。
如同预测分析程序的构造,该函数代码的流程是根据当前的输入符号来决定调用哪个产生式。
2.与每个产生式相关的代码根据产生式右端的终结符,非终结符,和语义规则集(语义动作),依从左到右的次序完成下列工作:
(1)对终结符X,保存其综合属性x的值至专为X.x而声明的变量;
然后调用匹配终结符(match_token)和取下一输入符号(next_token)的函数;
(2)对非终结符B,利用相应于B的函数调用产生赋值语句c:
=B(b1,b2,…,bk),其中变量b1,b2,…,bk对应B的各继承属性,变量c对应B的综合属性
(3)对语义规则集,直接copy其中每一语义规则(动作)来产生代码,只是将对属性的访问替换为对相应变量的访问。
4、文法的属性分析
文法符号
属性
综合或继承
含义
start
无
D
B
L
L.type
继承
类型
A
A.type
S
E
E.place
综合
指向变量或临时变量的指针(用整数实现)
R
R.i
同上
R.s
T
T.place
P
P.i
P.s
F
F.place
V
V.place
5、过程设计
intgetsym();
//读一个单词
voidenter(enumsymboltype);
//登记符号表
voidinit();
intposition(char*idt);
//查询符号表用函数,返回在符号表中位置
intgen(enumsymbolop,intarg1,intagr2,intresult);
//生成四元式
voidnewtemp()//申请临时变量
voidstart();
voidD();
voidB();
voidL(enumsymboltype);
voidA(enumsymboltype);
voidS();
voidH();
intE();
intR(intRi);
intT();
intP(intpi);
intF();
intV();
6、子程序说明
init():
初始化函数,主要是用于把单字符(例如:
+、-、*、/)赋值一个symbol。
getsym():
把文件中的一个字符或者一个字符串分类成各种类型,用sym表示。
enter():
把声明过的变量保存到table[tx]这个结构体数组中。
position():
查找名字的位置,找到则返回在名字表中的位置,否则返回0。
gen():
生成中间代码,通过传来的参数生产四元式。
start():
开始对整个文件的语法语义经行分析。
D()、B()、L()、A():
实现变量的声明,并把变量的类型和名字保存到table[tx]这个结构体数组中。
S()、H()、E()、T()、P()、R()、F()、V():
实现后面程序运算语句的检查,并生成中间代码;
其中:
S()是检验赋值运算;
H()是执行下一条运算语句;
E()分析赋值号后面的运算;
R()是实检验+运算;
P()是检验*、/运算;
F()是实现*、/运算的优先级高于+运算,并获得当前位置的ID;
V()获得当前位置的ID。
四、设计的基本思想(包括修改之后的属性文法、属性类型分析、翻译模式)
按照扩展要求分析:
1、增加除法运算
*,/优先级别高于+,*和/满足左结合规则
对包含除法运算的表达式生成对应的四元式
(1)、可以在翻译模式中非终结符P增加一个产生式:
P—>
/F{p1.i:
/"
P.i,F.place,T)}P{P.s:
},
这样就在翻译模式中增加了‘/’运算;
(2)、在程序中的P()函数里面模仿‘*’运算,增加相应的分析语句:
if(sym==divid){
getsym();
Fplace=F();
tv=tv+1;
gen(divid,pi,Fplace,tv);
Ps=P(tv);
(3)、在gen()函数里模仿*运算,增加相应的四元式输出语句:
if(op==divid)///运算
{
fprintf(fout,"
(/,%s,%s,%s)"
temp1,temp2,temp3);
printf("
这样就在程序中增加了‘/’运算的分析要求。
2、禁止同名重复声明
所以登记符号之前要检查有没有同名变量声明过。
因为table[tx]数组就是存放声明变量名和类型的结构体数组,可以在enter()这个存放声明变量的函数中,增加相应检验变量名重复的函数:
for(inti=1;
i<
txmax;
i++){/*检查变量是否重名*/
if(strcmp(id,table[i].name)==0){
printf("
错误4:
变量名重复.\n"
);
exit(0);
}
}
每次要把一个变量加入到table[tx]数组中都要检验变量名是否跟table[tx]数组中已有的变量名重复,重复就报错,并跳出程序。
这样就在程序中增加了检查重复变量名的功能。
五、结果及分析
1、运行的文件a.txt内容为:
reala,b;
intc,d;
c:
=c+d*b;
d:
=b*a.
运行结果为:
2、运行文件a.txt的内容为:
intc,d,a;
3、运行文件a.txt的内容为:
f:
运行的结果为:
从以上三个结果(一个正确,两个错误)来看,完全实现了扩展要求的两个功能,也完全符合定义的语法语义规则。