编译原理课设报告
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
课程设计报告
课程名称编译原理课程设计
WHILE循环语句的翻译程序设计题目
(递归下降法、输出四元式)学院计算机科学与技术
班级
学号
姓名
指导教师汪祥莉
2019年1月3日
课程设计任务书
学生姓名:专业班级:
指导教师:汪祥莉工作单位:计算机科学与技术学院
题目: WHILE循环语句的翻译程序设计(递归下降法、输出四元式)
初始条件:
理论:学完编译课程,掌握一种计算机高级语言的使用。
实践:计算机实验室提供计算机及软件环境。
如果自己有计算机可以在其上进行设计。
要求完成的主要任务:(包括课程设计工作量及其技术要求,以及说明书撰写等具体要求)
(1)写出符合给定的语法分析方法的文法及属性文法。
(2)完成题目要求的中间代码四元式的描述。
(3)写出给定的语法分析方法的思想,完成语法分析和语义分析程序设计。
(4)编制好分析程序后,设计若干用例,上机测试并通过所设计的分析程序。
(5)设计报告格式按附件要求书写。
课程设计报告书正文的内容应包括:
1 系统描述(问题域描述);
2 文法及属性文法的描述;
3 语法分析方法描述及语法分析表设计;
4 按给定的题目给出中间代码形式的描述及中间代码序列的结构设计;
5 详细的算法描述(流程图或伪代码);
6 软件的测试方法和测试结果;
7 实践总结(本设计的评价、特点、不足、收获与体会等);
时间安排:
设计安排一周:周1、周2:完成系统分析及设计。
周3、周4:完成程序调试及测试。
周5:撰写课程设计报告。
设计验收安排:设计周的星期五第1节课开始到实验室进行上机验收。
设计报告书收取时间:设计周的次周星期一上午10点。
指导教师签名: 2019年 10月 1日
系主任(或责任教师)签名: 2019年 10月 1日
一.系统描述
设计编写一个常见高级语言while循环语句的词法﹑语法及语义分析程序,语法分析选择递归下降法,使用语法制导的语义计算输出四元式形式的中间代码。
其中,递归下降法使用的是LL(1)文法,必须先消除左递归,使文法符合LL(1)文法。
词法分析部分可采用先前实验所写代码,再利用递归下降法编写一个集语法分析和语义分析为一体的程序。
该程序首先可以检查输入语句是否符合词法要求,不符合的话能给出具体的错误信息,若符合则继续识别输入的语句是否符合while语句的文法。
最后,输出用四元式表示的中间代码。
本次课程设计采用C++语言进行设计编写。
二.文法及属性文法的描述
2.1 文法的描述
表2.1 扩展巴克斯范式(EBNF)描述对上述巴克斯范式分析并消除左递归得到以下文法:
∙S → while (A) {B} | while (A) B
∙ A → C D C | C
∙ B → i = C;B | ε
∙ C → E G
∙ D → == | < | > | >= | <= | && | ||
∙ E →F H
∙G → + E G | - E G | ε
∙ F → (C) | i | n
∙H → *F H | / F H | ε
该文法符合LL(1)文法规则:
1. 任意非终结符都不是左递归的,否则会产生死循环。
2. 关于产生式不同的左部,其产生式的Select集的交集为空集2.1 属性文法的描述
三.语法分析方法描述及设计
3.1 递归下降法描述
递归下降法是一种比较简单直观,易于构造的语法分析方法。
它的优点是简单直观,
易构造,很多编译系统所实现缺点是对文法要求很高,由于递归调用多,影响分析器的效率。
他要求文法满足LL(1)文法,他的设计思想是对应文法中每个非终结符编写一个分
析子程序,分析程序从调用文法开始符号所对应的分析子程序开始执行。
每个过程的功能
是识别由该非终结符推出的单词(或串),当某非终结符的产生式有多个候选时,根据下
一次单词能够按LL(1)形式可唯一地确定自顶向下分析过程中应该选择的某个产生式进
行推导。
根据所选的产生式,分析子程序的行为依据产生式右端依次出现的符号来设计:
∙每遇到一个终结符,则判断当前读入的单词符号是否与该终结符相匹配(只要求单词
符号与该终结符对应,不必考虑单词自身的值),若匹配,则继续读取下一个符号,若不
匹配,则进行错误处理。
∙每遇到一个非终结符,则调用相应的分析子程序。
3.2 分析程序设计
递归下降程序是由一组子程序组成,每个子程序对应于一个非终结符。
每个子程序处
理相应句型中相对于此非终结符号的产生式。
在定义文法时,是递归定义的,所以这些子
程序也是递归的。
当一个子程序调用另一个子程序时,原子程序顺序执行语句,即总是先
执行被调用的子程序,然后再执行后继的程序。
将属性的引用传到下一个调用函数中。
void ParseS();
……
void ParseH();
例如F→(C)可大致设计:
void ParseF(){
MatchToken(T_LPAREN); //T_LPAREN为终结符‘(’对应单词种别
ParseC();
MatchToken(T_RPAREN); //T_RPAREN为终结符‘)’对应单词种别}
函数MatchToken()可大致设计为:
void MatchToken(char c){
if(lookahead != c){
调用出错函数
}else{
lookahead++;
}
}
其中分析的单词来自结构体数组:
struct Word {
string word;
string type;
};
四.中间代码形式的描述及中间代码序列的结构设计
4.1中间代码——四元式
中间代码选用四元式,四元式是一种更接近目标代码的中间代码形式。
由于这种形式的中间代码便于优化处理,因此,在许多编译程序中得到了广泛的应用。
它的一般形式为:(op,arg1,arg2,result)
其中,op可以为零元,一元,二元或者多元运算符;arg1,arg2分别为它的两个运算(或操作)对象,它们可以是变量、常数或系统定义的临时变量名(tn),四元式最后的运算结果(或临时变量名)将放入result中。
而且,每个四元式只能有一个运算符,所以,一个复杂的表达式必须由多个四元式(多
个临时变量)构成的序列来表示。
例如(1+2)*5的四元式为:
(+,1,2,t1)
(*,t1,5,t2)
其中,T1,T2是编译系统所产生的临时变量名。
当op为一元、零元运算符(如无条件转移)时,arg2甚至arg1应缺省。
4.2四元式结构设计
采用结构体存储四元式结构:
struct FoEle {
string op;
string arg1;
string arg2;
string result;
};
定义四元式结构数组:
FoEle foEle[1000];
并且添加一个全局变量存储四元式数:
int fENum = 0;
五.详细的算法描述
5.1词法分析
While语句词法分析(已省略界符,标识符,操作符的判断):
void LexAnalysis () {
while(未到文本尾)
if (当前字符 == 空格 or 制表符 or 回车) { //删除无用字符
清空临时部分词
continue;
}
if (当前字符 == 界符) {
将当前字符添加到界符词组
continue;
}
if (当前字符 == 字母 or 下划线) { //标识符或while关键字
while (当前字符 == 字母 or 数字 or 下划线) {
临时部分词 +=当前字符;
}
if (临时部分词 != "while") {
将当前字符添加到标识符词组
}else {
将当前字符添加到关键符词组
}
清空临时部分词
Continue;
}
if (当前字符 == 运算符) {
// + - * / = && || += -= ++ -- == >= <= > <
将当前字符添加到操作符词组
continue;
}
if (当前字符 == 数字) { //数字开头的只能是常数
while (当前字符 == 数字) {临时部分词 += 当前字符;}
将当前字符添加到数字词组
continue;
}
}
}
5.2 语法分析
典型递归程序(表达式)伪代码:
int ParseB() { //B→i=C;B | 空
if (当前词语 == "while") {
ParseS();
return;
}
if (当前词语类型 == "常数" && 下一个词语类型 == "标识符") 报错
if (当前词语类型 == 标识符) {
if(当前标识符不再表中) 报错
}else {return;}
Switch(当前词语){
case = : 操作类型 = =; //临时变量存放操作类型
case += : 操作类型 = +=;
case -= : 操作类型 = -=;
……
}else {
return;
}
Cval = ParseC();
if (当前词语 != ";") {报错}
switch(操作类型){
case = : Bval = Cval;
case += : Bval = Bval + Cval;
case -= : Bval = Bval - Cval;
……
}
上述结果填入四元式
if (当前词语类型 == "标识符" && 使用大括号 ) {
B1val = ParseB();
}
else {
根据代码回填到while语句的跳转属性
if (当前词语 != "}") {报错}
}
if (当前词语类型 == "标识符")
B1val = ParseB();
}
}
5.3 语义分析
布尔表达式逻辑值计算:
int BExp(string op, string a, string b) {
int A,B;
if(a为临时变量 || a为标识符){
A = lookupval(a); //符号表中查找标识符或临时变量a的值
}else
A = atoi(a.c_str()); //string转int
if(b为临时变量 || b为标识符){
B = lookupval(b); //符号表中查找标识符或临时变量b的值
}else
B = atoi(b.c_str()); //string转int
switch(op){
case == : return A == B ? 1:0; //逻辑真值为1,假值为0
case >= : return A >= B ? 1:0;
case <= : return A <= B ? 1:0;
case > : return A > B ? 1:0;
case < : return A < B ? 1:0;
case && : return A && B ? 1:0;
case || : return A || B ? 1:0;
}
}
六.软件的测试方法和测试结果四元式生成结果截图:
词法分析 & 四元式输出上图测试代码:
i=6;
while (i == 5) {
a=1;
c=(1+1)*2;
haha = (a+c)/b+2*5;
}
b=2+1;
c=5*6;
测试结果:
●支持while的大括号中多个表达式的执行
●支持大括号后表达式的执行
●While中逻辑表达式正确跳转
●支持复合表达式的赋值和布尔值判断
鲁棒性测试:
测试代码:
while (i == 1 && (a+b)>2 ) {
_E6 += a*5+d++;
t = (a+c)/(b+2*5);
}
结果截图:
出错时提示错误代码,错误描述以及错误行号。
七.实践总结(本设计的评价、特点、不足、收获与体会等)7.1 设计的评价
本系统采用实现起来较为简单的递归下降法,对文法的要求较高。
支持常见的整数属性的加减乘除计算,支持常见的逻辑运算:&& 和 ||。
设计中考虑到了while语句的嵌套问题以及while有无大括号的不同情况,大括号中多条语句的情况。
在鲁棒性方面也做了大部分的考虑并输出对应的错误情况。
7.2 设计的不足
由于课时和安排冲突,以及个人水平的原因,本次课程设计仍然离真正的高级语言的编译系统还有着难以逾越的距离。
例如某些时候的错误检测不能及时反馈给用户,编译的效率在代码量较多时会明显下降,部分操作符的功能还并未实现,属性文法仍有可完善的地方。
7.3 收获和体会
编译原理是计算机专业的一门重要专业课,介绍编译程序构造的一般原理和基本方法。
本次课程设计的内容主要是词法分析、语法分析、语法制导翻译、中间代码生成。
课设在理论课程的基础上更加理解并掌握编译原理的实现。
在本次的课程设计中,电脑前奋战数小时,出现了很多问题,查阅了很多资料,解决了一些,空出了一些,也增强了自己的编码能力。
编译原理是计算机专业设置的一门重要的专业课程。
尽管编译原理已经发展到瓶颈,难以进步,专攻编译原理的技术人员也并不多,但是这门课在理论、技术、方法上都对学生提供了系统而有效的训练,作为优秀的武汉理工学子,学习原理性的课程才能进行更高的创新,同时也有利于提高我们就业时所展现的素质和能力。
7.3 后续学习
本学期正好选修了汇编语言,将汇编语言与编译原理课程结合学习,可在网络上寻找四元式到汇编语言翻译的学习资料,进一步将本次课设所生成的四元式中间代码翻译成汇编代码进行调试运行。
之后可根据自己需要创造属于自己的高级语言,与自然语言处理结合,例如输入一段文本要求即可生成对应的计算机程序。
本科生实践课程成绩评定表
指导教师签字:
年月日。