WHILE循环语句的翻译程序设计递归下降法输出三地址表示.docx
《WHILE循环语句的翻译程序设计递归下降法输出三地址表示.docx》由会员分享,可在线阅读,更多相关《WHILE循环语句的翻译程序设计递归下降法输出三地址表示.docx(13页珍藏版)》请在冰豆网上搜索。
WHILE循环语句的翻译程序设计递归下降法输出三地址表示
WHILE循环语句的翻译程序设计
1问题描述
1.1实现思想:
本次设计用java高级语言,识别的是C语言的while循环语句的文法,通过良好的用户界面实现相应的输入和输出。
。
1.2语法分析器构造:
该程序的语法分析器能对输入的语法进行分析,判断输入语句能否满足while循环语句的文法。
通过递归下降的方法对语句进行分析,看能否通过开始符号推导出来。
1.3语义分析器构造:
该程序的语义分析器就是对分析结果进行输出,要求输出结果是三地址形式的。
2文法描述
2.1文法描述
:
:
=while(<条件表达式>)(<赋值语句>|)
2.2递归文法
while语句文法:
S->while(B)S|i=E
B->ErelopE
relop-><|=|>
E->E+E|E-E|E*E|E/E|(E)|i|n
在编写程序的时候用到的是递归下降法,而递归下降法对文法的要求是不能包含左递归,对上述的文法进行消除左递归之后,得到如下的递归文法:
S->while(B)S|i=E
B->ErelopE
relop-><|=|>
E->(E)F|iF|nF
F->+EF|-EF|*EF|/EF|ε
3语法分析方法描述
3.1实现思想
递归下降识别程序是由一组子程序组成,每个子程序对应于一个非终结符号(S,B,E,F,relop)。
该子程序处理相应句型中相对于此非终结符号的产生式。
在定义文法时,是递归定义的,所以这些子程序也是递归的。
当一个子程序调用另一个子程序时,总是先执行被调用的子程序,然后再执行后继的程序。
程序中5个子程序,其中S是开始符号,也是递归下降分析的入口,通过调用词法分析器进行单词分析,并通过Getsymbol()函数返回当前所分析到的单词,然后在递归语法分析中根据这个单词分析下一步要执行的子程序。
3.2具体设计
一下图示反映了在程序调用过程中,遇到终结符符时调用的函数次序,具体的步骤在概要设计时具体体现.(见下图):
4中间代码形式的描述
4.1三地址代码
在本程序中用到了三地址语句的输出包括以下的种类:
赋值语句:
x:
=yopz
复制语句:
x:
=y
条件转移语句:
ifxrelopygotoL
例如,本程序中语句while(B)S,可以输出三地址代码为:
ifBgotoLelsegotoLnext;
而E->(E)F可以输出三地址代码为:
E1:
=(E2)F。
4.2本程序中的三地址代码
S->while(B)S
L0:
=if(B)gotoL1elsegotoLnext
S->i=E
L:
=i=E
B->ErelopE
B:
=E1relopE2
relop-><
relop:
=<
relop->=
relop:
==
relop->>
relop:
=>
E->(E)F
E1:
=(E2)F
E->iF
E:
=IF
E->nF
E:
=nF
F->+EF
F1:
=+EF2
F->-EF
F1:
=-EF2
F->*EF
F1:
=*EF2
F->/EF
F1:
=/EF2
F->ε
F:
=ε
图2三地址代码
5概要设计
5.1简要分析
递归下降分析技术就是通过对每个非终结符编写一个子程序来实现它的操作,然后通过递归的调用来实现对输入字符串的分析,这其中还包括对输入字符串的词法分析。
在词法分析的时,得到的字符单词要和关键字比较,看是否是关键字,根据比较结果进行返回相应的单词类型。
单词类型主要包括变量,关键字,常量,各种符号等,每种符号都是一种类型。
在语法分析程序中,根据词法得到的结果,进行判断是否是当前需要的单词类型,如果不是就说明输入字符串不能由该文法推导出来;如果是当前需要的类型,就相应得做该单词类型分支程序。
根据文法可以得到这个递归下降程序可以分析包含有while嵌套的语句,在文法的开始符号S中就嵌套了S本身,因此这个文法的递归中就要考虑到while的自身嵌套。
在递归子程序中,在嵌套调用其他子程序时都是有一定条件的,当满足这个条件的时候该程序可以按照满足的条件执行下去,当没有满足程序中的条件时就会报错。
5.2程序的概要设计
在本程序中,Getsymbol()子程序就是对当前输入的字符串进行词法分析,包括对变量,常量,关键字,各种符号的分析。
主程序main()主要就是进行各种变量的初始化,调用递归分析程序的入口子程序。
子程序间的嵌套关系如下:
voidmain()
{S();}
voidGetsymbol(){…}
voidERROR(){…}
voidS()
{re=Getsymbol();
if(re==‘while’(关键字)){B();S();}
else(re==i(变量))
{re=Getsymbol();
if(re===)E();}}
voidB()
{E();relop();E();}
voidE()
{re=Getsymbol();
if(re==()
{E();re=Getsymbol();if(re==))F();}
elseif(re==i)F();
elseif(re==n)F();}
voidF()
{re=Getsymbol();
if(re==+){E();F();}
elseif(re==-){E();F();}
elseif(re==*){E();F();}
elseif(re==/){E();F();}}
6详细的算法描述(流程图或伪代码)
6.1文件及其相应函数构成
recursion.java------main()----------组织整个程序流程,包括初始化界面
face.java-----------按钮事件驱动----通过界面接受源程序,触发词法分析器,并读取词法分析结果,进行递归下降语法语义分析
lexical.java-------wordAnalysis()—接受源程序,进行词法分析,结果依符号表的形式保存在相应文件
调用次序:
recursion.javamain()--->face.javaface()--->cfPanel--->lexical.javawordAnalysis()
S()
6.2publicbooleanwordAnalysis(Strings)子程序的算法描述
publicbooleanwordAnalysis(Strings)
{char[]str=s.toCharArray();//用数组存储源程序
while(没有达到数组上界)
{if(str[count]是空格,换行符,制表符){count++;continue;}
if(str[count]是字母){从这个字母开始,将接下来的字母都保存在临时数组中,再跟关键字表比较,不是关键字就是标志符;分别置标号}
if(str[count]是数字){从这个数字开始,将接下来的数字都保存在临时数组中,置标号}
if(str[count]是运算符){若为单目,直接保存;若为双目,则向后看一位,用临时数组记录;
若为三目,则依次向后看两位,用临时数组记录;分别置标号}
if(str[count]是界符){直接保存,置标号}
}
}
6.3publicintGetsymbol()子程序的算法描述
publicintGetsymbol(){
While(词法分析结果文件不为空)
{Strings1;//保存取出的一个词法分析结果中的单词;
if(s1是关键字”while”)return16;
Elseif(s1是标志符)return13;
Elseif(s1是常量)return12;
Elseif(s1是/)return1;
Elseif(s1是*)return2;
Elseif(s1是-)return3;
Elseif(s1是+)return4;
Elseif(s1是<)return11;
Elseif(s1是=)return10;
Elseif(s1是>)return9;
Elseif(s1是;)return20;
}
该程序就是对词法分析结果(保存在lexical.txt文件中)进行分析,提取对本次while循环语句中的关键单词,分析到不同的数据类型就相应返回它的机内码,这样方便在语法分析中进行分析。
6.3S()子程序的算法描述
voidS()
{re=Getsymbol();//取下一个字符的机内码
if(re==关键字)//执行S->while(B)S
{re=Getsymbol();//取下一个字符的机内码
if(re==左括号)
{调用B();
re=Getsymbol();//取下一个字符的机内码
if(re==右括号)
调用S();
}}
Elseif(re==变量)//执行S->i=E
{re=Getsymbol();//取下一个字符的机内码
If(re==等号)
调用E();}
Else
ERROR();
}
该程序就是对通过Getsymbol()得到的单词,进行不同的程序语句执行。
当得到了while是就分析下一个是不是(,是的话就调用B();否则就出错。
取下一个单词,是)就调用S();否则也出错。
当得到的是变量i时,去下一个单词,如果是=就调用E()。
6.4B()和relop()子程序的算法描述
在B()子程序中,不用判断任何的单词,就依次调用E(),relop(),E(),执行B->ErelopE
Voidrelop()
{re=Getsymbol();//取下一个字符的机内码
if(sym==大于号);//执行relop-><
Elseif(sym==等于号);//执行relop->=
Elseif(syn==小于号);//执行relop->>
Else
ERROR();
}
在relop程序中就主要上判断当前取得的单词是不是条件运算符。
6.5E()子程序的算法描述
VoidE()
{re=Getsymbol();//取下一个字符的机内码
if(re==左括号)//执行E->(E)F
{E();
re=Getsymbol();//取下一个字符的机内码
if(re==右括号)
F();
}
Elseif(re==变量)//执行E->iF
F();
Elseif(re==常量)//执行E->nF
F();
}
6.6F()子程序算法描述
VoidF()
{re=Getsymbol();//取下一个字符的机内码
If(re==加号)//执行F->+EF
{E();F();}
Elseif(re==减号)//执行F->-EF
{E();F();}
Elseif(re==乘号)//执行F->*EF
{E();F();}
Elseif(re==除号)//执行F->/EF
{E();F();}
}
这个子程序和E()合起来就是一个完整的可递归的算术操作运算,但由于递归下降分析方法不能含有左递归文法,所以消去左递归后就成了两个子程序。
7软件的测试方法和测试结果
7.1测试方法---黑盒测试
本次设计由于程序结构和处理算法比较简单,并没有按照程序内部的逻辑测试程序,检测程序中的主要执行通路是否都能按预定要求正确工作,所以没有采取白盒测试方法.
7.2测试用例和测试结果
主要测试步骤是进行模块测试和系统测试,具体到设计中是对词法分析结果和语法测试结果分别测试,具体的测试用例是:
7.2.1测试词法分析器
输入字符串:
inti=0;abc=abc+k;
测试分析:
依此分析词法分析是否能识别关键字,标志符,界符,关键字
测试结果:
图4输出结果
7.2.2测试词法分析器
输入字符串:
while(i=2)abc=(i+j)*k;
测试分析:
这个输入字符串是正确的,是最简单的while语句
测试结果:
图4输出结果
输入字符串:
while(i<=2)i=j+k;
测试分析:
该字符串不符合本程序的文法,条件符号只有<>=
测试结果:
图5输出结果
输入字符串:
while(i<2)while(j<9)abc=(i+abc)*j;
测试分析:
该字符串符合文法,它嵌套了while语句
测试结果:
图6测试结果
输入字符串:
while(i<2)whilea=b+c23;
测试分析:
在嵌套的语句中,第二个while没有条件表达式
测试结果:
图7测试结果
8研制报告
8.1研制过程
在做本次实验之前我对LL
(1)文法的构成,递归下降原理不是很了解,在查阅了相关资料后,对此有了深入了解.在整个设计过程中,将词法分析做为一个单独的模块,它可以被任何语法分析调用,提高独立性.并且在编程之前就已经将程序的概要设计都做出来了,所以在编写程序的时候相对比较容易。
词法分析,语法分析都是很容易的,只要理解了分析方法的实现原理,编写程序判断输入字符串是否满足给定的文法是比较简单的。
8.2本设计的评价
在本次设计中,程序具有良好的用户界面,独立的词法与语法接口,并且在语法分析过程中可以准确指出语句中有错误的位置。
在编制整个设计的过程中,利用了所学的软件工程,软件设计面向对象的方法。
9参考文献
[1]陈火旺.刘春林等著,编译原理,北京:
国防工业出版社,2002.6
[2]陈意云.编译原理与技术(第二版).中国科学技术大学出版社.2002年1月
[3]张幸儿.计算机编译原理—编译程序构造实践:
科学出版社,2005.7
[4]王毅.JAVA程序设计自学手册:
人民邮电出版社,2005.9