编译原理课程设计.docx

上传人:b****7 文档编号:8965432 上传时间:2023-02-02 格式:DOCX 页数:41 大小:159.75KB
下载 相关 举报
编译原理课程设计.docx_第1页
第1页 / 共41页
编译原理课程设计.docx_第2页
第2页 / 共41页
编译原理课程设计.docx_第3页
第3页 / 共41页
编译原理课程设计.docx_第4页
第4页 / 共41页
编译原理课程设计.docx_第5页
第5页 / 共41页
点击查看更多>>
下载资源
资源描述

编译原理课程设计.docx

《编译原理课程设计.docx》由会员分享,可在线阅读,更多相关《编译原理课程设计.docx(41页珍藏版)》请在冰豆网上搜索。

编译原理课程设计.docx

编译原理课程设计

宁波大红鹰学院

信息工程学院

课程设计报告

课程名称

编译原理

实验名称

基于LL

(1)法的条件语句语法语义分析程序

 

姓名

学号

专业

班级

地点

教师

目录

一.系统需求分析------------------------------------------------------------------------------------

二.概念模型设计------------------------------------------------------------------------------------

三.逻辑模型设计------------------------------------------------------------------------------------

四.物理模型设计------------------------------------------------------------------------------------

五.实验结果分析------------------------------------------------------------------------------------

六.心得体会--------------------------------------------------------------------------------------------

七.源代码------------------------------------------------------------------------------------------------

 

一.系统需求分析

通过设计,编制,调试一个语法及语义分析程序,加深对语法及语义分析原理的理解。

IF〈布尔表达式〉THEN〈赋值语句〉ELSE〈赋值语句〉

其中

(1)、可以选择递归下降法、LL

(1)、算符优先分析法、LR法完成以上任务,中间代码选用四元式。

(2)、写出符合分析方法要求的文法,给出分析方法的思想,完成分析程序设计。

(3)、编制好分析程序后,设计若干用例,上机测试并通过所设计的分析程序。

 

二.概念模型设计

首先设计一个IF-THEN-ELSE的LL

(1)文法。

推导出该文法的预测分析表,在此基础上编写能识别该IF-THEN-ELSE的语法分析程序。

程序要求有三部分组成,即词法分析、语法分析、以及语义分析。

其中词法分析部分要求完成对输入程序的关键字、标识符、常数、运算符进行识别;并分析词法分析的结果,检查程序输入的关键字是否为符合设计文法的关键字,检查标志符是否是合法标志符,识别运算符的种类。

语法分析部分主要是以算符优先文法的设计思想和步骤完成对词法分析结果的的语法分析工作,判断输入的程序是否符合设计的IF-THEN-ELSE文法。

在语法分析通过的基础上进行语义分析,其主要任务是完成对语法分析后的程序的语义分析,根据语法制导翻译去翻译输入的程序,从而得到程序的中间代码表示形式——四元式。

 

词法分析、语法分析、以及语义分析的系统流程图如下所示:

 

 

Main函数流程图:

输出单词表

 

语法分析程序的详细数据流图:

 

(1)词法分析

A词法分析器的功能和输出形式

输入:

所给文法的源程序字符串

输出:

二元组(单词种别,单词符号的属性值)构成的序列

B.待分析的简单语言的词法

因为是模拟简单编译器,所以就以C语言的小型子集作为模拟编译器的词法.

模拟程序语言的单词符号可分为下列五种;

关键字:

{(相当于Pascal语言中的begin),if,else,while,}(相当于Pascal语言中的end)所有的关键字都是小写字母.

运算符:

+,-,*,/,=,<,<=,==,>,>=,<>,&&,||,!

界符:

逗号,分号,左圆括号,右圆括号,#

常数:

在这里只涉及到int型常量

其他单词是标识符(ID)和整形常数(NUM),通过以下正规式定义:

ID=letter(letter|digit)*

NUM=digitdigit*

空格由空白,制表符和换行符组成,空格一般用来分隔ID,NUM,运算符,界符和关键字,词法分析阶段通常会被过滤掉。

C.各种单词符号的种别码:

单词符号

种别码

单词符号

种别码

If

0

/

17

else

1

=

18

while

2

&&

19

{

3

||

20

}

4

!

21

;

6

rop

22

#

8

23

+

14

24

-

15

letter(letter|digit)*

25

*

16

digitdigit*

26

值得说明的是;

当种别码为22,也就是六种运算符时,会根据一个POS的值(0-5)来定位到底是六种运算符中的哪一种.当pos=0时rop=‘<=’;

当pos=1时rop=‘<’;

当pos=2时rop=‘>=’;

当pos=3时rop=‘>’;

当pos=4时rop=‘<>’;

当pos=5时rop=‘==’;

D.词法分析的设计思想:

算法的基本任务是从字符串表示的源程序中识别出其具有独立意义的单词符号,其基本思想是根据扫描到的单词符号的第一个字符的种类,拼出相应的单词符号。

(2)语法分析

语法分析要处理的输入是词法分析的输出即单词序列。

该部分主要用到两个栈,一个用来保存单词标志号的状态栈另一是用来保存单词本身信息的符号栈。

程序从词法分析输出的单词序列中读取一个单词,检查单词是否是合法单词,如果是合法的,则取符号栈的栈顶元素,和当前单词的标志号进行优先级比较,如果小于当前单词的优先级那么将当前单词压入符号栈,将其标志号压入状态栈;如果大于当前单词的优先级那么继续弹出状态栈的元素,和上一个符号栈弹出的元素进行比较,如果两优先级相等则继续弹,如果小于上一次弹出的元素的优先级,则弹的所有元素按先后弹的倒置顺序排列为一个句柄,查找产生式找到相应的产生式进行规约,把规约或的元素当多当前一的元素继续进行比较,直到词法分析输出结果全部遍历完。

在规约的过程中记下规约的次数,和每次规约的元素,以便语义分析和中间代码生成。

(3)语义分析

语义分析主要是将语义分析结果转化成三地址码表示的中间代码的过程。

在语法分析的过程中,在每次规约的过程中记录规约的类型和各个类型规约的次数。

即当规约的语句是布尔表达式时每规约一次都将规约的语句转化成三地址码的形式保存在字符串E中并记录E中规约产生式的次数在m1.quad中;如果规约的产生式是第一个赋值语句块中的赋值语句,则将规约的产生式以三地址形式保存在字符串B1中并记录B1中规约产生式的次数在m2.quad中;如果规约的产生式是第二个赋值语句块中的赋值语句,则将规约的产生式以三地址形式保存在字符串B2中并记录B2中规约产生式的次数在m3.quad中。

最后控制将B1、B2和E中的内容输入。

三.逻辑模型设计

LL

(1)文法及其属性文法

LL

(1)文法分析流程图:

•构造不带回溯的自上而下分析的文法条件

1.文法不含左递归,

2.对于文法中每一个非终结符A的各个产生式的候选首符集两两不相交。

即,若

A→1|2|…|n

则FIRST(i)∩FIRST(j)=(ij)

3.对文法中的每个非终结符A,若它存在某个候选首符集包含,则

FIRST(A)∩FOLLOW(A)=

如果一个文法G满足以上条件,则称该文法G为LL

(1)文法。

构造预测分析表的步骤:

①对每个产生式A→1|…|n执行②,③。

②对FIRST(A)中每个终结符a,把A→i加入到M[A,a],其中a∈FIRST(i)

③若ε∈FIRST(i),则对任何属于FOLLOW(A)的终结符b,将A→i加入M[A,b]。

④把所有无定义的M[A,a]标记为出错。

根据算符优先文法的定义和算符优先文法的要求设计文法如下:

G=(VN,VT,P,Z)VN={S,E,B,N},VT={if,then,else,>,a,b,x,=},

P由下列产生式组成:

S->ifEthenP1elseP2

E->id1Nid2

P->id1Nnum

N->>|=|<

在此文法中,a,b,x是指程序中的变量。

本次设计语法的相关属性文法可描述如下:

产生式

属性文法

S->ifEthenP1elseP2

E.true:

=newlabel;

E.false:

=newlabel;

P1.next:

=S.next;

P2.next:

=S.next;

S.code:

=E.code||gen(E.true,‘:

’)||P1.code||gen(‘goto’,S.next)||gen(E.false,‘:

’)||P2.code

E->id1Nid2

E.place:

=newtemp;

emit(‘if’,id1.place,relop.op,id2.place,‘goto’,nextstat+3);

emit(E.place,‘:

=’,‘0’);

emit(‘goto’,nextstat+2);

emit(E.place,‘:

=’,‘1’)

N-><

N.place:

=‘<’;

N->>

N.place:

=‘>’;

N->=

N.place:

=‘=’;

P->id1Nnum

p:

=lookup(id.name);

ifp!

=nilthen

emit(p’:

=’num.place);

elseerror;

在上面的属性文法中我们使用了这样的假定:

每当需要临时变量时,newtemp产生新的临时名字;lookup(id.name)用于根据名字的拼写检查符号表中是否存在该名字的条目。

如果有,返回该条目的指针,否则lookup返回nil,以表示没有找到;E的属性place用来存放E值的变量名在符号表的登录项或一整数码(若此变量是一个临时变量);函数newtemp用来产生一个新的临时变量的名字,把该名字也存入符号表,并返回该条目的地址。

过程emit将其参数写到输出文件上。

emit的参数构成一个三地址语句;变量nextstat给出在输出序列中下一个三地址语句的序号,emit在产生每个三地址语句后将nextstat加1。

我们给relop以属性op,用来确定该关系算符究竟代表哪个关系运算。

E.true,E.falsen和S.next都是三地址语句的标号,它们都是继承属性.。

E.true和E.false分别表示E为真和为假时控制流应该转向的标号,这两个属性由E的上下文决定;S.next表示执行完S后应该执行的第一个三地址语句的标号,它也是由S的上下文决定。

四.物理模型设计

(1)语法分析方法描述

开始时,将"#"和文法开始符号放入栈底。

总控程序在任何时候都是根据栈顶符号X和当前的输入符号进行工作的,它与文法无关

总控程序根据现行栈顶符号X和当前输入符号a,执行下列三种动作之一:

1.若X=a=‘#’,则宣布分析成功,停止分析。

2.若X=a‘#’,则把X从STACK栈顶逐出,让指针指向下一个输入符号。

3.若X是一个非终结符,则查看分析表M。

若M[X,a]中存放着关于X的一个产生式,把X逐出STACK栈顶,把产生式的右部符号串按反序一一推进STACK栈(若右部符号为,则意味不推什么东西进栈)。

在把产生式的右部符号推进栈的同时应做这个产生式相应的语义动作。

若M[X,a]中存放着“出错标志”,则调用出错诊察程序ERROR。

(2)语法分析表

计算每个非终结符的FirstVT集合和LastVT集合,结果为:

•First(S)={if}

•First(E)={id1}

•First(P)={id1}

•First(N)={>,=,<}

•FOLLOW(S)={#}

•FOLLOW(E)={then}

•FOLLOW(P)={else}

•FOLLOW(N)={num,id2}

由此可得出下面的LL

(1)分析表

if

then

else

Id1

Id2

num

>

=

<

#

S

S->ifEthenP1elseP2

E

E->id1Nid2

P

P->id1Nnum

N

N->>

N->=

N-><

五.实验结果分析:

要编译的文件:

 

词法分析:

输出的四元式:

六.心得体会:

经过二个星期的编译原理课程设计,在老师的指导下,顺利完成该课程设计。

通过该课程设计,收获颇多,对实验原理有更深的理解。

通过该课程设计,掌握了什么是编译程序,编译程序工作的基本过程及其各阶段的基本任务,熟悉了编译程序总流程框图,了解了编译程序的生成过程、构造工具及其相关的技术对课本上的知识有了更深的理解,课本上的知识师机械的,表面的。

通过把该算法的内容,算法的执行顺序在计算机上实现,把原来以为很深奥的书本知识变的更为简单,对实验原理有更深的理解。

  对该理论在实践中的应用有深刻的理解,通过把该算法的内容,算法的执行顺序在计算机上实现,知道和理解了该理论在计算机中是怎样执行的,对该理论在实践中的应用有深刻的理解。

  作系统的认识是模糊的,概念上的,现在通过自己动手做实验,从实践上认识了操作系统是如何处理命令的,如何协调计算机内部各个部件运行,对计算机编译原理的认识更加深刻。

课程设计中程序比较复杂,在调试时应该仔细,在程序调试时,注意指针,将不必要的命令去除。

 本次课程设计程序部分是用C语言编写的,《编译原理》,《C语言》两门门学科联系起来,把各个学科之间的知识融合起来,把课程的知识联系起来,对计算机整体的认识更加深刻。

使我加深了对《编译原理》,《C语言》两门课程的认识。

七.源代码

#include

#include

#include

#include

#include

enumkeyword{$right_paren,$left_paren,$mul,$div,$add,$sub,$fenhao,

$equal,$IF,$THEN,$ELSE,$greater,$less,$id,$num,$end};//关键字的枚举

typedefstructToken

{

keywordtype;

charch;

}Token;//定义的token结构

typedefenum{JUMP,JG,JL,equal,END,add,mul,sub,div}OpKind;//操作符定义为opkind

typedefstruct

{

intlabel;//标号

OpKindop;//操作符

charpar1,par2;//操作数

union

{

charresult;//结果

intaddress;//地址

};

}Quad;//四元式入口

#defineMAX_TOKEN256//Token表大小

#defineMAX_QUAD256//四元式数组大小

Tokentokentable[MAX_TOKEN];

Quadquad[MAX_QUAD];

inttoken_index;//token表索引

inttotal_len;//token表有效长度

intquad_len;//四元式表有效长度

intquad_index;//四元式索引

Tokencur;

Tokenqueue[10];

intlabel,k,one;//标记接口

charcurchar;//存储当前待比较字符

charcurtocmp;//存储当前栈顶字符

ifstreamins;

inttrueadd,falseadd,end;

inttable[5][8]={{1,0,0,0,0,1,0,0},

{0,1,1,0,0,0,1,1},

{1,0,0,0,0,1,0,0},

{0,1,1,1,1,0,1,1},

{1,0,0,0,0,1,0,0}};//存储预测分析表,1为有产生式,0为没有

inti,j;

intflag;

structLchar

{

charchar_ch;

structLchar*next;

}Lchar,*temp,*top,*base;

intright;//定义开关项

boolinitialize(charfilename[255]);//文件打开初始化

boolaccidence();//词法分析

voidprint();//输出单词表

voidbackpath(int,int);//回填出口

voidERROR();

voidsentence();//分析语句

voidboolean();//分析E->idid语句

boolnexttoken();//读下一单词

charnewchar();

voidpush();//进队列

chardosome(void);//算法函数

voidpushs(charpchar);//入栈函数

voidpop(void);//出栈函数

voiddoforpush(intt);//根据数组下标计算的值产生式入栈

voidchangchartoint();//根据curchar,curtocmp转为数字以判断是否有产生式

voidsemantic();//语法语义分析

charLL1();//LL

(1)文法分析

voidprintQuad();//输出四元式

voidERROR(charstr[20]);

voidAD_ADDRESS(intnlabel,OpKindnop,charnpar1,charnpar2,intnaddress);

voidAD_RESULT(intnlabel,OpKindnop,charnpar1,charnpar2,charnresult);

 

voidmain()

{

cout<<"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"<

<<"@基于LL

(1)法的条件语句语法语义分析程序@"<

<<"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"<

cout<<"输入您要编译编译文件的文件名(文件名.txt):

";

charfname[100];

cin>>fname;

if(!

initialize(fname))//初始化文件

return;

if(!

accidence())//词法分析

return;

charch;

while

(1)

{

if(ins.eof())//ifstreamins;文件输入串,若文件已完。

则break

break;

ins>>ch;//继续读入文件内容

}

cout<

";

print();//打印词法分析的结果

cout<

cout<<"词法分析结束。

"<

semantic();//语法语义分析

cout<

"<

printQuad();//输出四元式

if(right==1)

cout<<"分析成功"<

else

cout<<"分析失败"<

cout<<"语法语义分析结束"<

}

charnewchar()

{charp;

p=char(k);//intlabel,k,one;//标记接口

k++;

returnp;

}

//文件打开初始化

boolinitialize(charfilename[100])

{

one=0;

token_index=0;//token表索引

total_len=0;//token表有效长度

quad_len=0;//四元表有效长度

quad_index=0;//四元表索引

label=0;//intlabel,k,one;//标记接口

end=0;//前面定义的全局变量inttrueadd,falseadd,end;

k=48;

ins.open(filename,ios:

:

nocreate|ios:

:

in);

if(ins.fail())

{

cout<<"文件打开出错!

"<

returnfalse;

}

returntrue;

}

//词法分析

boolaccidence()

{

intk=0;

charbuf[16];//暂存数组单元

charch;

while

(1)

{

ins>>ch;

if(ins.fail())

break;

while(ch=='')

{ins>>ch;}

if(ch=='I')

{

ins>>buf;

//对关键字分析

if(strcmp(buf,"F")==0)

tokentable[total_len++].type=$IF;

}

elseif(ch=='T')

{

ins>>buf;

if(strcmp(buf,"HEN")==0)

tokentable[total_len++].type=$THEN;

}

elseif(ch=='E')

{

ins>>buf;

if(strcmp(buf,"LSE")==0)

tokentable[total_len++].type=$ELSE;

}

//对关系运算符分析

elseif(ch=='>')

{

tokentable[total_len++].type=$greater;

}

elseif(ch=='<')

{

tokentable[total_len++].type=$

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 解决方案 > 学习计划

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1