带括号的四则混合运算编译原理课程设计报告Word文件下载.docx
《带括号的四则混合运算编译原理课程设计报告Word文件下载.docx》由会员分享,可在线阅读,更多相关《带括号的四则混合运算编译原理课程设计报告Word文件下载.docx(33页珍藏版)》请在冰点文库上搜索。
03.EEOPADDT
04.EEOPSUBT
05.TP
06.TTOPMULP
07.TTOPDIVP
08.PINTC
09.PFLOATC
10.PLPARENERPAREN
基本要求:
1、以ASSIGN作为文法结束符号;
2、应用词法分析技术识别单词;
3、应用SLR
(1)分析技术判别表达式的合法性;
4、应用尾动作文法技术计算表达式的类型与值;
5、要求表达式的类型与值严格一致。
三、课程设计报告要求
1、课程设计报告必须按本系规定的格式要求打印成册;
2、课程设计报告每人一份,正文必须包含如下几个方面的内容:
1)基本设计思想;
2)主要数据结构;
3)总结与体会。
3、课程设计报告装订顺序:
封面、任务书、目录、正文、源程序清单。
四、选题及考核办法
1、一人一组,学号为奇数者做课题一,学号为偶数者做课题二。
2、成绩考核按个人课题完成情况、设计报告质量及对课程设计的态度等综合评定。
五、设计进度安排
1、讲课时间安排:
18周周一上午
2、上机调试时间安排:
18周周三周四上午
3、答辩时间安排:
18周周五上午
4、其余时间:
查阅资料,确定方案,设计课题相关程序。
目录
一设计内容与设计要求6
1.1课程设计的性质和目的6
1.2设计课题6
1.3进度安排7
二基本设计思想8
2.1词法分析8
2.2语法分析9
三主要数据结构14
四调试运行结果15
五总结与体会16
一设计内容与设计要求
1.1课程设计的性质和目的
1.2设计课题
INTC→D+
FLOATC→(D+.D+)|(D+.)|(.D+)
FLOATC→((D+.D+)|(D+.)|(.D+)|(D+))(E|e)(+|−|λ)D+
OPADD→+
OPSUB→−
OPMUL→*
OPDIV→/
LPAREN→‘(’
RPAREN→‘)’
LINE→‘\n’
ASSIGN→=
01.S→E
02.E→T
03.E→EOPADDT
04.E→EOPSUBT
05.T→P
06.T→TOPMULP
07.T→TOPDIVP
08.P→INTC
09.P→FLOATC
10.P→LPARENERPAREN
1.3进度安排
计算机1181班:
第18周:
星期一8:
00——12:
002:
30——5:
30
星期二8:
二基本设计思想
本计算器采用编译原理的方法构建,先用有穷自动机辅助进行词法,把字符串形式的算术表达式的格式标准化,分离出一个个词法单元。
然后采用SLR
(1)文法分析法进行文法分析,检查表达式的正确性。
并在过程中计算出已分析出的部分表达式的值。
最终得出表达式的值。
2.1词法分析
由于各词法元素都可以用正则表达式来表示,所以做词法分析时采用正则表达式形式化表示各个元素以便于程序实现。
四则混合运算各词法元素的正则表达式如下所示:
INTC→D+
FLOATC→D+.D+|D+.|.D+
FLOATC→(D+.D+|D+.|.D+|D+)(E|e)(+|−|λ)D+
正则表达式把能够把各词法元素的格式用形式化的方法表示出来,是格式的判断能够用程序来完成,但最终写程序时,用正则表达式直接分析对人来说仍然是不太直接,不方便,所以把正则表达式转化为有限自动机,以是写程序实现词法分析方便。
如图1.1为四则混合运算的有限自动机。
图2.1四则混合运算的有限自动机
2.2语法分析
四则混合运算算术表达式符合SLR
(1)文法但不符合LR(0)文法,所以语法分析采用SLR
(1)语法分析方法。
四则混合运算算术表达式的产生式如下:
通过文法的产生式可以把四则混合运算算术表达式的文法中各个非终极符的FIRST集合和FOLLOW集合一一求出来,以便进行下一步分析。
其FIRST集和FOLLOW集如表1.1所示:
表2.1四则混合运算算术表达式文法中非终极符的FIRST集和FOLLOW集
符号
FIRST集合
FOLLOW集合
S
INTCFLOATCLPAREN
ASSIGN
E
ASSIGNOPADDOPSUBRPAREN
T
ASSIGNOPADDOPSUBRPARENOPMULOPDIV
P
根据文法的产生式和FIRST集、FOLLOW集即可确定文法的规约活前缀DFA(SLR
(1)_DFA),如图1.2所示。
S→·
E→·
EOPADDT
EOPSUBT
T→·
TOPMULP
TOPDIVP
P→·
INTC
FLOATC
LPARENERPAREN
ES1
TS2
PS3
INTCS4
FLOATCS5
LPARENS6
2
E→T·
T→T·
OPMULP
OPDIVP
ASSIGNR2
OPADDR2
OPSUBR2
RPARENR2
OPMULS9
OPDIVS10
3
T→P·
ASSIGNR5
OPADDR5
OPSUBR5
RPARENR5
OPMULR5
OPDIVR5
6
P→LPAREN·
ERPAREN
ES11
7
E→EOPADD·
TS12
5
P→FLOATC·
ASSIGNR9
OPADDR9
OPSUBR9
RPARENR9
OPMULR9
OPDIVR9
4
P→INTC·
ASSIGNR8
OPADDR8
OPSUBR8
RPARENR8
OPMULR8
OPDIVR8
1
S→E·
E→E·
OPADDT
OPSUBT
ASSIGNR1
OPADDS7
OPSUBS8
图2.2SLR
(1)_DFA
9
T→TOPMUL·
P
PS14
10
T→TOPDIV·
PS15
8
E→EOPSUB·
TS13
14
T→TOPMULP·
ASSIGNR6
OPADDR6
OPSUBR6
RPARENR6
OPMULR6
OPDIVR6
16
P→LPARENERPAREN·
ASSIGNR10
OPADDR10
OPSUBR10
RPARENR10
OPMULR10
OPDIVR10
15
T→TOPDIVP·
ASSIGNR7
OPADDR7
OPSUBR7
RPARENR7
OPMULR7
OPDIVR7
13
E→EOPSUBT·
T→T·
OPMULP
OPDIVP
ASSIGNR4
OPADDR4
OPSUBR4
RPARENR4
12
E→EOPADDT·
ASSIGNR3
OPADDR3
OPSUBR3
RPARENR3
11
P→LPARENE·
RPAREN
E→E·
RPARENS16
根据SLR
(1)_DFA即可用构造文法的相应action表和goto表如表1.3和表1.3所示。
表2.2SLR
(1)_action
OPADD
OPSUB
OPMUL
OPDIV
LPAREN
RPAREN
S4
S5
S3
S7
S8
R1
R2
R5
R8
R9
S6
S16
R3
S9
S10
R4
R6
R7
R10
表2.3SLR
(1)_goto
有了文法的action表和goto表,就可以根据表中所指示的状态转移情况,编写程序并完成相应功能。
三主要数据结构
程序的主要数据结构为栈。
1词法分析中用一个栈来保存分析中到达的状态。
staticcharlexstack[BUFSIZE];
2语法分析中一个状态栈用来保存已到达的状态,一个符号栈用来保存已读入的符号或规约产生的符号中还没被规约掉的语法符号。
struct{
intstate;
TokenTypetoken;
}stack[BUFSIZE];
由于状态栈,与符号栈的出入栈是同步的所以两个栈写在同一个结构中。
当读入一个字符或前一个规约产生一个符号,之后若不能直接规约这将该符号入栈到token并跳转到新的状态,原状态入栈state。
当一个活前缀被规约,被规约符号出栈,相应状态也出栈。
四调试运行结果
正确的输入结果,得到值35
五总结与体会
这次课程设计的过程我遇到了很多的困难,不过有足够的时间给我看书和查资料,从这次课程设计的过程我也看到了自己学习的理论知识的不足。
通过这次课程设计我对于编译原理有了更加深入的了解,也懂得了构造一种语言的编译器所要考虑的过程,还有锻炼了我看别人写的大型的程序的能力。
进一步加强了我写程序和读程序的能力。
这次实验用是C语言,对此并不熟练,所以在修改的过程中遇到了一些比较难的问题,但在老师与同学们的讨论后才得以解决。
同时,也就此机会熟悉和回忆了了C语言,为今后进行C++设计积累了不少的经验。
这次实验我做了五个内容,其中在增加一些语句的时候遇到的困难比较大,不过通过查资料和与同学讨论我最后解决了这个问题,也学到了很多的东西,在这次实验中充分理解了团结就是力量。
在编译程序实现的过程中反复使用了递归调用的思想,且也使用了模块化处理问题的思想,使用模块化的思想关键是在抽象阶段要抽象出对应的模块,且模块的层次必须是清晰的。
在实现此程序中,由于要实现关键字和符号表中字段的搜索,实现中就必须注意快速查找的方法,而在实现的过程中多次用到了二分搜索的方法,这是个比较快的搜索方法。
由于此程序的实现相对比较复杂,且不方便调试,改进时可以把此程序的词法分析,语法分析和执行原代码作为单独的测试程序来测试,这样也方便大家来调试。
通过本次的课设我知道了一个算法的设计是需要静下心来仔细的研究的,且实现中必须先了解程序的整个流程,也就是说在编程中首先必须看懂那些对应的UML图,只有在图的指导下,编程中才不会盲目,也有一定的方向性。
同样在编程中必须注意代码的规范,多写一些对应的注释是很必要的,要时刻想这代码并不是给你自己看的,而是必须要给别人看,因此我觉得代码的规范是相当重要的。
附录(源程序)
#include<
stdio.h>
stdlib.h>
string.h>
#defineBUFSIZE256
staticFILE*in;
staticFILE*out;
typedefenum{NONE=-3,FEOF,ERROR,
INTC,FLOATC,OPADD,OPSUB,OPMUL,OPDIV,LPAREN,RPAREN,LINE,ASSIGN,
S,E,T,P//文法的非终极符11-13
}LexType;
#defineMacro_caseD'
0'
:
case'
1'
2'
3'
4'
5'
\
case'
6'
7'
8'
9'
LexTypelex(char*word)
{staticintlexstacktop=-1;
staticcharlextryword[BUFSIZE];
staticLexTypelextryflag[BUFSIZE];
staticcharlexcurch='
'
;
staticLexTypelexstateflag[]={ERROR,INTC,FLOATC,ERROR,ERROR,ERROR,FLOATC,OPADD,OPSUB,OPMUL,OPDIV,LPAREN,RPAREN,LINE,ASSIGN};
intstate=0;
intlexindex=0;
do{if(lexstacktop==-1)
lexcurch=fgetc(in);
elselexcurch=lexstack[lexstacktop--];
}while(lexcurch=='
||lexcurch=='
\t'
);
while
(1)
{switch(state){
case0:
switch(lexcurch){
caseMacro_caseD:
state=1;
break;
.'
state=3;
+'
state=7;
-'
state=8;
*'
state=9;
/'
state=10;
('
state=11;
)'
state=12;
\n'
state=13;
='
state=14;
default:
state=-1;
};
break;
case1:
state=2;
E'
e'
state=4;
case2:
case3:
case4:
state=6;
state=5;
case5:
case6:
}
if(state==-1)break;
lextryword[lexindex++]=lexcurch;
/*maybeoverflow*/
lextryflag[lexindex-1]=lexstateflag[state];
if(lexstacktop==-1)lexcurch=fgetc(in);
if(lexindex==0&
&
lexcurch==EOF)returnFEOF;
lextryword[lexindex]=lexcurch;
lextryflag[lexindex]=ERROR;
while(lexindex>
0&
lextryflag[lexindex]==ERROR)
lexstack[++lexstacktop]=lextryword[lexindex--];
lextryword[lexindex+1]=0;
strcpy(word,lextryw