编译原理 第5章课件.docx

上传人:b****5 文档编号:5627404 上传时间:2022-12-29 格式:DOCX 页数:30 大小:163.91KB
下载 相关 举报
编译原理 第5章课件.docx_第1页
第1页 / 共30页
编译原理 第5章课件.docx_第2页
第2页 / 共30页
编译原理 第5章课件.docx_第3页
第3页 / 共30页
编译原理 第5章课件.docx_第4页
第4页 / 共30页
编译原理 第5章课件.docx_第5页
第5页 / 共30页
点击查看更多>>
下载资源
资源描述

编译原理 第5章课件.docx

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

编译原理 第5章课件.docx

编译原理第5章课件

第五章自底向上优先分析方法

教学要求:

1.掌握算符优先关系表的构造,算符优先分析算法;

2.理解自底向上分析思想,简单优先文法及简单优先分析法,算符优先文法的定义;

目录:

5.1自底向上优先分析法概述

5.2简单优先分析法

5.3算符优先分析算法

自下而上语法分析的基本思想:

从输入串开始,朝着文法的开始符号进行最左归约,直到到达文法的开始符号为止。

主要是进行移进或归约操作,采用最左归约。

也称移进-归约分析法。

工作方式:

“移进-归约”方式

即:

自左至右把输入串的符号一个一个移进栈,在移进过程中不断查看栈顶符号串,一旦形成某个句型的句柄时,就将此句柄用相应的产生式左部替换(归约),称为一步归约.重复上面的过程直到栈顶只剩下文法的开始符号,输入串读完为止,这样就认为识别了一个句子。

自左至右的移进-归约过程是自顶向下最右推导的逆过程,所以也称规范归约。

分析程序模型

 

1)初态时栈内仅有栈底符“#”,读头指针在最左单词符号上。

2)语法分析程序执行的动作:

a)移进读入一个单词并压入栈内,读头后移;

b)归约检查栈顶若干个符号能否进行归约,若能,就以产生式左部替代该符号串,同时输出产生式编号;

c)识别成功移进-归约的结局是栈内只剩下栈底符号和文法开始符号,读头也指向语句的结束符;

d)识别失败

注意:

 

例如:

有文法如下

(1)SaAcBe

(2)Ab

(3)AAb

(4)Bd

问:

语句abbcde是不是该文法的

合法语句?

 

 

 

5.1自底向上优先分析法概述

5.1自底向上优先分析法概述

分类:

1、简单优先分析:

对一个文法按一定原则求出所有符号即终结符号和非终结符号之间的优先关系,按照这种关系确定归约过程中的句柄.

特点:

准确、规范,但分析效率底,使用价值不大.

2、算符优先分析:

只规定算符(终结符号)之间的优先关系,不考虑非终结符号之间的优先关系,只要找到句柄就归约,不考虑归约到那个非终结符号。

特点:

不是规范归约,分析速度快,特别适合于表达式的分析.

5.2简单优先分析法

基本思想:

1、对句型中相邻的文法符号规定优先关系,以寻找句型中的句柄。

2、规定句柄内各相邻符号之间具有相同的优先级。

3、规定句柄两端符号优先级要比位于句柄之外而又和句柄相邻的符号的优先级高,以先归约句柄。

4、对于文法中所有符号,只要它们可能在某个句型中相邻,就要为它们规定相应的优先关系,若某两个符号永远不可能相邻,则它们之间就无关系。

与数学中的=,<,>不同!

一、优先关系:

相等、小和大

A)X

Y:

当且仅当G中含有形如P…XY…的产生式,

B)X

Y:

当且仅当G中含有形如P…XQ…的产生式,其中Q为非终结符,且QY...

C)X

Y:

当且G中含有形如P…QR…的产生式,其中Q为非终结符,且Q=>…X,R=>Y…

D)对任何X,若文法开始符号S=>X…,则#X,若S=>…X,则X#,#=#。

关系有:

b=A,A=b,

(=B,A=a,a=)

关系有:

b<(,b

(<(,(

关系有:

)>b,a>b,B>b

)>a,a>a,B>a

例如:

G[S]:

S’->#S#

S->bAb

对于#有:

#=###,b>#

A->(B|a

B->Aa)

简单优先矩阵:

用于表示文法符号之间的简单优先关系的矩阵

S

b

A

B

a

#

S

·>

b

·>

A

B

·>

·>

a

·>

·>

·>

·>

#

二、简单优先文法的定义

一个文法G,若它不含产生式,也不含任何右部相同的不同产生式,并且它的任何符号对(X,Y),或者没有关系,或者存在下述三种关系:

·>、<·、=·之一,则称该文法是一个简单优先文法。

三、简单优先分析法

数据结构:

构造文法的优先关系矩阵

保存文法的产生式

设置栈S。

算法步骤:

将输入符号串a1a2…an#依次逐个存入符号栈S中,直到遇到栈顶符号ai的优先性下一个待输入符号aj为止。

栈顶当前符号ai为句柄尾,由此向左在栈中找句柄的头ak,即找到ak-1ak为止。

由句柄ak….ai在文法的产生式中查找右部为ak….ai的产生式,若找到,则用相应的左部替换句柄,若找不到则为出错,这时输入串不是该文法的句子。

重复以上三步,直到归约完输入符号串,栈中只剩下文法的开始符号为止。

5.3算符优先分析方法

一、基本思想

1、自下而上归约

2、规定算符(更一般地说,指终结符)的优先级及结合规则,以使得分析过程唯一

3、比较相邻两个算符而决定动作

§注:

1)这里的关键是对所有算符定义某种优先关系

2)算符优先分析法是仿效四则运算的计算过程而构造的一种语法分析方法

4、实例

表达式文法:

EE+E|E-E|E*E|E/E|(E)|i

对这个二义文法可能会有好几个规范推导和归约,真正运算时也有几种不同结果,但若按算符优先顺序和结合规则的规定进行归约,句子的归约过程就是唯一的,运算结果也唯一。

※例如:

i+i-i*(i+i)归约过程如下:

i+i-i*(i+i)设算量级别最高,最先归约;

E+i-i*(i+i)

E+E-i*(i+i)+,-同级,先归约左边“+”

E-i*(i+i)

E-E*(i+i)-,*不同级,先归约右边“*”

E-E*(E+i)先括号内,后括号外

E-E*(E+E)归约括号内

E-E*(E)归约括号对

E-E*E先归约“*”

E-E后归约“-”

E结束(接受)

二、直观算符优先分析法

1、确定运算符的优先级·

关键是对一个给定文法G,人为地规定其运算符的优先顺序,优先关系的表示与简单优先文法类似:

对于任何两个可能相继出现的终结符a,b,则a、b之间的关系为:

1)a<·ba的优先级低于b

2)a=·ba的优先级等于b

3)a·>ba的优先级高于b

4)若ab在任何情况下都不可能相继出现,则a,b无关系。

注:

1)算符优先分析法的关键是比较两个相继出现的终结符的优先级而决定应采取的动作。

2)要完成运算符间优先级的比较,可以先定义各种可能相继出现的运算符的优先级,并表示为矩阵的形式,使得能够在分析中通过查询矩阵元素而得到算符之间的优先关系。

左右

+

*

I

#

+

·>

·>

·>

*

·>

·>

·>

·>

·>

·>

·>

·>

I

·>

·>

·>

·>

#

§注:

1)在此表中,+包括-,*包括/,“#”是一个特殊符号,用于语句的开

始符号和结束符号。

2)这张表满足通常数学上的习惯约定:

a、运算量i的优先级高于算符;

b、语句开始和结束符号“#”与终结符a相继出现时,应该有#<·a和a·>#,以此来保证语句内先归约。

3)(=·)表示括号是成对归约的。

4)优先关系和代数中的大于小于关系不同,a<·b并不意味着b·>a,终

结符所处的左右位置很重要。

三、算符文法的定义

1、定义及性质

给定上下文无关文法G,若G中所有产生式右部都不包含两个相继的非终结符,则G为算符文法OperaterGrammar(OG)。

§注:

算符文法保证了两个运算符之间只有一个操作数。

算符文法性质

★性质1在算符文法中任何句型都不包含两个相邻的非终结符。

  

证明:

用归纳法。

  设γ是句型,即Sγ

  S=ω0ω1...ωn-1ωn=γ

  推导长度为n,归纳起点n=1时,

  S=ω0ω1=γ,即Sγ,必存在产生式S→γ,而由算符文

法的定义,文法的产生式中无相邻的非终结符,显然满足性质1。

  假设n>1,ωn-1满足性质1。

  若ωn-1=αAδ,A为非终结符。

  由假设α的尾符号和δ的首符号都不可能是非终结符,否则与假设矛盾。

  又若A→β是文法的产生式,则有ωn-1ωn=αβδ=γ

  而A→β是文法的原产生式,不含两个相邻的非终结符,所以αβγ也

不含两个相邻的非终结符。

满足性质1。

证毕。

★性质2如果Ab或(bA)出现在算符文法的句型γ中,其中A∈VN,b∈VT,则γ中任何含b的短语必含有A。

证明:

用反证法。

  因为由算符文法的性质1知可有:

  S*γ=αbAβ

  若存在B→αb,这时b和A不同时归约,则必有SBAβ,这样在

句型BAβ中存在相邻的非终结符B和A,所以与性质1矛盾,证毕。

注意:

含b的短语必含A,含A的短语不一定含b。

2、算符优先文法定义

设G是一个不包含空串产生式的算符文法,并设a,bVT;P,Q,RVN,定义关系:

1)a=·b当且仅当G中含有形如P…ab…产生式,或者P…aQb…产生式;

2)a<·b当且仅当G中含有形如P…aR…的产生式,其中Rb…,或RQb…;

3)a·>b当且仅当G中有形如P…Rb…产生式,其中R…a,或R…aQ.

若G中任何终结符序偶(a,b)至多满足上述关系之一,则称G为算符优先文法OperaterPrecedenceGrammar(OPG)。

A

用语法树来理解更直观A

A

…aB…

……Bb……..

…ab…

a=·b

P

a<·b

…a

b…

a·>b

表达式文法:

EE+E|E*E|(E)|I是算符文法和算符优先文法吗?

 

注意

是算符文法,但不是算符优先文法。

两个算符之间的优先关系是有序的,允许有a·>b,

b·>a同时存在,而不允许有a<·b,a·>b,a=·b三种情况之两种同时存在。

3、算符文法和算符优先文法定义的意义

这两个定义相当于对文法的句型和可归约的短语做了如下规定:

设A1A2…Ai-1AiAi+1…An是文法G的一个句型,

1)、若AiVN,则Ai-1、Ai+1VT,即不许出现相继两个非终结符;

+*

矛盾

2)、若B1B2…Bm是当前可归约短语,并可归约为Ai,则:

a)B1B2…Bm中不能有相继两个非终结符且相邻的终结符优先级全相等;

b)对于B1B2…Bm中首终结符b有Ai-1<·b

c)对于B1B2…Bm中尾终结符c有c·>Ai+1.

§注:

实际上,可归约短语是某产生式右部符号串,所以通过检查G的每个产生式的每个候选式,可以查找出任意优先级相同的终结符序偶。

要找出所有满足关系<·和·>的终结符序偶,就要找出各非终结符P的首终结符集和尾终结符集。

三、算符优先文法及优先表的构造

1、各非终结符P的首终结符集和尾终结符集

a)定义

首终结符集FIRSTVT(P)={a|P=>a…或P=>Qa…,aVT;P,QVN}

尾终结符集LASTVT(P)={a|P=>…a或P=>…aQ,aVT;P,QVN}

§注:

1)有了这两个集合,就可通过检查每个产生式的每个候选式,确定满足关系·>和<·的所有终结符序偶。

2)确定优先关系方法如下:

若产生式右部有形如:

…aP…的串,则对于任何bFIRSTVT(P),有a<·b;

若产生式右部有形如:

…Pb…的串,则对于任何aLASTVT(P),有a·>b;

若有产生式A->…ab…A->…aBb…则有a=·b

※例如:

设文法G的产生式为:

SaAcBeAAb|bBd

计算每个非终结符的FIRSTVT与LASTVT及所有终结符之间的关系。

解:

FIRSTVT(S)={a}LASTVT(S)={e}

FIRSTVT(A)={b}LASTVT(A)={b}

FIRSTVT(B)={d}LASTVT(B)={d}优先关系表:

右左

a

b

c

d

e

a

b

·>

·>

c

d

·>

e

※[例]考虑下面文法:

0.E’->#E#1.EE+T|T2.TT*F|F3.FPF|P4.P(E)|i构造优先关系表

解:

1)=·关系:

#=·#,(=·)

2)计算每个非终结符的FIRSTVT和LASTVT集合

FIRSTVT(E’)={#}LASTVT(E’)={#}

FIRSTVT(E)={+,*,,(,i}LASTVT(E)={+,*,,),i}

FIRSTVT(T)={*,,(,i}LASTVT(T)={*,,),i}

FIRSTVT(F)={,(,i}LASTVT(F)={,),i}

FIRSTVT(P)={(,i}LASTVT(P)={),i}

3)<·关系:

对表达式文法中终结符在前,非终结符在后的相邻符号对有:

#E,+T,*F,F,(E终结符<·FIRSTVT(非终结符)

4)·>关系:

对表达式文法中终结符在后,非终结符在前的相邻符号对有:

E#,E+,T*,P,E)LASTVT(非终结符)·>终结符

+

*

i

#

+

·>

·>

·>

*

·>

·>

·>

·>

·>

·>

·>

·>

I

·>

·>

·>

·>

·>

·>

·>

·>

·>

·>

·>

#

5)优先关系表

 

2、构造首终结符集和尾终结符集算法

★1)构造集合FIRSTVT(P)的算法

a)规则——根据FIRSTVT(P)的定义,按下面的规则来构造:

①若有产生式Pa…或PQa…,则aFIRSTVT(P)

②若aFIRSTVT(Q),且有产生式PQ…,则aFIRSTVT(P)

b)方法——基本思想:

使用两个特殊的数据结构,一个是二维布尔矩阵F,行标为非终结符P,列标为终结符a;F[P,a]=true,当且仅当aFIRSTVT(P);另一个是堆栈STACK,栈中动态存放曾在F[P,a]中为真的序偶(P,a)。

基本算法:

(1)初始化:

将布尔矩阵F中各元素置为假;栈清空;

(2)按规则1,查看产生式,对于形如Pa…或PQa的产生式,置相应的F[P,a]为真,并将序偶(P,a)入栈;

(3)按规则2,对栈施加如下操作:

弹出栈顶序偶并记为(Q,a),查看所有产生式,看有无形如PQ…的产生式,若有,且aFIRSTVT(P)(即F[P,a]为假),则将F[P,a]为置为真,并把(P,a)入栈;

(4)重复步骤3,直到栈空为止。

那么,在F[P,a]中,凡是“真”的元素即属于P的首终结符集。

程序描述

MAIN()

{FOR每个非终结符A和终结符aDO

F[A,a]=FALSE;

FOR每个形如A->a…或A->Ba…的产生式

DOINSERT(A,a);

WHILESTACK非空DO

{把STACK的栈顶弹出记为(B,a);

FOR每个形如A->B…的产生式DO

INSERT(A,a);

}

}

INSERT(A,a);

{

IFNOTF[A,a]THEN

{F[A,a]=TRUE;

PUSH(A,a)ONTOSTACK

}

}

1、

例如:

表达式文法

0.E’->#E#

1.EE+T|T

2.TT*F|F

3.FPF|P

4.P(E)|i

求FIRSTVT(B),

第一次扫描后

STACK的初始值为:

 

2、(P,i)为栈顶时,由产生式F->P,T->F,E->T,栈顶内容逐次变为:

(F,i),(T,i),(E,i)

3、(P,()为栈顶时,由产生式F->P,T->F,E->T,栈顶内容逐次变为:

(F,(),(T,(),(E,()

4、(F,)为栈顶时,由产生式T->F,E->T,栈顶内容逐次变为:

(T,),(E,)

5、(T,*)为栈顶时,由产生式E->T,栈顶内容逐次变为:

(E,*)

6、逐次弹出栈顶无进栈,直到栈空。

凡在栈中出现过(A,a)的数组F[A,a]为1。

+

*

i

#

E’

1

E

1

1

1

1

1

T

1

1

1

1

F

1

1

1

P

1

1

FIRSTVT(E’)={#}FIRSTVT(E)={+,*,,(,i}

FIRSTVT(T)={*,,(,i}FIRSTVT(F)={,(,i}

FIRSTVT(P)={(,i}

★2)同样我们可得,构造LASTVT(P)的算法。

a)方法1——根据LASTVT的定义,按下面的规则来构造:

①若有产生式P…a或P…aQ,则aLASTVT(P)

②若aLASTVT(Q),且有产生式P…Q,则aLASTVT(P)

b)方法——基本思想:

使用两个特殊的数据结构,一个是二维布尔矩阵F,行标为非终结符P,列标为终结符a;F[P,a]=true,当且仅当aLASTVT(P);另一个是堆栈STACK,栈中动态存放曾在F[P,a]中为真的序偶(P,a)。

算法类似。

我们有了每个非终结符P的FISTVT(P)和LASTVT(P)之后我们就能够造文法G的优先表。

★3)构造算符优先表的算法

FOR每条产生式PX1X2…XnDO

{FOR(i=1,i<=n-1,i++)

{ifXi和Xi+1均为终结符then置Xi=·Xi+1;

ifi<=n-2andXi和Xi+2均为终结符andXi+1为非终结符then置Xi=·Xi+2;

ifXi为终结符而Xi+1为非终结符then

forFIRSTVT(Xi+1)中的每个aDO{置Xi<·a}

ifXi为非终结符而Xi+1为终结符then

forLASTVT(Xi)中的每个aDO{置a·>Xi+1}}

注;如果文法G按此算法构造出的优先表没有重定义项,则文法G是个算符优先文法。

※例:

构造下面文法的算符优先表。

SifEbthenEelseEEE+T|TTT*F|FFiEbb

解:

1)求各非终结符的首终结符集和尾终结符集。

为了考虑语句的开始和结束符号“#”,对文法拓广,加一个产生式S’#S#

FIRSTVT(S)={if}LASTVT(S)={else,+,*,i}

FIRSTVT(E)={+,*,i}LASTVT(E)={+,*,i}

FIRSTVT(T)={*,i}LASTVT(T)={*,i}

FIRSTVT(F)={i}LASTVT(F)={i}

FIRSTVT(Eb)={b}LASTVT(Eb)={b}

2)填写算符优先表

if

then

else

+

*

i

b

#

If

Then

Else

·>

+

·>

·>

·>

*

·>

·>

·>

·>

i

·>

·>

·>

·>

b

·>

#

四、算符优先分析方法

1、优先表构造算法的讨论

构造优先表的算法仅仅反映文法符号间关系,并不反映附加条件,对二义性文法构造算符优先表,可能会出现多重定义项.

2、非规范分析

1)规范归约:

严格按照句柄进行归约,终结符和非终结符一起考虑,只要栈顶形成句柄,不管句柄内是否包含终结符都要进行归约。

2)算符优先分析:

在算符优先分析中,仅研究终结符之间的优先关系,而不考虑非终结符之间的优先关系,但句柄是由终结符和非终结符一起构成的,所以算符优先分析相对来说是非规范的分析。

3、最左素短语

在算符优先分析中,可归约的短语不再称为句柄,而称为最左素短语。

素短语是指这样一个短语,至少含有一个终结符,且除它自身外不再包含其他素短语,最左边的素短语称为最左素短语。

※例如:

考虑非二义的表达式文法G(E):

EE+T|TTT*F|FF(E)|i

句型#T+T*F+i#的素短语是什么?

我们把算符优先文法句型(括在两个#号之间)的一般形式写成:

#N1a1N2a2

…NnanNn+1#其中每个ai都是终结符,Ni是可有可无的非终结符。

一个算符优先文法G的任何句型的最左素短语是满足如下条件的最左子串:

Njaj…NiaiNi+1,aj-1<·ajaj=aj+1,…,ai-1=·aiai·>ai+1

根据这个最左素短语的定义我们可以构造算符优先分析算法。

4、算符优先分析算法

在文法的产生式中存在右部符号串的符号个数与该素短语的符号个数相等,非终结符号对应Nk,(k=i,…,j+1)不管其符号名是什么。

终结符对应ai,…,aj,其符号名要与ai,…,aj的实际名相一致,相应位置也一致,才有可能形成素短语。

我们在分析过程中可以设置一个符号栈S,用以寄存归约或待形成最左素短语的符号串,用一个工作单元a存放当前读入的终结符号,归约成功的标志是当读到句子结束符#时,S栈中只剩#N,即只剩句子最左括号'#'和一非终结符N。

 

k=1;s[k]=‘#’;/*S为下推栈,这里称符号栈*/

repeat将一个输入符号读入SYM中;

IFS[k]VTTHENj=k

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

当前位置:首页 > 工程科技 > 能源化工

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

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