语法制导的三地址代码生成器Word文档下载推荐.docx

上传人:b****3 文档编号:18440157 上传时间:2022-12-16 格式:DOCX 页数:17 大小:46.03KB
下载 相关 举报
语法制导的三地址代码生成器Word文档下载推荐.docx_第1页
第1页 / 共17页
语法制导的三地址代码生成器Word文档下载推荐.docx_第2页
第2页 / 共17页
语法制导的三地址代码生成器Word文档下载推荐.docx_第3页
第3页 / 共17页
语法制导的三地址代码生成器Word文档下载推荐.docx_第4页
第4页 / 共17页
语法制导的三地址代码生成器Word文档下载推荐.docx_第5页
第5页 / 共17页
点击查看更多>>
下载资源
资源描述

语法制导的三地址代码生成器Word文档下载推荐.docx

《语法制导的三地址代码生成器Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《语法制导的三地址代码生成器Word文档下载推荐.docx(17页珍藏版)》请在冰豆网上搜索。

语法制导的三地址代码生成器Word文档下载推荐.docx

F→(E)|idT'

→*FT'

|ε

间接左递归的消除F→(E)|idS→Ac|cA→Bb|bB→Sa|a

将B的定义代入A产生式得:

A→Sab|ab|b

将A的定义代入S产生式得:

S→Sabc|abc|bc|c

消除直接左递归:

S→abcS'

|bcS'

|cS'

S'

→abcS'

删除“多余的”产生式:

A→Sab|ab|b和B→Sa|a

结果:

εabcS'

|→S'

消除左递归的一般方法:

用产生式组

A?

βB|βB|…|βBn21B?

αB|αB|…|αB|εn12替换产生式组

|…|Aα|…|ββ|β|→AAα|Aαm121n2其中:

B为新变量,相当于A'

消除左递归的算法:

Ⅰ、把文法G的所有非终结符按任一种顺序排列成A,A,……,A;

按此顺序执行;

n12Ⅱ、FORi:

=1tonDO

Begin

FORj:

=1toi-1DO

把形如A?

Aγ的规则改写成jiA?

δγ│δγ│……│δγ。

其中A?

δ│δ│……│δ是关于P的jijk121k2所有规则;

消除关于Pi规则的直接左递归性

END

Ⅲ、化简由(Ⅱ)所得的文法。

即去除那些从开始符号出发永远无法到达的非终结符的产生规则,为非终结符编号,再采用代入法将间接左递归变为直接左递归,消除直接左递归。

1.2.2消除回溯、提左因子

欲构造行之有效的自顶向下的分析器,必须消除回溯。

为了消除回溯就必须保证:

对文法的任何非终结符,当要用它去匹配输入串时,能够根据它所面临的输入符号准确地指派它的一个侯选去执行任务,并且此侯选的工作结果应是确信无疑的。

也就是说,若此侯选获得成功匹配,那么,这种匹配决不会是虚假的;

若此侯选无法完成匹配任务,则任何其它侯选也肯定无法完成。

但是,如何把一个文法改造成任何非终结符的所有侯选首符集两两不相交呢?

其办法是,提取公共左因子。

if语句的原始文法

S→ifEthenS

|ifEthenSelseS

|other

遇到if时难以判断用哪一个产生式进行匹配(推导)

存在左因子ifEthenS

提取作因子:

S→ifEthenSS'

|other

S'

→ε|elseS

左因子提取方法:

|…|αβ|…|γγ|→Aαβ|αβγ|将形如mn2112|…|γ|…|ββ|β和A'

→|的规则改写为A→αA'

|γγn1m2121.2.3候选式的确定与回溯(Backtracking)

当要进行某个语法变量的推导时,希望能够根据当前符号确定候选式。

如果有几个候选式(右部)左端第一个符号相同,则分析器无法根据当前输入符号选择产生式,只能试探。

因此,希望寻找一类文法,我们可以方便地根据当前输入符合确定正确的候选式。

为了描述方便,我们定义文法符号的FIRST(首符号集)和非终结符的FOLLOW(后续符号集):

FIRST集:

对于?

α∈(VT∪VN)*定义:

α的首符号集

FIRST(α)={a|α?

*a…,a∈VT*}

FOLLOW集:

A∈VN定义A的后续符号集:

FOLLOW(A)={a|S?

*…Aa…,a∈VT}

求FIRST(X)的算法:

FIRST(x)={x},VT∈x?

对1)

欢迎下载学习好资料

VN,取FIRST(X)∈的初值:

2)对?

X{a|X→a…∈P};

X→ε?

P

FIRST(X)=

{a|X→a…∈P}∪{ε};

X→ε∈P

3)对?

X∈VN,重复如下过程,直到所有FIRST集不变

若X→Y…∈P,且Y∈VN,

则FIRST(X)=FIRST(X)∪(FIRST(Y)-{ε});

…Y∈P,且Y...Y?

*ε,若X→Yi-1n11则对k=1到i-1:

FIRST(X)=FIRST(X)∪(FIRST(Y)-{ε});

k若Y...Y?

*ε,n1则FIRST(X)=FIRST(X)∪{ε}

求FOLLOW(A)的算法:

对于所有非终结符,重复进行以下计算

1)将#加入到FOLLOW(S)

#为句子的结束符

2)若A→αBβ,

则FOLLOW(B)=FOLLOW(B)∪FIRST(β)–{ε}

3)如果A→αB或A→αBβ,且β?

*ε,A≠B,

则FOLLOW(B)=FOLLOW(B)∪FOLLOW(A)

1.2.4LL

(1)分析条件

|…|α是所有A产生式,它们满足下列条件,则称G是A→α|α的任意变量对GA,n12LL

(1)文法:

Ⅰ、FIRST(α)∩FIRST(α)=Φi≠jjiⅡ、且当ε∈FIRST(α)时,FOLLOW(A)∩FIRST(α)=ΦijLL

(1)文法是自顶向下方法能够处理的一类文法:

第一个L表示从左向右扫描输入符号串;

第二个L表示生成最左推导;

1表示读入一个符号可确定下一步推导。

表达式文法是LL

(1)文法

E→TE'

E'

T→FT'

T'

→*FT'

F→(E)|id

考察

:

+不在FOLLOW(E'

)={),#}

*不在FOLLOW(T'

)={+,),#}

F:

(和id不同

非LL

(1)文法的不确定性

对文法

S→cAdA→ab|a

输入cad的分析

不确定性的解决方法:

1)采用回溯算法

2)将非LL

(1)文法改写为等价的LL

(1)文法

3)无法改写时,增加其它的判别因素

1.3递归子程序法

当一个文法满足LL

(1)条件时,我们就可以为它构造一个不带回溯的自顶向下分析器(又称递归下降分析器),这个分析器是由一组递归过程组成的,每个过程对应文法的一个非终结符。

这种分析方法称为递归子程序法。

具体做法为:

对应每个语法变量设置一个处理子程序:

即对于每条产生式规则:

A→XX…X…Xnk21.

当遇到Xk是终极符号时直接进行匹配

当遇到Xk是语法变量时就调用Xk对应的处理子程序

要求处理子程序是可以递归调用的

例如:

简单算术表达式的分析器

E的子程序(E→T(+T)*)

procedureE;

begin

T;

T的过程调用

whilelookhead='

+'

do

begin当前符号等于+时

match(‘+'

);

处理终结符+

TT的过程调用

end

end;

lookhead:

当前符号

实现递归子程序的一个有效工具是状态转换图。

语法分析器和词法分析器的状态转换图不同,每个非终结符对应一个状态转换图,边上的标记是记号和非终结符。

记号上的转换意味着如果该记号是下一个输入符号,就应进行转换。

非终结符A上的转换是对与A对应的过程的调用,从文法构造语法图,对每个非终结符A执行如下操作:

创建一个开始状态和一个终止状态(返回状态)。

对每个产生式A→XX…X,创建一条从开始状态到终止状态的路径,边上的标记分别n21为X,X,…,X。

n12开始,分析器进入状态图的开始状态,输入指针指向输入符号串的第一个符号。

如果经过一些动作后,它进入状态s,且从状态s到状态t的边上标记了终结符a,此时下一个输入符又正好是a,则分析器将输入指针向右移动一位,并进入状态t。

另一方面,如果边上标记的是非终结符A,则分析器进入A的初始状态,但不移动输入指针。

一旦到达A的终态,则立刻进入状态t,事实上,分析器从状态s转移到状态t时,它已经从输入符号串“读”了A(调用A对应的过程)。

最后,如果从s到t有一条标记为ε的边,那么分析器从状态s直接进入状态t而不移动输入指针。

递归子程序法小结:

1)构造文法

2)改造文法:

消除二义性和左递归、提取左因子

3)求每个候选式的FIRST集和每个变量的FOLLOW集

4)检查是不是LL

(1)文法,不是LL

(1),说明文法的复杂性超过自顶向下方法的分析能力,需要附加新的“信息”

5)按照LL

(1)文法画语法图

6)化简语法图

7)按照简化后的语法图,为每个非终结符设置一个分析子程序。

事实上,如果有一个恰当的文法,可以直接根据每个语法变量的产生式设计相应的程序。

递归子程序法优点:

1)直观、简单、可读性好

2)便于扩充

递归子程序法缺点:

1)递归算法的实现效率低

2)处理能力相对有限

3)通用性差,难以自动生成

实验二的语法分析部分建议学生采用递归子程序法实现。

当第二个实验被分解为两个实验时,则先采用递归子程序法实现一个自顶向下的语法分析器。

1.4预测分析法

实现LL

(1)分析的另一种有效方法是预测分析法。

一个预测分析器的组成为:

一个通用的控制算法;

一个分析栈,#为栈底符号;

一个输入缓冲区,#为输入串结束符;

一个统一形式的分析表M;

(不同语言使用内容不同的分析表)。

主要通过一张分析表和一个分析栈进行联合控制。

其模型如下:

…………#输入缓冲n

输出的产生

控制程S序

#

预测分析M

分析方式:

根据栈和文法的开始符号S输入指针指向输入串的第一个字符,分析栈中存放栈底符号#M,以决定相应的动作,其关键是分析表的构造。

和读入的符号a,查看分析表顶符号A预测分析表的构造算法:

2)和3)对于每一产生式A→α,执行1)

填入M[A,a]A→α2)对于FIRST(α)中的每一终结符a,将若M[A,b];

A→α填入,FIRST(α),则对FOLLOW(A)中的每个符号b将3)如果ε属于M[A,#];

A→α填入,且FIRST(α)#在FOLLOW(A),则将ε属于M[A,b]标上错误标志4)将所有无定义的

预测分析法的步骤:

1)构造文法。

2)改造文法:

消除二义性、消除左递归、提取左因子。

FOLLOW集。

)求每个候选式的FIRST集和变量的3说明文法的复杂性超过自顶向下方法的分析能LL

(1),LL

(1)文法,若不是4)检查是不是

“信息”力,需要附加新的构造预测分析表。

5)

实现预测分析器。

)6出错处理问题:

同步为“属于FOLLOW(A),则增加M[A,a]a对语法变量A,如果M[A,a]无定义,并且”(synch)。

点预测分析法的优点:

1)效率高)便于维护、自动生成2由于我们建议学生采用递归子程序法自己手工地实现一个自顶向下的语法分析器,关于预测分析器的设计实现细节就不在这里赘述。

属性文法和语法制导翻译1.5目前实际应用中比较流行的语义描述和语义处理的方法主要还是属性文法和语法制导翻译方法。

属性文法是在上下文无关文法的基础上,为每个文法符号(终结符或非终结符)配备若干年提出的。

这些属性代表与文法符号相关信息,例在1968(称为属性)相关的“值”,是Knuth如它的类型、值、代码序列、符号表内容等等。

属性与变量一样,可以进行计算和传递。

属性文法的特点:

)是一种接近形式化的语义描述方法

(1)长于描述静态语义、短于描述动态语义(23)每个语法符号有相应的属性符号()每个产生式有相应的计算属性的规则(4属性表达式:

=)属性变量5(.

举例:

产生式属性(计算)规则/语义规则

E→E1+E2E.val:

=E1.val+E2.val

E→E1*E2E.val:

=E1.val*E2.val

E→(E1)E.val:

=E1.val

E→idE.val:

=id.val

属性文法的定义:

三元组:

A=(G,V,F)

G是上下文无关文法

V属性的有穷集

F关于属性的计算规则

属性及其计算规则:

语义信息作为终结符和非终结符的属性。

语义分析为产生式相关的属性计算:

每个产生式设置语义规则,描述各属性的关系——计算规则。

属性的设定:

根据文法符号的语义,为文法符号设置属性,用来表示文法符号的语义。

终结符使用单词的属性(id.val)

保留字:

if,begin,function,……

常数:

40.12,232,80,“TCP/IP”

标识符:

sum,tcc,id

语法变量根据实际需要设定属性

表达式E:

E.type,E.val

计算器的属性文法要完成一个输入表达式值的计算和显示——翻译

用文法描述要完成的动作:

L→E

E→E1+T|T

T→T1*F|F

F→(E)|digit

如何描述翻译过程?

请看如下属性文法:

L→Eprint(E.val)(L的虚属性)

E→E1+TE.val:

=E1.val+T.val

E→TE.val:

=T.val

T→T1*FT.val:

=T1.val*F.val

T→FT.val:

=F.val

F→(E)F.val:

=E.val

F→digitF.val:

=digit.lexval

其中,lexval是单词digit的属性

下面简述一下属性的分类

继承属性

…X为一个产生式,Xi的属性设A→XXn12,…,c)

Xi.in=f(c,c,ci-112,…,c是A,X,X,…,X,cc,c属性(Inherited)的属性叫做继承i-121i-121.

A

c

n

k<

ixk.in

ci2

推导分析较自然综合属性为一个产生式A→X1X2…Xn设A.s=f(c1,c2,…,ck)的属性和XnA的继承属性X1,X2,…,是c1,c2,…,ck是从其子结点的属性值计算出来的这种属性叫做综合(Synthesized)属性。

A.sA

A.s

A.in

xx21ccxn21cn适应:

归约分析

固有属性、常量,它们的属性是用户给定的、不变的。

语言中的标识符、常数(数值的、符号的)T.type:

=integerintT→

属性(单词属性),归类于综合属性。

固有(Inherent)属性的计算:

——在归约时进行计算综合属性是自底向上按照语义规则来计算各结点的综合属性值TopologicalSort)。

继承属性是根据依赖关系决定计算顺序的任意一个拓扑排序(固有属性在词法分析时计算。

的分析树与属性计算:

3*5+4

LPrint(19)

E.val=19

+T.val=4E.val=15

T.val=15F.val=4*digit.lexval=4F.val=5T.val=3.

语法制导翻译

属性加工的过程即是语义处理的过程。

对于文法的每个产生式都配备了一组属性的计算规则,称为语义规则。

语法制导翻译是在进行语法分析的同时,完成相应的语义处理。

E→E1+E2E.val:

=E1.val+E2.val

如何根据被识别出的语法成分进行语义处理?

语义——可以看成是相应文法符号的属性。

(1)对应每一个产生式编制一个语义子程序,当一个产生式获得匹配时,调用相应的语义子程序实现语义检查与翻译。

E→E1+TE.val:

=E1.val+T.val

T→T1*FT.val:

=T1.val*F.val

F→idF.val:

=id.val

以上翻译模式适应在完成归约的时候进行。

(2)在产生式的右部的适当位置,插入相应的语义动作,按照分析的进程,执行遇到的语义动作

D→T{L.in:

=T.type}L

T→int{T.type:

=integer}

T→real{T.type:

=real}

L→{L1.in:

=L.in}L1,id{…}

以上翻译模式适应在进行推导时完成对应语法基本分析方法(Top-down、Bottom-up)

1.6实现的关键技术提示

对于“语法制导的三地址代码生成器的编制”实验而言,除了能正确地画出语法图并化简,求出FIRST,FOLLW集外,在实现过程中还要想方设法保证输出的产生式规则(三地址代码)严格按照自顶向下、从左至右的顺序进行,为了达到这一要求,需要在每次调用与某个语法变量相应的处理程序时,一进入过程就输出该规则(生成相应的三地址代码),而在有些情况下,为了正确地选择匹配的规则(生成相应的三地址代码)必须连续向前看若干的符号(token),这时应想到如何把分析过的符号暂时保存起来(事实上栈是解决这类问题的良好选择)。

这些难点的最终解决,正体现了计算机学科的魅力所在,它要求每个从事这项工作的人“既要想得对,也要做得到”。

二具体实验要求

2.1实验目的

掌握计算机语言的语法分析器设计与属性文法应用的实现方法。

2.3实验内容

编制一个能够进行语法分析并生成三地址代码的微型编译程序。

2.4实验要求

1考虑下述语法制导定义中文法,采用递归子程序法,改写文法,构造语法分析器;

2考虑下述语法制导定义中语义规则,改写语法分析器,构造三地址代码生成器。

产生式

语义规则

→Sid=E

S.code=E.code||gen(id.place'

:

='

E.place)

then

CS→ifS1

C.true=newlabel;

C.false=S.next;

S.next=S.next;

1S.code=C.code||gen(E.true'

'

)||S1.code

ifS

→thenCS1.

C.false=newlabel;

C.true=newlabel;

elseS2

S.next=S.next=S.next;

21S.code=C.code||gen(E.true'

)||S.code

1||gen(‘goto'

S.next)||gen(E.false'

)||

S.code

2

SwhileCdo

→S1

S.begin=newlabel;

.next=S.begin;

SC.false=S.next;

1S.code=gen(S.begin'

)||C.code||

.code||gen(‘goto'

S.begin);

gen(E.true'

)||S1

C→E>

E21

.code||

.code||EC.code=E21.place'

>

E.place'

goto'

C.true)||gen(‘if'

E21e)

gen(‘goto'

C.fals

C→E<

C.code=E.code||E.code||21.place'

<

E21gen(‘goto'

C.false)

C→E=E21

.code||E.code||C.code=E21.place'

E→E+T1

E.place=newtemp;

.code||T.code||

E.code=E1gen(E.place'

T.place)1

E→E-T1

.code||T.code||E.code=EE.place=newtemp;

1gen(E.place'

E-'

T.place).place'

1

→ET

E.code=T.codeE.place=T.place;

→TF

T.code=F.codeT.place=F.place;

→T

T*F1

T.place=newtemp;

.code||F.code||

T.code=T1.place'

*'

F.place)gen(T.place'

T1

T→T/F1

.code||F.codeT.code=TT.place=newtemp;

1||

gen(T.place'

T.place'

/'

F.place)1

F→(E)

F.place=E.pla

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

当前位置:首页 > 初中教育 > 科学

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

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