武汉理工大学编译原理课程设计中国好学长系列之小灰灰的爸爸.docx
《武汉理工大学编译原理课程设计中国好学长系列之小灰灰的爸爸.docx》由会员分享,可在线阅读,更多相关《武汉理工大学编译原理课程设计中国好学长系列之小灰灰的爸爸.docx(28页珍藏版)》请在冰豆网上搜索。
武汉理工大学编译原理课程设计中国好学长系列之小灰灰的爸爸
学号:
课程设计
题目
布尔表达式翻译为逆波兰式的算法实现
学院
计算机科学与技术学院
专业
软件工程
班级
中国好学长系列
姓名
小灰灰的爸爸
指导教师
何九周
2014
年
1
月
2
日
目录
课程设计任务书1
1引言2
2概述3
2.1设计题目3
2.2设计目的3
2.3设计任务内容3
3设计环境与工具4
4设计原则4
4.1基本方法4
4.2属性文法4
5简要的分析与概要设计4
6详细的算法描述,框图5
6.1主要数据结构的设计5
6.2全局变量设计7
6.3递归下降得到推导过程7
6.4递归下降得到四元式序列11
6.5分析四元式序列生成逆波兰式14
7软件的测试方法和测试结果16
8设计的特点、不足收获与体会16
8.1设计的特点16
8.2设计的不足16
8.3收获与体会16
9参考文献16
附录:
本科生课程设计成绩评定表
课程设计任务书
学生姓名:
专业班级:
指导教师:
何九周工作单位:
计算机科学与技术学院
题目:
布尔表达式翻译为逆波兰式的算法实现
初始条件:
程序设计语言:
主要使用C语言的开发工具,或者采用LEX、YACC等工具,也可利用其他熟悉的开发工具。
算法:
可以根据《编译原理》课程所讲授的算法进行设计。
要求完成的主要任务:
(包括课程设计工作量及其技术要求,说明书撰写等具体要求)
1.明确课程设计的目的和重要性,认真领会课程设计的题目,读懂课程设计指导书的要求,学会设计的基本方法与步骤,学会如何运用前修知识与收集、归纳相关资料解决具体问题的方法。
严格要求自己,要独立思考,按时、独立完成课程设计任务。
2.主要功能包括:
利用LR分析法编制、调试其语法及语义分析程序,生成的中间代码为逆波兰式。
编制好分析程序后,设计若干用例,上机测试并通过所设计的分析程序。
3.进行总体设计,详细设计:
包括算法的设计和数据结构设计。
系统实施、调试,合理使用出错处理程序。
4.设计报告:
要求层次清楚、整洁规范、不得相互抄袭。
正文字数不少于0.3万字。
包含内容:
①课程设计的题目。
②目录。
③正文:
包括引言、需求分析、总体设计及开发工具的选择,设计原则(给出语法分析方法及中间代码形式的描述、文法和属性文法的设计),数据结构与模块说明(功能与流程图)、详细的算法设计、软件调试、软件的测试方法和结果、有关技术的讨论、收获与体会等。
④结束语。
⑤参考文献。
⑥附录:
软件清单(或者附盘)。
时间安排:
消化资料、系统调查、形式描述1天
系统分析、总体设计、实施计划3天
撰写课程设计报告书1天
指导教师签名:
2014年1月2日
系主任(或责任教师)签名:
2014年1月2日
布尔表达式翻译为逆波兰式的算法实现
1引言
实践离不开理论,而理论是为了实践,这一点在软件设计的学习过程中显得尤为重要。
而《编译原理》是一门研究设计和构造编译程序原理和方法的课程,是计算机各专业的一门重要的专业基础课。
编译原理这门课程蕴含着计算机学科中解决问题的思路、形式化问题和解决问题的方法,对应用软件和系统软件的设计与开发有一定的启发和指导作用。
“编译原理”是一门实践性较强的课程,要掌握这门课程中的思想,就必须要把所学到的知识付诸实践。
而课程设计是将理论与实践相互联系的一种重要方式。
本文是《编译原理》中的“布尔表达式翻译为逆波兰式的算法实现”课程设计的说明书。
2概述
2.1设计题目
布尔表达式翻译为逆波兰式的算法实现
2.2设计目的
课程设计是将理论加以实践较好的方法,也对学生的一种全面综合训练,是与课堂听讲、自学和练习相辅相成的必不可少的一个教学环节。
通常,设计题中的问题比平时的练习题要复杂,也更接近实际。
编译原理这门课程安排的课程设计的目的是旨在要求学生进一步巩固课堂上所学的理论知识,深化理解和灵活掌握教学内容,选择合适的数据逻辑结构表示问题,然后编制算法和程序完成设计要求,从而进一步培养学生独立思考问题、分析问题、解决实际问题的动手能力。
2.3设计任务内容
针对布尔表达式的二义性文法:
BBandB|BorB|notB|(B)|true|false|iropi
将文法拓广为G’[B’]:
(0)B’B
(1)BBandB
(2)BBorB
(3)BnotB
(4)B(B)
(5)Btrue
(6)Bfalse
(7)Biropi
利用LR分析法编制、调试其语法及语义分析程序,生成的中间代码为逆波兰式。
编制好分析程序后,设计若干用例,上机测试并通过所设计的分析程序。
3设计环境与工具
VisualC++
4设计原则
4.1基本方法
在本程序中,要求利用LR分析法编制、调试其语法及语义分析程序,生成的中间代码为逆波兰式。
编制好分析程序后,设计若干用例,上机测试并通过所设计的分析程序。
4.2属性文法
BTB′B’.in=T.type
B′andTB′B’.in=T.typeaddtype(and,entry,B.in)
B′εB’.val=ε
TFTT.in=F.type.
T′orFT′T’.in=F.typeaddtype(or,entry,B.in)
T′εT’val=ε
FnotFF.val=not.F.val
FtrueF.val=true
FfalseF.val=false
F(B)F.val=B.val
FiropiF.val=i.lexvalropi.lexvaladdtype(i,entry,l.in)
5简要的分析与概要设计
该程序共包括3个模块,第一个模块是对输入的布尔语句进行递归下降的分析,从而得出从文法到该布尔语句的推导过程,第二个模块是使用递归下降的方法,该布尔语句的四元式序列,第三个模块对四元式序列进行扫描并分析每个四元式的结构特点,并据此将四元式转化为逆波兰式。
main函数的流程图如下:
在开始进行本次实验中,本来计划在递归下降分析的过程中就得到逆波兰式,但是经过多次尝试之后总是存在错误,所以采用先得到四元式序列,再根据四元式序列生成逆波兰式这种效率比较低的方法。
6详细的算法描述,框图
6.1主要数据结构的设计
逆波兰式结构体
这个结构体的对象用来存储逆波兰式,它的成员是一个word数组
structnipolan
{
wordnibolan[100];
}n;
四元式类
在该类中,要包含四元式中的四个元素,运算结果,两个运算数以及一个运算符号
classquad
{
public:
charresult[8];
chararg1[8];
charop[8];
chararg2[8];
voidprint()//输出该四元式
{
cout<}
}q[20];
Word结构体
这个结构体的对要用来存储单个单词,包括一个字符串成员。
structword
{
charw[10];
voidprint()
{
cout<";
}
}wr[200];
翻译器类
用来存储翻译过程中的各个变量以及声明主要的函数:
classinterpreter
{
private:
ifstreamSourceFile;
charbuffercode[200];//存放源码的缓冲区
intsyn;
intcurrent;//buffercode中当前读到的字符下标
chartoken[8];//记录当前读到的单词
public:
voidscaner();voidB();voidB1();voidT();voidF();voidT1();voidrun();voidread();voidbolon();voidtoword();char*factor();char*expression();char*term();voidbolan();voidreset()
{
current=0;
};
voidrun1()
{
scaner();
expression();
};
};
6.2全局变量设计
inttear=51;//逆波兰式尾部
inthead=50;//逆波兰是首部
intnumberoftemp=0;//临时变量个数
intnumberofquad=0;//四元式个数
6.3递归下降得到推导过程
根据递归下降的思想,对于文法中的每个非终结符编写一个函数,每个函数的功能是识别由该非终结符所表示的语法成分。
由于描述语言的文法常常是递归定义的,因此相应的这组函数必然以相互递归的方式进行调用。
该过程的基本思想为每执行一个非终结符对应的函数就根据读入的单词符号来写入该非终结符对应的推出式。
该功能的入口函数run1的流程图如下:
非终结符B对应的函数B()
该函数首先要写入B=>TB’,然后执行T()与B1()
流程图为
非终结符T对应的函数T()
该函数首先要写入T=>FT’,然后执行F()与T1()
流程图为:
非终结符B’对应的函数B1()
在该函数中如果读入的下一个单词是“and”则写入B’=>andTB’.否则,要写入B’推出了空串。
流程图为:
非终结符T’对应的函数T1()
在该函数中如果读入的下一个单词是“or”则写入T’=>orFT’.否则,要写入T’推出了空串。
流程图为:
非终结符F对应的函数F()
由于非终结符F对应的推出式比较多,所以该函数的分支也比较多,当读入“not”时,则写入F=>notF并执行F()函数,当读入”true”或者”false”时,则要写入F=>true或者F=>false当读入的字符为”(”时,则写入F=>(B),并执行B()函数,当读入的单词为i时,要写入F=>iropi.
流程图为:
在完成该功能时,推到过程存入到tuidao类生成的对象数组中。
6.4递归下降得到四元式序列
生成四元式必须分析布尔语句,and语句以及最小的分析单元三个部分expression()函数分析布尔语句,term()分析and语句,unit()分析最小单元
该过程的入口函数run1()流程图如下:
expression()函数
该函数首先调用了一个term函数,如果下一个读到单词是“or”则分析or后面的一个term并将or和两个term写入到四元式序列中,如果读到的不是“or”则只把term返回到四元式序列中。
流程图如下:
term()函数
该函数首先调用了一个factor函数,如果下一个读到单词是“and”则分析and后面的一个factor并将or和两个factor写入到四元式序列中,如果读到的不是“and”则只把factor返回到四元式序列中。
流程图为:
unit()函数
在该函数中,分析了优先级最高的运算或者是单个终结符,如果读入的是true或者false则直接返回token,如果读入的是i则把iropi写入到四元式序列中,如果读入的是not,则分析not后面的expression(),并将not以及expression()写入到四元式中,返回生成的newtemp
流程图:
该过程结束后,布尔语句对应的四元式存放在quad类生成的对象数组q中.
6.5分析四元式序列生成逆波兰式
本过程根据四元式序列以及每一个四元式的类型,将四元式中的信息按照一定规则写入到逆波兰式中,主要函数为bolan()函数,bolan函数将四元式序列从头到尾扫描一遍,对于每一个四元式序列根据其操作数是临时变量还是终结符将终结符以及操作符按照逆波兰式规则写入到逆波兰式类生成的对象n中。
当当前四元式类型为临时变量=临时变量OP临时变量是,则直接将op插入到逆波兰式尾部。
当当前四元式类型为临时便令=arg1oparg2时则按照arg1,arg2,op的顺序将他们插入逆波兰式的尾部。
当当前四元式类型为临时便令=临时变量oparg1时则按照arg1,,op的顺序将他们插入逆波兰式的尾部。
当当前四元式类型为临时便令=arg1op临时变量时则将op的顺序将他们插入逆波兰式的尾部,将arg1插入到逆波兰式的首部。
bolan函数的流程图为:
本过程结束之后,逆波兰式存放在nibolan类定义的对象n中。
7软件的测试方法和测试结果
输入一个字符串,执行改程序,观察产生的四元式以及逆波兰式是否正确。
8设计的特点、不足收获与体会
8.1设计的特点
该程序不仅按照题目要求的到了翻译的逆波兰式,而且还求出了布尔语句的推导过程和四元式,实现的功能比较多,对翻译的过程和结果有一个比较全面的描述。
程序的逻辑明确,易于理解。
8.2设计的不足
在本次课程设计的程序中存在着两个主要问题是没有在递归下降的过程中直接求出逆波兰式,而是根据生成的四元式序列产生的逆波兰式,虽然可以达到题目的要求,但是程序的效率比较低。
另外,在递归下降生成逆波兰式的过程中,由于最小单元函数中读入”not”以及”(”的分支中出现了问题,导致了在调试过程中not语句以及括号中语句必须放在最后,否则在分析完该单元之后程序不再继续向后扫描。
导致了布尔语句分析不全。
8.3收获与体会
通过本次课程设计,我学会了将理论知识运用到实际编码中,同时也知道严谨细心对于一个程序员来说有多么重要。
这次课程设计在让我对《编译原理》更加熟悉的同时也训练了我的耐心和毅力。
虽然程序写得很一般,有的地方甚至有些小错误,但是我仍然收获了很多平时学习中没有学到的知识,锻炼了平时学习中没有的学习和实践能力。
9参考文献
《编译原理》(第二版),主编:
吕映芝、张素琴、蒋维杜,出版社:
清华大学出版社,出版时间:
2004年11月
《编译原理》,主编:
张幸儿,出版社:
科学出版社,出版时间:
1999年4月
本科生课程设计成绩评定表
班级:
姓名:
学号:
序号
评分项目
满分
实得分
1
学习态度认真、遵守纪律
10
2
设计分析合理性
10
3
设计方案正确性、可行性、创造性
20
4
设计结果正确性
40
5
设计报告的规范性
10
6
设计验收
10
总得分/等级
评语:
注:
最终成绩以五级分制记。
优(90-100分)、良(80-89分)、中(70-79分)、
及格(60-69分)、60分以下为不及格
指导教师签名:
2014年1月 日
附录:
代码
不要求加入实验报告,上传时考虑到如果分成多个文档可能会让大家难以找到,就贴在后面了。
#include
#include
#include
intkk;
inttear=51;
inthead=50;
intnumberoftemp=0;
intnumberofquad=0;
classquad
{
public:
charresult[8];
chararg1[8];
charop[8];
chararg2[8];
voidprint()
{
cout<}
}q[20];
voidqemit(chara[],charb[],charc[],chard[])
{
strcpy(q[numberofquad].result,a);
strcpy(q[numberofquad].arg1,b);
strcpy(q[numberofquad].op,c);
strcpy(q[numberofquad].arg2,d);
numberofquad++;
}
char*newtemp()
{
char*p;
inttemp=numberoftemp;
p=newchar[8];
p[0]='t';
for(inti=0;;i++)
{
p[++i]=char(temp%10+48);
temp=temp/10;
if(temp==0){p[i+1]='\0';break;}
}
numberoftemp++;
returnp;
};
structword
{
charw[10];
voidprint()
{
cout<";
}
}wr[200];
structnipolan
{
wordnibolan[100];
}n;
inttcount=0;
intwcount=0;
char*rwtab[9]={"true","not","false","(",")","rop","i","or","and"};
classtuidao
{
public:
chara[10];
charb[10];
charc[10];
chard[10];
voidemit(char*m,char*n,char*p,char*q);
voidprint(){cout<"<}t[100];
voidtuidao:
:
emit(char*m,char*n,char*p,char*q)
{
strcpy(a,m);
strcpy(b,n);
strcpy(c,p);
strcpy(d,q);
}
classinterpreter
{
private:
ifstreamSourceFile;
charbuffercode[200];
intsyn;
intcurrent;
chartoken[8];
public:
voidscaner();
voidB();
voidB1();
voidT();
voidF();
voidT1();
voidrun();
voidread();
voidbolon();
voidtoword();
char*unit();
char*expression();
char*term();
voidbolan();
voidreset()
{
current=0;
};
voidrun1()
{
scaner();
expression();
};
};
voidbolan()
{
strcpy(n.nibolan[tear].w,q[0].arg1);tear++;
strcpy(n.nibolan[tear].w,q[0].arg2);tear++;
strcpy(n.nibolan[tear].w,q[0].op);tear++;
for(inti=0;i{
for(intj=i-1;j>=0;j--)
{
if(strcmp(q[i].arg1,q[j].result)==0)
{
if(strcmp(q[i].arg2,q[j+1].result)==0){strcpy(n.nibolan[tear].w,q[i].op);tear++;break;}
else
{
strcpy(n.nibolan[tear].w,q[i].arg2);tear++;
strcpy(n.nibolan[tear].w,q[i].op);tear++;
break;
}
}
if((strcmp(q[i].arg1,q[j].result)!
=0)&&(strcmp(q[i].arg2,q[j+1].result)==0))
{
strcpy(n.nibolan[tear].w,q[i].op);tear++;
strcpy(n.nibolan[head].w,q[i].arg1);head--;
break;
}
if((strcmp(q[i].arg1,q[j].result)!
=0)&&(strcmp(q[i].arg2,q[j].result)!
=0))
{
strcpy(n.nibolan[tear].w,q[i].arg1);tear++;
strcpy(n.nibolan[tear].w,q[i].arg2);tear++;
strcpy(n.nibolan[tear].w,q[i].op);tear++;
break;
}
}
}
}
voidinterpreter:
:
toword()
{
current=0;
inti=0;
while(buffercode[current]!
='#')
{
scaner();
strcpy(wr[wcount].w,token);
wcount++;
i++;
}
};
voidinterpreter:
:
read()
{
cin.getline(buffercode,200);
cout<}
voidinterpreter:
:
run()
{
current=0;
{
scaner();
B();
}
}
voidinterpreter:
:
B()
{
t[tcount].emit("B","","T","B'");
tcount++;
T();
B1();
}
voidinterpreter:
:
B1()
{
if(strcmp(token,rwtab[8])==0){t[tcount].emit("B'","and","T","B'");tcount++;scaner();T();B1();scaner();}
elset[tcount].emit("B'","empty","","");
}
voidinterpreter:
:
T()
{
t[tcount].emit("T","","F","T'")