PL0语言编译器的中间代码生成.docx
《PL0语言编译器的中间代码生成.docx》由会员分享,可在线阅读,更多相关《PL0语言编译器的中间代码生成.docx(12页珍藏版)》请在冰豆网上搜索。
PL0语言编译器的中间代码生成
课程设计报告
(2016--2017年度第一学期)
名称:
编译技术课程设计
题目:
PL/0语言编译器的中间代码生成
院系:
控制与计算机工程
班级:
信安1401
学号:
**********
*******
******
设计周数:
一周
成绩:
日期:
2016年12月29日
1课程设计的目的和要求
1.1课程设计的目的
本次设计的时间为1周,目的是通过使用高级语言实现部分算法加强对编译技术和理论的理解。
设计的题目要求具有一定的规模,应涵盖本课程内容和实际应用相关的主要技术。
1.2课程设计的要求
1、要求用递归子程序法/或预测分析法实现对表达式、各种说明语句、控制语句进行语法分析。
2、若语法正确,则用语法制导翻译法进行语义翻译:
对说明语句,要求将说明的各符号记录到相应符号表中;对可执行语句,应产生出四元式中间代码并填写到三地址码表中;
3、若语法错误,要求指出出错性质和出错位置(行号)。
出错处理应设计成一个出错处理子程序。
2系统描述
PL/0的编译程序和目标程序的解释执行程序都是用JAVA语言书写的,因此PL/0语言可在配备JAVA语言的任何机器上实现。
本次课设开发平台即为JAVA。
用递归子程序法实现了对表达式、各种说明语句、控制语句进行语法的分析。
其中,对各个变量符号保存到了符号表中。
对可执行语句,转化成四元式中间代码进行输出。
本程序中,通过出错处理子程序,也进行了语法的错误的记录,并且输出了出错的行号和出错原因。
该程序的输入是打开test文件,通过文件输入流读入,输出有生成的中间代码、符号表内容、错误分析三部分内容,分别用java界面控件显示出来。
2.1文法的描述
在计算机科学中,文法是编译原理的基础,是描述一门程序设计语言和实现其编译器的方法。
文法的描述多用BNF(巴克斯范式),而另一个重要的概念:
正则表达式,也是文法的另一种形式。
PL/0文法的EBNF表示:
<程序>:
:
=<分程序>.
<分程序>:
:
=[<常量说明部分>][<变量说明部分>][<过程说明部分>]<语句>
<常量说明部分>:
:
=const<常量定义>{,<常量定义>};
<常量定义>:
:
=<标识符>=<无符号整数>
<无符号整数>:
:
=<数字>{<数字>}
<标识符>:
:
=<字母>{<字母>|<数字>}
<变量说明部分>:
:
=var<标识符>{,<标识符>};
<过程说明部分>:
:
=<过程首部><分程序>{;<过程说明部分>}
<过程首部>:
:
=procedure<标识符>;
<语句>:
:
=<赋值语句>|<条件语句>|<当循环语句>|<过程调用语句>
|<复合语句>|<读语句>|<写语句>|<空>
<赋值语句>:
:
=<标识符>:
=<表达式>
<表达式>:
:
=[+|-]<项>{<加法运算符><项>}
<项>:
:
=<因子>{<乘法运算符><因子>}
<因子>:
:
=<标识符>|<无符号整数>|‘(’<表达式>‘)’
<加法运算符>:
:
=+|-
<乘法运算符>:
:
=*|/
<条件>:
:
=<表达式><关系运算符><表达式>|odd<表达式>
<关系运算符>:
:
==|<>|<|<=|>|>=
<条件语句>:
:
=if<条件>then<语句>
<当循环语句>:
:
=while<条件>do<语句>
<过程调用语句>:
:
=call<标识符>
<复合语句>:
:
=begin<语句>{;<语句>}end
<读语句>:
:
=read‘(’<标识符>{,<标识符>}‘)’
<写语句>:
:
=write‘(’<表达式>{,<表达式>}‘)’
<字母>:
:
=a|b|c|d…..x|y|z
<数字>:
:
=0|1|2|3…...8|9
3概要设计
3.1概要设计(体现系统的设计思路和主要功能)
首先在源程序相同的目录下创建一个txt文档,并在文档中输入需要编译的程序即if-else语句,然后定义一个输入流文件,利用这个流文件中的open函数打开我需要编译的txt文件,在调用初始化各种变量的初始化函数。
接着开始进行词法分析,词法分析程序的主要任务是对构成源程序的字符串从左到右的扫描,逐个字符地读入源程序字符并按照构词规则切分成一个一个具有独立意义的单词。
并确定其属性(如保留字、标识符、运算符、界限符和常量等)。
再把它们转换成长度统一的标准形式—属性字。
词法分析是编译过程中的第一个阶段,在语法分析前进行。
也可以和语法分析结合在一起作为一遍,由语法分析程序调用词法分析程序来获得当前单词供语法分析使用。
单词的分类(五类):
1.关键字:
由程序语言定义的具有固定意义的标识符。
也称为保留字或基本字。
2.标识符:
用来表示程序中各种名字的字符串。
3.常数:
常数的类型一般有整型、实型、布尔型、文字型。
4.运算符:
如+、-、*、/等。
5.界限符:
如逗号、分号、括号等。
但是我做的这个实验没有用到那么多东西,词法分析的有效字符串为:
IF,ELSE,THEN,<,>,.<=,>=,=,和从a到z的单个标识符,但是程序还是相对来说比较简单,复杂的表达式可能不能处理,以后会改进。
而词法分析的结果就是将相应的单词赋予不同的属性值,利用词法分析表将结果保存起来,为后面的语义分析做准备。
词法分析完成之后就是把词法分析的结果都显示出来。
语法分析的过程在上面已经有了说明,语法分析完了之后就是打印中间代码的三地址形式,根据上面的结果,三地址的数组里面已经存储了编译的具体信息,之需要按照相应的算符,将他们输出出来,即可看到中间代码的三地址表示形式。
3.2系统用例图【必须有】
图3-1系统用例图
3.3系统用例
此编译器系统共有两个面向用户的用例,导入程序用例和分析PL/0程序用例。
其中分析PL/0程序用例中又包含了词法分析用例、语法分析用例、和生成四元式用例。
3.4开发环境
在JAVA开发环境下实现PL/0中间代码(四元式)生成编译器。
4详细设计
4.1系统的类图
4.2主要算法的流程图
4.3数据分析与定义
1、token类用于存放读取的token单词
classtoken{
privateStringsym="";//保存token的类型
privateStringname="";//保存token的内容
publicintlineNum;//该词所在的行
}
2、符号类,存放于符号表中
classnameClass{
Stringname=null;
Stringkind=null;
intval;//值
intlevel;//层次
intadr;//过程的入口代码地址
}
3、错误处理类
classerro{
publicstaticStringerrorString="";
String[]err={"缺少左括号"
"非法字符:
赋值符号:
="
"等号后的字符为非法字符"
"缺少等号"
"声明过程中遇到的字符不是标识符"
"缺少分号"
"非法语句"
"整数大小越界"
"整数位数越界"
"缺少右括号"
"语句和语句之间没有分号"
"标识符不存在"
"标识符不是变量名"
"缺少赋值符号"
"call后不是标识符"
"call后不是过程名"
"if后不是then"
"没有遇到end"
"while循环缺少do"
"标识符长度越界"
"缺少逻辑运算符"
"标识符为过程名"
"缺少右括号"};
intlinenumber;
intt;
}
4、midcode类表示midcode指令
classmidcode{
Stringop="";//第一个参数:
操作码
Stringarg1="";//第二个参数:
操作数1
Stringarg2="";//第三个参数:
操作数2
Stringresult="";//第四个参数:
结果-中间参数
}
4.4系统界面设计
5测试方法和测试结果
5.1测试用例1
测试目的:
通过primenum.pl文件(本身词法语法是正确的)来进行检测,在没有词法语法的前提下是否能够正确的分析PL/0程序,并且生成正确的中间代码,符号表的内容是否正确。
其中test.pl文件中的程序代码包含了conset常量,var变量,procedure过程声明,begin、end关键字,复杂表达式赋值,read、write语句,算术运算符(+、—、*)、关系运算符(=、/、#、>、<、>=、<=),条件if、then语句,过程调用call语句,当型循环while、do语句,和字母数字,基本包含了所有pl0语言的语法语义规则。
输入如程序5-1所示。
consttrue=1,false=0;
varx,y,m,n,pf;
procedureprime;
vari,f;
proceduremod;
x:
=x-x/y*y;
beginf:
=true;
i:
=3;
whileibeginx:
=m;
y:
=i;
callmod;
ifx=0thenf:
=false;
i:
=i+2
end;
iff=truethen
begin
write(m);
pf:
=true
end
end;
begin
pf:
=false;
read(n);
whilen>=2do
begin
write
(2);
ifn=2thenpf:
=true;
m:
=3;
whilem<=ndo
begincallprime;
m:
=m+2
end;
read(n)
end;
ifpf=falsethenwrite(0)
end.
5.1测试用例2
测试目的:
通过primenume.pl文件来进行检测,存在语法错误的时候,查看运行结果是否能将错误所在的行找出来,并且打印出错误的个数和错误的原因。
输入如程序5-2所示。
consttrue=1,false=0;
varx,y,m,n,pf;
procedureprime
vari,f;
proceduremod;
x:
=x-x/y*y;
beginf:
=true;
t:
=3;
whileibeginx:
=m;
y:
=i;
callmod;
ifx=0thenf:
=false;
i:
=i+22345
end;
iff=truethen
begin
write(m);
pf:
=true
end
end;
begin
pf:
=false;
read(n;
whilen>=2
begin
write
(2);
ifn=2thenpf:
=true;
m:
=9234;
whilem<=ndo
begincallpr;
m:
=m+2
end;
read(n)
end;
ifpffalsethenwrite(0)
end.
结论和展望
结论
通过本次编译课程设计,让我们将理论学习与实践很好的结合了起来,是将理论应用于实际的最好的方法,通过对pl/0语言的词法和语法分析,我们了解了编译过程是一个什么样的具体分析过程,这也是通过本门课设收获最大之处,以前使用过的许多种编译器,却从来没有想过这些编译器是怎样将高级语言程序转化成低级语言程序的,这次课设让我明白了许多东西。
同时,课程设计过程中对语法分析时,需要很好的数据结构的设计,也让我们认识到了数据结构的重要性。
总之,通过本次课设,锻炼了自己设计算法,设计软件的能力,是一次很好的实践过程,同时也暴露了不少缺点,让我们认识到了不足,这为我们今后的学习指引了新方向。
展望
本次实验的不足还有很多,作为一个完善的编译器,由于时间的原因,我们没有实现文件保存功能,即不能将生成的中间代码和错误分析写进文件进行保存,也没有将用户界面设计的很详细。
但是之后我们会尽量完善该编译器的这些功能。
收获:
通过本次实验,我收获了很错东西。
首先对编译有了进一步的深刻理解,通过对递归下降法应用,让我对数据结构的设计思想有了很深的认识,同时我们对词法分析、语法分析的原理和过程都有了进一步的巩固,使用JAVA平台开发也让我们的编程水平也起到了锻炼的作用,巩固了平时所学的知识,真正做到了学以致用。
但是在编码过程中暴露的问题是我们今后需要改进的地方,我相信认识到了问题所在,今后努力的方向才会更明确,才会更好的提高自己的水平。
学习编译技术课程的体会和对本门课程的评价
这次课程设计加深了我对编译过程的理解,不管是整体还是细节都有了更深入的体会,有些章节学的比较浅的,在这次课设中也强化了知识,如活动记录、符号表等。
实践出真知,平时学习的仅限于书本知识,只会做几道题目,只有真的应用于实践中,才明白原来它的原理是这样的,而这些细节也在一步一步的调试过程中明了。
但是,我深知编译原理的博大精深。
现在学的只能涉及到它一些最基本的原理,对于宏观的方法去研究,还需要在以后的时间里去钻研。