编译原理实验报告.docx
《编译原理实验报告.docx》由会员分享,可在线阅读,更多相关《编译原理实验报告.docx(12页珍藏版)》请在冰豆网上搜索。
编译原理实验报告
FoshanUniversity
编译原理课程设计实验报告
学院:
专业:
计算机科学与技术
班级:
姓名:
学号:
日期:
2014年6月5日
目录
一、实验简介1
二、语言定义2
三、词法分析2
1.实现方法3
2.PL/0语言的词汇表3
3.具体实现流程图4
4.错误处理4
四、语法分析4
1.实现方法5
2.程序流程图5
3.错误处理7
五、目标代码生成8
1.实现方法8
2.汇编指令集8
3.具体实现8
六、程序运行测试8
1.测试样例9
2.词法分析结果9
3.语法分析结果9
4.汇编代码生成9
七、程序所存在的缺点与不足10
八、实验总结10
一、实验简介
本次实验旨在设计一个类PL语言子集的编译器,可以对自己设计的语言进行编译,最终生成可执行的汇编代码。
实验分为词法分析、语法分析和中间代码生成、汇编代码生成四个阶段。
通过实验,掌握词法分析的实现技术,深入了解语法分析的四种实现技术及具体实现方法,了解代码优化和代码生成的实现技术及具体实现方法。
明确编译各阶段之间的关系。
熟悉符号表的建立及在编译过程中的作用。
二、PL/0语言文法的EBNF
<程序>:
:
=<分程序>.
<分程序>:
:
=[<常量说明>][<变量说明>][<过程说明>]<语句>
<常量说明>:
:
=CONST<常量定义>{,<常量定义>};
<常量定义>:
:
=<标识符>=<无符号整数>
<无符号整数>:
:
=<数字>{<数字>}
<变量说明>:
:
=VAR<标识符>{,<标识符>};
<标识符>:
:
=<字母>{<字母>|<数字>}
<过程说明>:
:
=<过程首部><分程序>{;<过程说明>};
<过程首部>:
:
=PROCEDURE<标识符>;
<语句>:
:
=<赋值语句>|<条件语句>|<当循环语句>|<过程调用语句>
|<复合语句>|<读语句><写语句>|<空>
<赋值语句>:
:
=<标识符>:
=<表达式>
<复合语句>:
:
=BEGIN<语句>{;<语句>}END
<条件语句>:
:
=<表达式><关系运算符><表达式>|ODD<表达式>
<表达式>:
:
=[+|-]<项>{<加法运算符><项>}
<项>:
:
=<因子>{<乘法运算符><因子>}
<因子>:
:
=<标识符>|<无符号整数>|‘(’<表达式>‘)’
<加法运算符>:
:
=+|-
<乘法运算符>:
:
=*|/
<关系运算符>:
:
==|#|<|<=|>|>=
<条件语句>:
:
=IF<条件>THEN<语句>
<过程调用语句>:
:
=CALL标识符
<当循环语句>:
:
=WHILE<条件>DO<语句>
<读语句>:
:
=READ‘(’<标识符>{,<标识符>}‘)’
<写语句>:
:
=WRITE‘(’<表达式>{,<表达式>}‘)’
<字母>:
:
=a|b|…|X|Y|Z
<数字>:
:
=0|1|…|8|9
<一维数组>:
:
=VAR<标识符>[‘数字‘]
3、词法分析
1.实现方法
通过逐词读入样例程序中的内容,对每个单词进行判断分析,输出该单词的内容以及种别码。
PL的词法分析器将要完成以下工作:
(1)跳过分隔符(如空格,回车,制表符);
(2)识别诸如begin,end,if,while等保留字;
(3)识别非保留字的一般标识符,此标识符值(字符序列)赋给全局量id,而全局量sym赋值为SYM_IDENTIFIER。
(4)识别数字序列,当前值赋给全局量NUM,sym则置为SYM_NUMBER;
(5)识别:
=,<=,>=之类的特殊符号,全局量sym则分别被赋值为SYM_BECOMES,SYM_LEQ,SYM_GEQ等。
相关过程(函数)有getsym(),getch(),其中getch()为获取单个字符的过程,除此之外,它还完成:
(1)识别且跳过行结束符;
(2)将输入源文件进行词法分析后写到输出文件;
产生一份程序列表,输出相应行号或指令计数器的值
2.PL/0语言的词汇表
序号
类别
单词
编码
1
基本字
begin,call,const,do,end
if,odd,procedure,read
then,var,while,write
beginsym,callsym,constsym
dosym,endsym,ifsym,oddsym
proceduresym,readsym,thensym
varsym,whilesym,writesym
2
标识符
ident
3
常数
number
4
运算符
+,-,*,/,odd
=,<>,<,<=,>,>=,:
=
plus,minus,times,slash,oddsym
eql,neq,lss,leq,gtr,geq,becomes
5
界符
(),;.
Lparen,rparen,comma,semicolon
period
3.具体实现流程图
4.错误处理
当遇到非法字符、标示符与关键字重复时会显示相应的错误信息。
四、语法分析
1.实现方法
使用LR
(1)算法,首先求出语言定义文法的LR
(1)分析表,然后LR分析算法的总控程序根据分析表对源语言进行语法分析。
采用递归下降的方法来设计PL/0编译器,证明PL/0语言属于LL
(1)文法。
然后结合语法图编写(递归下降)语法分析程序的一般方法,具体方面有:
(1)用合适的替换将语法约化成尽可能少的单个图;
(2)将每一个图按下面的规则(3)-(7)翻译成一个过程说明;
(3)顺序图对应复合语句:
Sn
S1
S2
对应:
beginT(S1);T(S2);...;T(Sn)end
(4)选择:
S1
S2
S3
对应:
case语句或者条件语句:
casechofifchinL1thenT(S1)else
L1:
T(S1);ifchinL2thenT(S2)else
L2:
T(S2);或...
...ifchinLnthenT(Sn)else
Ln:
T(Sn);error
其中Li∈FIRST(Si),ch为当前输入符号。
(下同)
(5)循环:
S
对应:
whilechinLdoT(S)
(6)表示另一个图A的图:
A
对应:
过程调用A。
(7)表示终结符的单元图:
对应:
ifch==xthenread(ch)elseerror
相关过程有:
block(),constdeclaration(),vardeclaration(),statement(),condition(),expression(),term(),factor()等。
并画出它们之间依赖关系图,并在此基础上实现程序的编制。
并适当进行语义分析的相关检查:
(1)是否存在标识符先引用未声明的情况;
(2)是否存在己声明的标识符的错误引用;
(3)是否存在一般标识符的多重声明。
2.程序流程图
语法分析流程图:
3.错误处理
A.对于缺少括号和;等分割符的错误:
对栈中的元素进行判断如果为非终结符还不匹配则出栈。
说明缺少;})等
但是由于一般这种错误都在上一行缺少所以:
错误行数为当前token所在行前一行
B.对于程序未完全解析完的处理{}不配陪:
可能由于括号冗余使得在文件未完全解析完时栈已经为空。
所以在控制程序中添加对栈底的判断,如果遇到文件还没有解析完将语句块非终结符压入栈中继续匹配。
一般为上一行冗余}。
错误行数:
为当前token所在行前一行。
E.代码不完整
对于程序解析完栈中还有符号,说明缺少部分信息,代码不完全需要将栈清空,并说明程序不完整。
错误行数:
代码的末尾。
五、目标代码生成
1.实现方法
通过查看语义分析所产生的结果,分析四元式,输出相应的汇编语句。
2.汇编指令集
本次目标代码的翻译采用了AT&T汇编指令集。
3.具体实现
详见源代码。
六、程序运行测试
1.测试样例
测试程序1
consta=10;
varb,c;
begin
read(b);
c:
=a+b;
write(c)
end.
所有测试程序见附录《编译原理测试程序》。
2.词法分析结果
3.语法分析结果
5.汇编代码生成
七、程序所存在的缺点与不足
1.由于时间原因,在语义分析阶段,没有实现对数组、函数部分的分析。
2.语法分析和语义分析的错误处理方面只能报出错误类型,无法确定是错误出现的具体位置。
3.词法分析和其他部分没有合并。
4.在布尔表达式方面,并未实现多个表达式之间的与、或、非功能。
5.文法设计的不够合理,有很多不需要的地方使得源语言很繁琐(if、while语句在结束时要在}后加上一个;等等)。
八、实验总结
通过从词法分析-语法分析-目标代码生成的过程,我也真是的体会着编码的开心与痛苦,但是收获解决一个个问题的幸福感,在不断学习中也教会我如何自己去学习,一点点建立着属于自己的信心,增强着自己不算强的问题解决能力。
词法分析虽然比较简单,但是构造识别单词的自动机的时候让我复习和巩固了关于自动机方面的知识。
语法分析过程中我掌握了自底向上和自顶向下两张思想,最后采用LR
(1)分析法。
通过编写程序,我对LR
(1)分析法有了深刻的理解。
汇编代码生成阶段让我对AT&T汇编语言有了一定的了解。
总之,通过实验我掌握了编译原理的一些基础,对于Java的堆栈的使用和list的使用有了进一步的了解,同时在每天思考如何实现程序时,也增强了的我解决问题的能力。