编译原理第五章语法分析—自上而下分析

自下而上分析法就是从输入串开始,逐步进行规约,直到文法的开始符号。

一,基本思想

1,规约

用一个寄存符号的先进后出栈,把输入符号一个一个地移进到栈里,当栈顶形成某个产生式的候选式时,即把栈顶的这一部分替换成(归约为)该产生式的左部符号。

如:设文法G:
       S -> aAcBe
       A -> b
       A -> Ab
       B -> d

 怎样把输入串abbcde规约到S?

首先a进栈,然后b进栈,根据规则 A -> b,把栈顶的b规约成A;再让第二个b进栈,这时栈顶是Ab,根据规则A->Ab,把Ab规约成A,类推下去。

为什么栈中是aAb的时候要用A->Ab把Ab规约,而不是用A -> b把b规约呢?自下而上分析的中心问题就是,怎样判断栈顶的符号的可规约性,以及如何规约。

2,规范规约

短语
 定义:令G是一个文法,S是文法的开始符号,假定是文法G的一个句型
 如果有

 
 
 则β称是句型相对于非终结符A的短语。

 直接短语:特别是,如果有A=>β,则称β是句型 相对于规则A->β的直接短语。

句柄:一个句型的最左直接短语称为该句型的句柄


例: G   : E -> T | E+T
               T -> F | T*F
               F -> (E) | i

对该文法的一个句型i1*i2+i3,

编译原理第五章语法分析—自上而下分析_第1张图片

课后题1:

编译原理第五章语法分析—自上而下分析_第2张图片

规范规约的过程:

假定是文法G的一个句子,我们称序列
       αn, αn-1,.....,α0
   是的一个规范归约,如果此序列满足:
  (1)  αn= α
  (2)  α0为文法的开始符号,即α0=S
  (3)  对任何i,0 < i <= n, αi-1是从αi经把句柄替换成为相应产生式左部符号而得到的。
例,  文法G

      S -> aAcBe
       A -> b
       A -> Ab
       B -> d

句子abbcde的规范归约

abbcde =>aAbcde =>aAcde =>aAcBe =>S

最右推导:S => aAcBe=> aAcde =>aAbcde => abbcde
规范归约是关于是一个最右推导的逆过程
由规范推导推出的句型称为规范句型。

对语法树:
 每个句型都有一棵语法树与之对应
 每棵语法树的叶结点自左至右排列就组成一个句型
 每棵子树的叶结点自左至右排列就组成一个短语
 每棵简单子树的叶结点自左至右排列就组成一个直接短语
 每棵最左简单子树的叶结点自左至右排列就组成一个句柄

用符号栈自下而上语法分析:

课后题2

编译原理第五章语法分析—自上而下分析_第3张图片

编译原理第五章语法分析—自上而下分析_第4张图片

编译原理第五章语法分析—自上而下分析_第5张图片



二,算符优先分析

定义两个终结符‘a’与‘b’的优先关系
 a =.b   表示a的优先性等于b
 a >.b   表示a的优先性大于b
 a <.b   表示a的优先性小于b

 =.  >. <. 不同于数学上的 = < >,所有两边的a,b没有交换性,三个终结符之间也没有传递性

一个文法,如果它的任一产生式的右部都不含两个相继(并列)的非终结符,即不含如下形式的产生式右部:
…QR…
    则我们称该文法为算符文法,也称OG文法

假定G是一个不含空字产生式的算符文法。对于任何一对终结符a、b,我们说:

1. a =. b 当且仅当文法G中含有形如P→…ab…或P→…aQb…的产生式;

2. a <. b 当且仅当G中含有形如P→…aR…的产生式, 而R    最终推出b…或R   最终 推出Qb…;

3. a>.b 当且仅当G中含有形如P→…Rb…的产生式,而 R   最终推出 …a或R  最终推出  …aQ。

即a、b谁先出现谁优先级低(因为规约是推导的逆过程,先推导的后规约),同一个产生式中出现的优先级同

如果一个算符文法G中的任何终结符对(a,b)至多只满足下述三关系之一:
   a=.b
   a>.b
   a<.b

    则称G是一个算符优先文法(OPG文法)。


构造算符优先关系表
(1)通过检查产生式的每一个候选式可以找出满足a=.b
  (即P→…ab…或P→…aQb…的产生式)
(2)为了满足<.和>.,需对G中每个非终结符P构造两个集合FIRSTVT(P)和LASTVT(P):

编译原理第五章语法分析—自上而下分析_第6张图片



构造集合FIRSTVT(P)的算法
 按其定义,可用下面两条规则来构造集合FIRSTVT(P):

 ① 若有产生式P→a…或P→Qa…,
  则a∈FIRSTVT(P);

 ② 若a∈FIRSTVT(Q),且有产生式P→Q…,
  则a∈FIRSTVT(P)。即P每一步推导中第一个出现的终结符的集合。
同理构造构造集合LASTVT(P)的算法
 按其定义,可用下面两条规则来构造集合LASTVT(P):

 ① 若有产生式P→… a或P→… aQ ,
  则a∈ LASTVT(P);

 ② 若a∈ LASTVT(Q),且有产生式P→… Q ,
  则a∈ LASTVT(P)。

有了这两个集合之后,就可以通过检查每个产生式的候选式确定满足关系<.和>.的所有终结符对。
(1)假定有个产生式的一个候选形为
…aP…
  那么,对任何bFIRSTVT(P),有a <. b。
(2)假定有个产生式的一个候选形为
…Pb…
  那么,对任何aLASTVT(P),有a >. b。

这样就可以求得优先表。

算符优先分析算法

移进-归约法:句柄为可归纳串
 算符优先分析法:最左素短语为可归纳串
素短语
 指一个句型的短语,它至少包括有一个终结符号且除去它本身之外不再含任何更小的素短语

最左素短语
 处在句型最左端那个素短语成为最左素短语

例,课后题3

编译原理第五章语法分析—自上而下分析_第7张图片

编译原理第五章语法分析—自上而下分析_第8张图片


三,LR分析法

1,LR分析器


LR分析器

动作表:
  ACTION[s,a]:
  当状态s面临输入符号a时,应采取什么动作

 状态转换表:
  GOTO[s,X]:
  状态s面对文法符号X时,下一状态是什么

动作表
 ACTION[s,a]:当状态s面临输入符号a时,应采取什么动作
 每一项ACTION[s,a]所规定的四种动作:
<1>. 移进
<2>. 归约
<3>. 接受
<4>. 报错
<1>. 移进 
 把(s,a)的下一状态s’=GOTO[s,a] 和输入符号a推进栈,下一输入符号变成现行输入符号.
<2>. 归约 
 指用某产生式A进行归约.  假若的长度为r, 归约动作是A, 去除栈顶r个项,使状态sm-r变成栈顶状态,然后把(sm-r, A)的下一状态s’=GOTO[sm-r, A]和文法符号A推进栈.
<3>. 接受  宣布分析成功,停止分析器工作。
<4>. 报错  发现源程序含有错误,调用出错处理程序

文法G(E):
   (1) E→E+T
(2) E→T
(3) T→T*F
(4) T→F
(5) F→(E)
(6) F→i

分析i*i+i

其LR分析表为:

编译原理第五章语法分析—自上而下分析_第9张图片

表中记号的意义:

(1) sj 把下一状态j和现行输入符号a移进栈

(2) 按第j个产生式规约

(3) acc 接受

(4) 空白格 出错标志

分析举例:S5就是把i移进栈,并跳转到状态5,即0号状态下,i进栈时,把i移进栈,同时5号状态进栈

                在4号状态下若面对E,根据GOTO函数,则把当前栈顶句柄规约成E(句柄出栈,E进栈)(同时状态4出栈),

                然后状态8进栈

 分析器工作过程如下:

编译原理第五章语法分析—自上而下分析_第10张图片

举例分析:(2)中,读头向后移,到*,即5号状态遇到*,按表则r6,按第6个产生式规约。

即【5,i】出栈,F进栈,状态5出栈后,状态栈顶是0,即0状态遇到F,按表转到3号状态,则状态3进栈

2,LR(0)项目集族

活前缀:文法G的活前缀是他的规范句型的前缀,该前缀不超过句柄的右端。

活前缀和句柄的关系:

(1)活前缀中已含有句柄的全部符号(句柄的符号即为其最右符号)。这表明:此时某一产生式A→β的右部符号串β已出现在栈顶,因此相应的分析动作应当是用此产生式进行归约。
(2)活前缀中含句柄的一部分符号(句柄开头的 若干符号与活前缀最右的若干个符号一致)。这表明形如A→β1β2的产生式的右部子串β1已出现在栈顶,正期待着从余留输入串中看到能由β2推出的符号串。
(3)活前缀中全然不包含句柄的任何符号 。
第三种情况则意味着,期望从余留输入串中能看到由某一产生式A→α右部,即A所推出的符号串。

LR分析表的构造需要构造识别活前缀的有限自动机

LR(0)项目

        A→β·
  A→β1·β2
  A→·α
右部某位置上标有圆点的产生式称为相应文法的一个LR(0)项目,特别对形如A→ε的产生式,A→·。
圆点之前是已识别的,之后是没有识别的。

若项目i为X→X1X2...Xi-1 • Xi…Xn。项目j为X→X1X2...Xi-1Xi • Xi+1…Xn。
则从状态i到状态j连一条标记为Xi的箭弧。

若i为X→α•Aβ,k为A→•γ,则从状态i画标记为的箭弧到状态k。

构成识别一个文法活前缀的DFA项目集(状态)的全体称为这个文法的LR(0)项目集规范族

构造G的拓广文法G’
 设S为文法G的开始符号,构造一个文法G’,它包含整个文法G,并且引进了一个不出现在G中的非终结符S,并加进一个新产生式S→S,这个S是G的开始符号。把G’成为G的拓广文法。(有一个仅含项目S→S. 的状态,这就是唯一的“接受”状态)

假定I是文法G'的任一项目集,构造I的闭包CLOSURE(I)的办法是:
1)  I的任何项目都属于CLOSURE(I);
(2)  若A→·B属于CLOSURE(I),那么,对任何关于B的产生式B→的项目B→·也属于CLOSURE(I);
(3)  重复执行上述两步骤直至CLOSURE(I) 不再增大为止

 定义转换函数如下:
 GOTO(I,X)=CLOSURE(J)其中:
 I为包含某一项目集的状态,
 X为一文法符号,
 J={任何形如A→αX•β的项目|A→α•Xβ属于I}。
即I通过识别X到达CLOSURE(J)

2,LR(0)分析表的构造

一个项目集可能包含多种项目

A)移进和归约项目同时存在。移进-归约冲突
B)归约和归约项目同时存在。归约-归约冲突
若其LR(0)项目集规范族不存在移进-归约,或归约-归约冲突,称为LR(0)文法。

a)若项目A→α•aβ属于Ik,且转换函数GO(Ik,a)=Ij,当a为终结符时 ,则置ACTION[k,a]为Sj。
b)若项目A→α •属于Ik, 则对a为任何终结符或#′,置ACTION[k,a]=rj, j为产生式在文法G′中的编号。
c)若GO(Ik,A)=Ij,则置GOTO[k,A]=j,其中A为非终结符,j为某一状态号。
d)若项目S′→S•属于Ik,则置ACTION[k,#]= acc。
e)其它填上“报错标志”。

对于文法:

S'->E

E->aA

E->bB

A->cA

A->d

B->cB

B->d


如下是LR(0)分析表:

编译原理第五章语法分析—自上而下分析_第11张图片

3,SLR分析

对于有冲突的状态,向前查看一个符号,以确定采用的动作。
一个LR(0)规范族中含有如下的项目集(状态)I,
I={X→α•bβ,A→α•,B→α•}

其中,第一个是移进项目;第二、三个是规约项目。三个项目的动作冲突。第一个项目应把下一个输入符号移进,第二、三个项目应把α规约。

解决:分析所有含有A或B的句型,考察句型中可能直接跟在A或B之后的终结符,即考察FOLLOW(A)和FOLLOW(B),如果这两个集合不想交,而且都不包含b,那么,当状态i面临任何输入符号a时,可以采用如下决策:


 1)若a=b,则移进。
 2)若a∈FOLLOW(A),则用产生式A→α进行归约。
 3)若a∈FOLLOW(B),则用产生式B→α进行归约。
 4)此外,报错。

例:课后题5
编译原理第五章语法分析—自上而下分析_第12张图片

编译原理第五章语法分析—自上而下分析_第13张图片


编译原理第五章语法分析—自上而下分析_第14张图片




你可能感兴趣的:(编译原理第五章语法分析—自上而下分析)