了解编译程序中LR分析表的作用以及语义加工程序的功能。
在掌握编译原理的基础上,对编译程序实例进行分析,通过编译程序的运行,检验编译程序输出结果的正确性。理论联系实际,将所学知识用到实处,进而学会怎么写编译程序。
(1)验证下述程序输出结果的正确性:
while (a>b) do
begin
if m>=n then a:=a+1
else
while k=h do x:=x+2;
m:=n+x*(m+y)
end#~
(2)自行设计一程序进行正确性验证,并按二元式序列的注释及状态栈STACK加工分析对应的符号栈内容。
掌握LR分析表的设计方法和语义加工程序的扩充。
参照表达式LR分析表的设计方法,设计扩充后的算术表达式LR分析表,并对原语义加工程序进行修改,加入新添加的内容。
(1)算术表达式文法扩充如下:
E->E+E|E-E|E*E|E/E|(E)|i
试根据该文法添加单词“-”,“/”的内部定义以及重新设计LR分析表,并修改语义加工程序,最后验证修改的结果。
(2)待验证程序:
begin
a:=a+b-c*d/e;
while a while b while d if a end#~ 在实验一中已给出编译程序的全部代码,且能识别加、乘算数表达式。而本实验只需根据识别加、乘算数表达式的设计方法来对算数表达式进行扩充以实现对减、除算数表达式的识别及分析。 (1)添加关键字减、除运算符的种别代码 #define sub 35 /* - */ #define div 37 /* / */ (2)重新构造算数表达式的LR分析表 static int action1[14][9]={ {3,-1,-1,-1,-1,2,-1,-1,1}, {-1,4,10,5,11,-1,-1,ACC,-1}, {3,-1,-1,-1,-1,2,-1,-1,6}, {-1,104,104,104,104,-1,104,104,-1}, {3,-1,-1,-1,-1,2,-1,-1,7}, {3,-1,-1,-1,-1,2,-1,-1,8}, {-1,4,10,5,11,-1,9,-1,-1}, {-1,101,101,5,11,-1,101,101,-1}, {-1,102,102,102,102,-1,102,102,-1}, {-1,103,103,103,103,-1,103,103,-1}, {3,-1,-1,-1,-1,2,-1,-1,12}, {3,-1,-1,-1,-1,2,-1,-1,13}, {-1,105,105,5,11,-1,105,105,-1}, {-1,106,106,106,106,-1,106,106,-1} }; (3)在扫描算法scan中增加对减、除运算符的识别 case '-': buf[count].sy1=sub; /* - */ count++; break; case '/': buf[count].sy1=div; /* / */ count++; break; (4)实现对减、除算术表达式的规约 case 105: E.pos=newtemp(); gen("-",sstack[ssp-2],sstack[ssp],E.pos+100); ssp=ssp-2; sstack[ssp].sy1=tempsy; sstack[ssp].pos=E.pos; sp1=sp1-3; break; case 106: E.pos=newtemp(); gen("/",sstack[ssp-2],sstack[ssp],E.pos+100); ssp=ssp-2; sstack[ssp].sy1=tempsy; sstack[ssp].pos=E.pos; sp1=sp1-3; break; (5)在测试字符是否是表达式中的值的test算法中增加对减、除运算符的识别 case sub: case div: return 1; default: return 0; 通过添加新的程序语句,全面了解一个语句的编译程序设计过程。 对添加的语句设计LR分析表及相应的处理程序,并将其添加到程序语句处理语句中。 (1)将计数循环for语句的功能添加到编译程序中。For语句的文法及每个产生式相应的语义子程序如下: F1→for i:=E(1) {GEN(:=,E(1).PLACE,_,ENTRY(i); F1.PLACE:=ENTRY(i); F1.CHAIN:=NXQ; GEN(j,_,_,0); F1·QUAD:=NXQ} F2→F1 step E(2) {F2.QUAD:=F1.QUAD; F2.PLACE:=F1.PLACE; GEN(+,F1.PLACE,E(2).PLACE,F1.PLACE); BACKPATCH(F1.CHAIN,NXQ)} F3→F2 until E(3) {F3.QUAD:=F2.QUAD; q:=NXQ; GEN(j≤,F2.PLACE,E(3).PLACE,q+2); F3.CHAIN:=NXQ; GEN(j,_,_,0)} S→F3 do S(1) {先形成S(1)相应的四元式序列; GEN(j,_,_,F3.QUAD); BACKPATCH(S(1).CHAIN,F3.QUAD); S.CHAIN:=F3.CHAIN} (2)待验证程序: begin for a:=1 to 8 do begin if m>=n then a:=a-1 else while k=h do x:=x+2; m:=n+x/(m-y); end end#~ (1)实现时可将for语句的文法设计为一个LR分析表,然后将该文法的开始符看作程序语句LR分析表中的一个终结符,即像赋值语句一样处理(当然仍要重新设计程序语句的LR分析表)。另一种方法就是直接将for语句的文法纳入到程序语句文法中(即像if和while语句一样处理),并重新设计程序语言的LR分析表。 (2)for语句中产生式的语义动作需要参考编译程序中对if和while语句的处理部分做相应修改。2.4算法设计
实验3 添加新的程序语句
3.1实验目的
3.2实验要求
3.3实验内容
3.4实验说明