完整word版FOR循环语句的翻译程序设计LL1法输出三地址文档格式.docx
- 文档编号:7560743
- 上传时间:2023-05-08
- 格式:DOCX
- 页数:20
- 大小:116.32KB
完整word版FOR循环语句的翻译程序设计LL1法输出三地址文档格式.docx
《完整word版FOR循环语句的翻译程序设计LL1法输出三地址文档格式.docx》由会员分享,可在线阅读,更多相关《完整word版FOR循环语句的翻译程序设计LL1法输出三地址文档格式.docx(20页珍藏版)》请在冰点文库上搜索。
FOR循环语句的翻译程序设计
——LL
(1)法、输出三地址
1.系统描述
1.1问题描述
用LL
(1)法设计、编制、调试一个FOR(表达式1;
表达式2;
表达式3)〈赋值语句〉的语法及语义分析程序,输出三地址代码。
1.2功能描述
(1)能对for循环语句做词法分析,并将其中的某些语句做预处理,如i++转换为i=i+1等。
(2)能依据给定的LL
(1)文法判断输入串是否符合LL
(1)文法
(3)给出输入串的LL
(1)分析过程
(4)完成对语句中控制变量赋值语句,控制条件语句以及控制变量变换语句的翻译
(5)完成对赋值语句包括复杂语句的翻译
(6)能够对三个表达式缺少一个或多个的情况下进行翻译
(7)用翻译后的语句以三地址代码的中间代码形式正确的表达for循环的执行流程。
2.文法及属性文法的描述
2.1文法的语言描述
(0)A->
for(C;
C;
C){Y}(“}Y{)C;
C(for”)
(1)Y->
i=E;
(“;
E=i”)
(2)C->
iD(“Di”)
(3)C->
(“”)
(4)D->
=E(“E=”)
(5)D->
<
E(“E<
”)
(6)D->
>
E(“E>
(7)E->
LM(“ML”)
(8)M->
+LM(“ML+”)
(9)M->
-LM(“ML-“)
(10)M->
(11)L->
NP(“PN”)
(12)P->
*NP(“PN*”)
(13)P->
/NP(“PN/”)
(14)P->
(15)N->
i(“i”)(i表示标识符或常数)
(16)N->
(E)(“)E(“)
(17)D->
=E(“E=<
(18)D->
=E(“E=>
2.2属性文法的描述
2.2.1FOR语句
for(C1C2C3)
nC1
n+1goton+3
n+2C3
n+3ifC2==truegotoY.start
n+4gotoY.end+2
Y.start...................//赋值语句的开始
.........................
Y.end...................//赋值语句结束
Y.end+1goton+2
Y.end+2//跳出循环体后第一条语句
2.2.2表达式和赋值语句
Y->
(C->
){i.value=E.Value}
E->
E1opE2(op:
+,-,*,/,>
>
=,<
或<
=)
{
E.place=newtemp;
//生成新的变量
E.value=E1.valueopE2.value
}
N->
(E){N.value=E.value}
i{N.value=i.value}
3语法分析方法描述及语法分析表设计
3.1LL
(1)文法及预测分析法的描述
LL
(1):
第1个L表明自顶向下分析是从左向右扫描输入串,第2个L表明分析过程中将用最左推导,1表明只需向右看一个符号便可决定如何推导即选择哪个产生式(规则)进行推导。
从文法的开始符号出发企图推导出与输入的单词串完全相匹配的句子,若输入串是文法给定的句子,则必能推出,反之必然出错。
LL
(1)优点:
实现方法简单、直观,便于手工构造或自动生成语法分析器。
文法很容易写出。
LL
(1)缺点:
对文法有一定得限制,要求推导过程中紧跟在飞终结符右边可能出现的终结符集不相交,要求文法产生式中不能含有左公共因子和左递归。
但并不是所有文法的左公共因子都能在有限的步骤内替换成无左公共因子的文法。
另外在做语法制导翻译时中间代码的输出方案相对于LR法比较复杂。
LR分析法的句柄即体现了算符的优先级,出现句柄即做相应的归约动作,中间代码很容易写出,实现很简单。
LL
(1)是做自顶向下推导,因此设计LL
(1)的语法制导翻译输出中间代码很需要技巧,涉及到了判断符号的优先级。
3.2预测分析表的构造
先求出每个产生式的select集,以产生式左侧非终结符为纵轴,以终结符(包括#)为横轴作预测分析表,在非终结符与其select集中元素对应的单元格中填上相应产生式的右部或其序号,没有则填-1。
文法产生式及其select集
序号
产生式
select集
A->
C){Y}
for
1
i
2
C->
iD
3
;
)
4
D->
=E
=
5
E
6
7
LM
i,(
8
M->
+LM
+
9
-LM
-
10
},),;
11
L->
NP
12
P->
*NP
*
13
/NP
/
14
+,-,),;
}
15
16
(E)
(
17
18
LL
(1)文法的预测分析表
)
{
}
num
A
-1
Y
C
D
M
L
P
N
单元格中数字表示选用第几个产生式,-1表示出错,num代表常数,i代表标识符。
4.中间代码形式的描述及中间代码序列的结构设计
4.1三地址代码描述
把表达式及各种语句表示成一组三元式。
每个三元式3个组成部分是:
酸腐op,第一运算对象ARG1,和第二运算对象ARG2.例如a:
=b*c+b*d的表示为:
(1)(*b,c)
(2)(*b,d)
(3)(+
(1),
(2))
(4)(:
=(3),a)
与后缀式不同,三地址码含有对中间计算结果的显式引用,比如三元式
(1)表示的是b*c的结果。
三元式(3)中的
(1)和
(2)分别表示第1个三元式和第2个三元式的结果。
对于一目算符op,只需选用一个运算对象,不妨规定只用ARG1.至于多目算符,可用若干个相继的三元式表示。
三地址代码一般形式:
x:
=yopz表示为
1>
yopz
2>
=<
4.2中间代码序列的结构设计
以for(i=0;
i<
10;
i++){i=i+2;
}为例,三地址中间代码生成序列如下:
i=0
goto<
4>
3>
i=i+1
5>
if<
goto<
7>
6>
10>
i+2
8>
i=<
9>
三地址代码结构:
控制变量赋值
跳转到判断语句
控制变量更改
判断语句
若成立跳转到赋值语句循环体
不成立则跳转到循环结束
赋值语句
i>
i+1>
跳转至控制变量更改语句
i+2>
循环结束语句
由于临时变量的个数是未知的,所以在语义分析的过程中需要保存临时变量的个数,以便保证下一条语句序号及循环出口的正确。
5.编译系统的概要设计
5.1LL
(1)文法的设计
(1)文法的设计需要合理,使之符合LL
(1)文法的要求,尽量避免产生式右部首部有交集,而某些文法的左公共因子无法完全消除
(2)文法应该考虑到循环条件的三个产生式中有一个或多个为空的情况下的循环流程(部分语言如C语言甚至允许三个条件都为空,第一个条件空,则需要循环体之前的语句中对讯黄控制变量进行赋值;
第二个条件为空,则循环会无限执行下去,即进入死循环;
第三个条件为空,则在循环体中对控制变量进行改变)。
(3)对于循环体中的赋值语句,不仅仅有形如i=a+b的简单语句,还应考虑更复杂的复合赋值语句,这时就要进行操作符的优先级分析。
5.2语法及语义分析
有LL
(1)文法写出预测分析表,由此可以用预测分析法对输入串进行分析。
当分析栈栈顶为非终结符时,通过查表,将非终结符出栈,并将表中产生式右部逆序进栈,若对应单元为空或为错误标记,则出错;
当栈顶为终结符时,若与当前输入符号相同,则栈顶出栈,输入串指针后移,若不同则出错。
一直分析下去,知道最后栈中只剩下#并且输入串也只有一个#,则该输入串可以被指定的LL
(1)文法所识别,反之则否。
对赋值语句的翻译。
主要是对操作符的优先级的比较,使用算符优先分析法。
死机一个操作符栈和一个操作数栈,当前操作符的优先级小于或者等于当前输入符号时,输入符号进操作符栈,若大于,则操作符栈顶出栈,操作数栈两次出栈(二目运算符)进行运算,并将结果(中间变量)进操作数栈,依此分析。
6.详细的算法描述(伪代码描述)
main()//主函数
{
lexicalAnalyze();
//词法分析(预处理
parseAnalyze(();
//语法预测分析
semanticsOutput();
//语义输出
部分方法的实现:
lexicalAnalyze(){//输入串的词法分析
stringinput[];
stringtmp=getText();
//读取文件到临时字符串
if(tmp.end!
=’#’)tmp.end=’#’;
//在字符串末尾添加’#’
do{
curString=getWord(tmp);
//从字符串中获取有效单词
if(curString==”“)tmpPointer++;
continue;
//去除无效空格,并移动扫描指针
curString->
input[];
//将单词存入字符串数组
if((input[n-1]=="
"
||input[n-1]=="
)&
&
input[n]=="
="
)//组合<
=和>
input[n-1].append(input[n]);
+"
-"
input[n]==input[n-1])//转换++和--
i=i±
1->
if((input[n-2]=="
||input[n-2]=="
input[n-1]=="
)//转换+=和-=
n->
parseAnalyze(){//语法分析
statckana();
ana.push(“#”);
//”#”和”A”进分析栈
ana.push(“A”);
if(input[]==”for”)
if(ana.getTop==input[])
input_pointr++;
//输入串扫描指针右移
ana.pop();
//栈顶出栈
if(ana.getTop==”A”)
ana.pop;
ana.reversePush(“for(C;
C){Y}”);
//产生式右部逆序入栈
if(input[]==”i”)
if(ana.getTop==input[])
...
if(ana.getTop==”C”)
if(ana.getTop==”Y”)
......
......
if(input[]==”#”)//匹配成功
if(ana.getTop==input[])cout<
”Matchsuccessful!
”;
elsecout<
”Matchfail!
//匹配失败
constProcess()//常数处理,字符串共有i个字符
for(dotCount=0;
dotCount<
i;
dotCount++)//对小数点定位,无则返回-1
if(curString[dotCount]==’.’)returndotCount;
elsereturn-1;
for(eCount=0;
eCount<
eCount++)//对e定位,无则返回-1
if(curString[eCount]==’e’)returneCount;
elsereturn-1;
if(dotCount==-1&
eCount==-1)//纯整数的情况
for(count=0;
count<
count++)
parseInt+=(curString[count]-30H)*pow(10.0,i-1-count);
//ASCII转为整数
elseif(dotCount!
=-1&
eCount==-1)//纯小数的情况
for(leftCount=0;
leftCount<
dotCount;
leftCount++)//小数的整数部分
parseInt+=(curString[leftCout]=30H)*pow(10.0,dotCount-1-leftCount);
for(rightCount=dotCount+1;
rightCount<
rightCount++)//小数的小数部分
parseDecimal+=(curString[leftCout]=30H)*pow(10.0,dotCount-reghtCount);
parseBase=parseInt+parseDecimal;
else//含有e的情况
if(k!
=-1)//e前面是小数
eCount;
parseBase=paseInt+parseDecimal;
else//e前面是整数
for(count=0;
pareseBase+=(curString[count]-30H)*pow(10.0,eCount-1-count);
for(count=eCount+1;
count++)//指数的幂
paresePower+=(curString[count]-30H)*pow(i-1-count);
parseTotal=parseBase*pow(10.0,parsePower);
semanticsOutput//执行语义动作
/*对于赋值语句和布尔表达式,调用词法分析程序分析并同步记录临时变量的个数*/
7.软件的测试方法和测试结果
在文本文件中输入for(i=0;
=10;
i++){i+=2;
词法分析结果(转换过双目运算符):
语法分析过程:
三地址代码输出结果:
将循环条件的第三个产生式删除后的输出结果:
8.研制报告
8.1研制过程
本实验在文法的构造方面遇到了困难,LL
(1)对文法有一定的限制:
不能含有左公共因子和左递归,表现在产生的select集不相交,而又要能表示比较宽泛的for循环的格式,需要用到一些空产生式,这又增加了select集相交的可能性,所有构造LL
(1)遇到了一些困难,不过最终还是构造出了符合LL
(1)文法要求的文法。
本来想对赋值语句的语法分析时也用LL
(1)方法,但是它并不适合做这一工作,最后还是交给了更适合的算符优先分析法。
本实验重要的是预测分析表的构造以及语义动作的书写,LL
(1)文法相对来说构造比较简单,但语义动作比较困难,可以在语法分析的过程中一起写出来。
8.2设计的特点和不足
本设计比较大的特点是在词法分析的过程中可以对双目运算符(如++,--,±
=等)做预先处理,将它们转换成一般的算术表达式,这样便于后期语法分析;
考虑到了第三个表达式为空的情况,此时控制变量的改变是在循环体中进行的;
另外还增加了常数处理的模块,包括整数,小数和包含e的指数的处理。
本、设计的不足:
本设计并没有考虑第一和第二个表达式为空的情况,第一个表达式为空时涉及到了for循环前面的语句,在此可以不加讨论;
第二个表达式为空时可以在语义分析时将它替换成1,即一直成立,这样在语义上也是正确的;
文法的限制过大,循环体中只能有一个赋值语句,并且只有一层循环,没有考虑循环的嵌套。
8.3收获和体会
此次课程设计综合了词法分析、语法分析(LL
(1)预测分析法和算符优先分析法)、语义分析(语法制导翻译)的知识内容,设计时需要全盘考虑它们之间的整合协作。
在书写文法的时候原本写的文法很简单,寥寥几句,但是无法全面地表达出for循环语句的语言结构,遗漏的地方有不少。
文法太复杂的话处理左递归时比较麻烦,而且有时并不能完全消除左递归。
最后采用了折中的办法,在复杂文法的基础上将表达式进行统一而不是原来的三个。
文法本来想考虑加入+=、++等双目运算符,但这样会大大影响文法的复杂度和语法分析时判断的正确性,所以在词法分析的阶段就预先将双目运算符转换成了单目运算符。
在语法分析时,由于我用的是字符串栈,当查找预测分析表后,产生式右部逆序进栈,然后取栈顶与输入符号比较时,取的不是栈顶,而是栈顶字符串的最后一个字符,这样增加了分析的难度,而且双目运算符以及多字符符号也会产生干扰:
如>
=逆序进栈后是=<
,取栈顶末尾字符即<
这里的双目运算符就被错误的拆成了两个单目运算符;
多字符符号如for也会有类似问题。
我用的方法是每次取栈顶时,首先先对栈顶字符串进行词法分析,将它拆成一个个有意义的单词后依次进栈,这样就解决了上述问题,不过这也增加了计算的开销。
自己写程序在命名规范上仍然存在不足,想到需要什么变量就随便起了个名字,没有起到很好的表达意义的作用。
程序的总体大局观不够,没有做到全盘考虑,部分重用代码可以写成单独的函数,减少空间开销。
在设计时,应该去学习新的思想和方法,提高对语言本身结构的认识,了解程序执行代码到底都做了什么,而不仅仅是去了解执行的结果。
这样才能通过一次次的程序设计提高自己对一种语言的根本认识。
9.参考文献
[1]张素琴,吕映芝,蒋维杜,戴桂兰.编译原理(第2版).清华大学出版社.2002.06
[2]闵联营,何克右.C++程序设计教程(第二版).武汉理工大学出版社.2005.07
[3]李普曼(StanleyB.Lippman)等.C++Primer中文版(第4版).人民邮电出版社.2008.07
本科生课程设计成绩评定表
班级:
姓名:
学号:
评分项目
满分
实得分
学习态度认真、遵守纪律
设计分析合理性
设计方案正确性、可行性、创造性
20
设计结果正确性
40
设计报告的规范性
设计验收
总得分/等级
评语:
注:
最终成绩以五级分制记。
优(90-100分)、良(80-89分)、中(70-79分)、
及格(60-69分)、60分以下为不及格
指导教师签名:
200年 月 日
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 完整 word FOR 循环 语句 翻译 程序设计 LL1 输出 地址
![提示](https://static.bingdoc.com/images/bang_tan.gif)