SlideShare a Scribd company logo
1 of 76
第 6章

自底向上的
LR 分析法


         1
在第 5 章的自底向上分析中的
关键问题是寻找可归约串。
      简单优先分析方法、算符优
先分析方法,基本上都是从左到右
地向前看若干个输入符号,找出句
柄 ( 或其变型 — 最左素短语 ) 的尾,
然后回头 ( 从右到左 ) 查看已扫描过
的符号,找出句柄 ( 或其变型 — 最左
素短语 ) 的头。
      这实际上已不是严格地从左
到右地查看源程序进行归约了。           2
LR 分析法是严格的规范归约


  LR 分析法是一种自底向上的语法
分析方法,它严格地从左到右地读入输
入符号串中的符号,且最多向前看确定
个数 (K 个 ) 的符号,就能无回溯地识别
给定的符号串。


                         3
它与算符优先分析法一样,也
通过当前输入符号和栈顶符号 ( 状态 )
相比较,根据栈中的符号串和向前查
看的 k(k≥0) 个输入符号,就能唯一确
定分析器的动作是移进还是归约,以
及用哪个产生式进行归约。



                        4
本章主要内容

   本章主要介绍 LR 分析的基本思
想和当 K≤1 是 LR 分析方法的基本构造
原理和方法。

 组成:总控程序 + LR 分析表 + 分析
栈


                         5
分析表的构造方法:
规范的 LR 法 :
 LR(0) ,能力最弱,理论上最重要;
 LR(1) ,它功能最强,但代价也最大。
简单的 LR 法:
  简称 SLR ,最容易实现,但功能最弱
。
向前看的 LR 法:
  简称 LALR ,功能和代价处于前两者 6
之间。
§ 6.1

LR 分析的
基本原理

         7
在语法分析中,句柄是逐步形成
的。
   据此,可以用 “ 状态” 的概念来
描述不同时刻所形成的那部分句柄。
   把每个句柄的识别过程划分为
若干状态,在每个状态下从左到右识
别句柄的一个符合。


                       8
在规范归约过程中,一方面记住已
移进和归约出的整个符号串,即记住 “ 历
史” ,另一方面根据所用的产生式推测未
来可能碰到的输入符号,即对未来进行 “
展望” 。
      当一串貌似句柄的符号串呈现于
分析栈的顶端时,根据所记载的 “ 历史 ”
和 “ 展望 ” 以及 “ 现实” 三方面的材料,来
确定栈顶的符号串是否构成句柄。
                             9
但 “ 展望 ” 材料的汇集是很困难的
,因为根据 “ 历史 ” 推测未来,即使是推
测未来一个符号也存在非常多的可能。




                         10
LR 分析法的实现原理

      为了记住分析的 “ 历史 ” 和汇集 “
展望 ” 的信息, LR 分析法这样处理:
       将归约过程的 “ 历史 ” 和 “ 展望 ”
材料综合抽象成某些状态,存放在一个
状态栈中,栈中每个状态都概括了从分
析开始直到某一归约阶段的全部 “ 历史 ”
和 “ 展望 ” 材料。

                                11
LR 分析法的每一步工作都是由栈
顶状态和当前输入符号所唯一确定的
。
      一个 LR 分析器实质上是一个
带先进后出栈的确定的有限自动机。




                        12
§ 6.2

LR 分析器
的逻辑结构

         13
LR 分析法的实现
  LR 分析法也是一种表驱动的分析
方法,有一个分析栈、一个总控程序和
一个分析表。
特殊性
  栈 = 状态栈 + 文法符号栈
  分析表 = 动作表 (ACTION) + 状态转移表
(GOTO)
总控程序都一样
文法不同,分析表不同
LR 分析表是   LR 分析器的核心部分
                               14
LR 分析器的逻辑结构
              输入串 a … a … a #
                   1   i   n
状态符号栈

Sn     Xn            总控程序       输出
Sn-1   Xn-1
 …      …
 …      …
 …      …
 S1     X1      动作表      状态转移表
                                分析表
 S0             action     goto
        #                             15
ACTION 表

  ACTION 表是一个状态及终结符的
二维矩阵; ACTION[si,a] 定义了在栈顶
状态 si 下,当前输入符为 a 时应采取的
动作,不外乎下列四种:




                            16
① 移进:若 ACTION[Si ,a]=sj(shift) ,
将状态 sj 及当前输入符 a 移入栈顶。
② 归约:若 ACTION[Si ,a]
=rj(reduce) ,将栈顶内容按第 j 个产
生式归约。
③ 接受:若 ACTION[Si ,a] =acc ,则
分析成功,正常停止。
④ 报错:若 ACTION[Si ,a] =error ,
语法出错,进行出错处理。                       17
GOTO 表

  GOTO 表是一个状态及非终结符的
二维矩阵; GOTO[Si,X] 定义了当栈顶
状态遇到当前符号时应转向的状态。




                          18
LR 分析法的分析过程

       总控程序对任何 LR 分析法都
适用。它从输入串中读入当前输入符
a ,然后由栈顶状态 si 与当前输入字符
a 查看 ACTION 表,决定应采取何种动
作。




                         19
若为 sj ,则将状态 j 及当前输入符 a 移入栈
顶。
若为 rj ,则按第 j 个产生式 A→β 归约,若
β 的长度为 r ,则从状态栈和文法符号栈中
自栈顶向下去掉 r 个符号,并把 A 移入文
法符号栈内, sj=GOTO[si , A] 移进状态栈。
其中 si 为修改后的栈顶状态。
若为 acc ,则分析成功,结束。

其他转错误处理程序。
                                20
对输入串 abbcde# 的 LR 分析过
步骤 符号栈 输入符号 动作  状态栈  ACTION                                   GOTO
  程 串
1)     #        abbcde#     移进            0        S2
2)     #a       bbcde#      移进            02       S4
3)     #ab       bcde#     归约 (A→ b)      024      r2           3
4)     #aA        bcde#     移进            023       S6
5)     #aAb        cde#     归约 (A→ Ab)    0236      r3           3
6)     #aA        cde#       移进           023       S5
7)     #aAc        de#       移进           0235      S8
8)     # aAcd       e#     归约 (B→ d)      02358         r4       7
9)     #aAcB        e#       移进           02357         S9
10 )   #aAcBe        #    归约 (S→ aAcBe)   023579        r1       1
11 )   #S            #       接受           01            acc

Si: 移进,将状态 i 和输入符进栈
ri: 归约,用第 i 个产生式归约,同时状态栈与符号栈退出相应个符号
                                  21

,并把 GOTO 表相应状态和第 i 个产生式的左部非终结符入栈。
§ 6.3

LR(0)
分析法

        22
首先讨论一种只概括 “ 历史 ” 资
料而不包含推测性 “ 展望 ” 材料的 “ 状态 ” 。
我们希望仅由这种简单状态就能识别呈
现在栈顶的句柄。
   在讨论之前,需要定义一个重
要概念,即文法的规范句型的 “ 活前缀”
。


                           23
规范句型的活前缀
   字 ( 符号串 ) 的前缀:字的前缀是指该字的
    任意首部。
   活前缀:是指规范句型的活前缀,它不包含
    该句型的句柄右边的任何符号。
   在活前缀的右边添上一些终结符号后,总可
    以构成一个规范句型。
    LR 识别过程中,栈里面的符号 ( 自栈底而
    上 ) 就是一个活前缀,把输入串的剩余部
    分配上后应成为一个规范句型。因此,只
    要输入串已扫描过的部分能构成一个活前
    缀,则意味着所扫描过的这一部分没有错        24

    误。
活前缀和句柄的关系
文法 G[S]: 若 S => αAω =>αβω   r 是 αβ 的前缀
,则称 r 是 G 的一个活前缀。
活前缀已含有句柄的全部符号,表明产生
式 A→β 的 右部 β 已出现在栈顶。
活前缀只含句柄的一部分符号表明
A→β1β2 的右部子串 β1 已出现在栈顶,期
待从输入串中看到 β2 推出的符号。
活前缀不含有句柄的任何符号,此时期望
A→β 的右部所推出的符号串。                      25
对规范句型活前缀的识别
    对于一个文法 G ,可以构造一 DFA
去识别给定文法的所有规范句型的活前缀,进
而由此构造文法的 LR 分析表,用来指导对句
柄的识别 — 可根据分析栈的栈顶状态了判断是
否得到句柄,并进行归约。只要输入串的已扫
描的部分 ( 符号栈中的内容 ) 可构成一个活前
缀,则说明所扫描过的部分没有错误。
    这样,对句柄的识别就变成了对规范
句型活前缀的识别。因此,活前缀反映了句柄
的识别状态。
                           26
LR(0) 项目
 定义:在文法的每一个产生式的右部适
  当位置添加一个圆点 “ .” ,则一个
  LR(0) 项目。
 A → xyz 的 LR(0) 项目:

  1. A → · xyz
  2. A → x · yz
                   注意:一个产生式可对应的
  3. A → xy · z    项目为它的右部符号长度加
                   1 ,对空产生式 A→ε 仅有
  4. A → xyz ·     项目 A→· 。
                                 27
直观地,一个项目指明了在分
析过程的某一时刻,已经看到的一个产
生式的多少。 即在 LR(0) 项目
中, “ ·” 左部符号串表示已被识别出来
的句柄符号。 “ ·” 右部符号串表示待识
别的符部分。
       可以由文法的所有 LR(0) 项目,
构造识别文法所有活前缀的 DFA 。

                            28
根据圆点所在的位置和圆点后
是终结符还是非终结符或为空把项目分
为以下几种:
移进 项目,形如 A →α • a β
待约 项目,形如 A →α • Bβ
归约 项目,形如 A →α •
接受 项目,形如 S’ →S •

                      29
构造识别活前缀的 NFA

 文法 G[S] 的拓广: G’[S’]=G[S]+{S’ →
  S}
 文法的每个项目为 NFA 的一个状态。

 确定状态之间的转换关系

 按规则可对文法 G’ 的所有项目对应的
  状态构造出识别活前缀的 NFA 。


                                   30
NFA 中初终态的确定

G’[S’]=G[S]+{S’ → S}
 由于 S’ 仅在第一个产生式的左部
出现,因此规定项目 1 为初态;
 其余每个状态都为活前缀的识别态
;
 圆点在最后的项目为句柄识别态;

 第一个产生式的句柄识别态为句子
的识别态。                  31
LR(0) 项目集规范族

提出 “ LR(0) 项目集规范族 ” 的原因
      若按以上方法先构造 NFA ,然
后再确定化为 DFA ,这样工作量较大
,不可取。

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

         可利用闭包函数 (CLOSURE)
求出 LR(0) 项目集规范族中的每个项目
集 (DFA 的状态 ) ,然后根据转换函数
(goto) 直接构造 DFA 。




                             33
构造步骤

 对文法进行拓广;
 构造拓广文法的 LR(0) 项目集规范族

(由初始项目出发,利用 CLOSURE 和
  goto 函数);
 将 LR(0) 项目集规范族中的每个项目
  集作为 DFA 的状态,将 goto 函数作
  为状态转换函数,构造出的 DFA 即为
  所求。                    34
项目集 I 的闭包 CLOSURE(I)

    设 I 是文法 G’( 拓广文法 ) 的任一项目集
,则定义和构造 CLOSURE(I) 的规则如下:
① 属于 I 的任何项目也属于 CLOSURE(I) ;
② 若 A → α .Bβ 属于 CLOSURE(I) ,那么,对
 于任何关于 B 的产生式 B→ γ , 项目 B→ .γ 也
 属于 CLOSURE(I) ;
③ 重复②直到 CLOSURE(I) 不再增大为止。此
 CLOSURE(I) 即为所求的一个项目子集,将其
 作为 DFA 的一个状态。
                                35
项目集闭包的例子
   文法:          若 I={E ’ →.E}
    0. E ’ → E   CLOSURE(I) 为
                 : ’ →.E
                 E
    1. E → E+T
    2. E → T     E→.E+T
    3. T → T*F   E→.T
    4. T → F     T→.T*F
                 T→.F
    5. F →(E)
                 F→.i
    6. F → i
                 F→.(E)          36
goto(I,X) 函数
   如果 LR(0) 项目集规范族中的每个项目集
    看做 DFA 一个状态,则项目集规范族的
    goto 函数把这些项目集连接成一个 DFA 。
   定义:设 I 是一个项目集 ,X 是任一文法符
    ,则 goto(I,X) 定义为:
     goto(I,X)=CLOSURE(J),
     其中 J={ 任何具有 [A → αX.β] 的项目 | [A
      → α.Xβ] ∈ I }
                   X
      I: A→α·Xβ          J: A→αX·β
                                        37
重要结论

     构造拓广文法的项目集规范族
C 时,其中的项目集可看作一个 DFA
的状态,该 DFA 能够识别文法的所有
活前缀。 C 上的 goto 函数可以看作
DFA 的状态转换函数。
   初始状态: CLOSURE({S ’ →.S})



                              38
LR(0) 文法

    如果文法 G’ 的项目集规范族的
每个项目集中不存在下述冲突项目:
  ① 移进项目和归约项目并存,
  ② 多个归约项目并存,
 则称文法 G’ 为 LR(0) 文法。
 注意:只有对于 LR(0) 文法,才能构
造它的 LR(0) 分析表。
                        39
LR(0) 分析表的构造

  设文法 G’ 的项目集规范族
C={I0,I1,…,In},
       令其中每个项目集的下标作
为分析器的状态。
      令包含项目 [S’ → .S] 的项目
集 Ik 的下标 k 为分析器的初态。
     构造 LR(0) 分析表的步骤如
下:                          40
① 若项目 A→α.aβ∈ Ii 且
移进
项目
     goto(Ii,a)=Ij, 其中 a 为终结符,置
     ACTION[i,a]=“ 把状态 j 和符号 a
     移进栈 ” ,简记为 “ sj”;
归约
项目
     ② 若项目 A→α.∈ Ii , 则对于任何输
     入符 a 或结束符 # ,置
     ACTION[i,a]=“ 用产生式 A→α 进
     行归约 ” ,简记为 “ rj”( 假定 A→α
                              41
     是文法 G’ 的第 j 条产生式 );
接受   ③ 若项目 S’→S.∈ Ii ,则置
项目   ACTION[i,#]=“ 接收 ” ,简记
     为 ‘ acc’ ;

     ④ 若 goto(I,A)=Ij , A 为非终结符
     ,则置 GOTO(i,A)=j

     ⑤ 分析表中凡不能用规则① - ④
     添入信息的元素均置上 ERROR 。
                                  42
构造 LR(0) 分析表的步骤小结

 文法拓广、产生式编号;
 利用 CLOSURE 和 goto 函数,求出项
  目集规范族 C;
 构造识别活前缀的 DFA ;

 由算法构造 LR(0) 分析表。




                             43
§ 6.4

  SLR
分析表的构造

          44
使用 SLR(1) 的原因
例: G: (0) S’→S (1) S→rD (2) D→D,i (3) D→i
LR ( 0 )项目集规范族
I0: S’→ . S      I3: S→r D .
    S→ . r D        D→D . i
I1: S’→S .           I4: D→i .
I2: S→r . D      I5: D→D . i
  D→ . D i       I6: D→Di .
   D→ . I      其中 I3 中含有移进 / 归约冲突。
文法不是 LR(0) 的,如何解决?                     45
SLR(1) 分析法

        若 LR(0) 项目集规范族中有
项目集 IK 含移进 / 归约、归约 / 归约冲
突: IK :{X→α.bβ, A → γ . , B →δ. }


  若满足 FOLLOW(A) ∩FOLLOW(B)
=φ
    FOLLOW(A) ∩ { b } =φ
    FOLLOW(B) ∩ { b} =φ             46

  冲突即可解决。这就是 SLR(1) 分析
当在状态 Ik 时面临某输入符号
a 时,则动作可由下规定决策。
          若 a=b ,则 action [ k,b ] = 移进
。
          若 a ∈FOLLOW (A) ,则 action
[ k,a ] = 用 A → γ 归约。
          若 a ∈FOLLOW (B) ,则 action [
k,a ] = 用 B→δ 归约。
          能用 SLR(1) 技术解决冲突的文
法称为 SLR(1) 文法。                         47

     SLR(1) 文法是无二义的。
SLR 分析表

移进   ① 若项目 A→α.aβ∈ Ii 且
项目   goto(Ii,a)=Ij, 其中 a 为终结符,置
     ACTION[i,a]=“ 把状态 j 和符号 a
     移进栈 ” ,简记为 “ sj”; ( 同 LR(0))
归约   ② 若项目 A→α .属于 Ii, 那么,
项目
     对任何输入符号 a, a∈ FOLLOW(A),
     置 ACTION[i, a] 为 “ 用产生式 A→α
     进行规约 ” ,简记为 “ rj”; 其中,假
     定 A→α 为文法 G’ 的第 j 个产生式
                                    48
接受   ③ 若项目 S’→S.∈ Ii ,则置
项目   ACTION[i,#]=“ 接收 ” ,简记
     为 ‘ acc’ ; ( 同 LR(0))

     ④ 若 goto(I,A)=Ij , A 为非终结符
     ,则置 GOTO(i,A)=j ( 同 LR(0))

     ⑤ 分析表中凡不能用规则① - ④
     添入信息的元素均置上 ERROR 。
     ( 同 LR(0))                   49
按上述算法构造的含有
ACTION 和 GOTO 两部分的分析表,
如果每个入口不含多重定义,则称它
为文法 G 的一张 SLR 表。
      具有 SLR 表的文法 G 称为一
个 SLR ( 1 )文法。
      数字 1 的意思是,在分析过程
中顶多只要向前看一个符号。

                          50
§ 6.6

  LR(1)
分析表的构造

          51
用 SLR(1) 也不能解决的冲突

文法 G:(0)S’→S (1) S→aAd (2) S→bAc
 (3)S→aec (4) S→bed (5) A→e
LR(0) 项目集规范族(识别 G 的活前缀的
  DFA) :
 I0: S’→ . S I1: S’→S . I2: S→a . Ad
  S→ .   aAd             S→a . ec
  S→ .   bAc             A→ . e
  S→ .   aec
  S→ .   bed                           52
I3: S→b . Ac   I4:         I5:
 S→b . ed       S→aA . d    S→ae . c
 A→ . e                    A→e .

I6:            I7:         I8:
  S→bA . c           S→be . d
 S→aAd .
                 A→e .
                                       53
上例的 SLR 分析表
     ACTION                                        GOTO
      a    c       e    b     d       #        S   A
0    S2                S3                      1
1                                   acc
2                 S5                               4
3                 S7                               6
4                             S8
5    r5   r5/S9   r5    r5     r5         r5
6          S10
7    r7    r7     r7   r7    r7/S11       r7
8    r1    r1     r1   r1      r1         r1
9    r3    r3     r3   r3      r3         r3
10   r2    r2     r2   r2      r2         r2
11   r4    r4     r4   r4      r4         r4
                                                          54
对问题的进一步分析

           对于 SLR 分析法而言,若项目
[A→ α .] ∈ Ii ,则对于 a ∈ FOLLOW(A), 规定
ACTION[I,a]=“ 用 A→ α 归约 ” 。
           有时,当状态 i 出现在栈顶时,
栈里的符号串组成的活前缀 βα 未必允许把
α 归约为 A ,因为可能根本就不存在一个规
范句型含有前缀 “ βA a” 。在这种情况下,
用 A→ α 进行归约未必有效。

                                       55
不能用 SLR(1) 解决的原因
I5: S →ae . c
     A →e .
    R   R      R
 S’==>S==>aAd==>aed
    R   R
 S’==>S==>aec
I7: S →be . d
    A →e .
    R   R      R
 S’==>S==>bAc==>bec
    R   R
 S’==>S==>bed
  哪些输入符号能跟在句柄之后!      56
解决方案

      让每个状态携带更多的信息,
以帮助 LR 分析器解决语法分析过程中
可能面临的移进 - 归约冲突,并尽可能
排除不合适的归约动作。
      必要时需要对状态进行分裂,
以便 LR 的每个状态都恰好指明:当那
些输入符号紧跟 在句柄 α 之后时,才
允许利用产生式 A→ α 进行归约。
                      57
为此,需要重新定义项目,使
得每个项目包含两个部分 :
    第一部分就是原来的项目自身
,
    第二部分由一个终结符号 ( 或 #)
组成。



                         58
LR(1) 项目

   LR(0) 项
     目

定义: [ A → α.β, a ]
      在原来的 LR(0) 项目中加一
个向前搜索符 a ,这样得到的项目
称为 LR(1) 项目。

                         59
向前搜索符的意义

         向前搜索符 a 只对归约项目 [
A → α. , a ] 有意义,它表示当它所
属的状态处于栈顶,且下一个输入符
为 a 时,才可以将栈顶符号 α 归约为
A 。
        除此之外的其他符号出现,
即使 FOLLOW(A) 中的符号,也不归
约。
      在其他项目中, a 只是起传递       60

作用。
LR(1) 分析法

   若 A →α .B β ∈ 项目集 I
   则 B → . γ ( B → γ 是一产生式)
) I
        把 FIRST(β) 中的符号作为用
B → γ 归约的搜索符 , 称为向前搜索符
,作为归约时查看的符号集合用以代替
SLR(1) 分析中的 FOLLOW 集,把此搜
索符号的集合也放在相应项目的后面,
这种处理方法即为 LR(1) 分析法。           61
构造 LR(1) 项目集规范族

  1. 构造 LR(1) 项目集的 closure(I)
(1) I 的任何项目属 closure(I) ;
(2) 若 [A →α .B β , a]∈ closure(I) , B→
  γ 是一产生式,那么对于 FIRST(βa) 中
  的每个终结符 b ,如果 [B→ . . ,b] 不
  在 closure(I) 中,则把它加进去;
(3) 重复 (1)(2) ,直至 closure(I) 不再增大
  。                                  62
2. 构造 GO 转换函数
若 I 是一个项目集, X 是一个文法符号
GO(I, X)= closure(J)
其中 J={ 任何形如 [A→αX . β,a] 的项
 目∣ [A→α.Xβ,a]∈ I}
LR(I) 项目规范族 C 的构造算法类同
 LR(0) 的,只是初始时:
C={ closure( { S’→ . S , # } ) };
                                    63
LR(1) 分析表的构造
        设文法 G’ 的项目集规范族 C={I0,I1,
…,In}, 令其中每个项目集的下标作为分析器
的状态,令包含项目 [S’ → .S,#] 的项目集 Ik
的下标 k 为分析器的初态。构造 LR(1) 分析
表的步骤如下:
① 若项目 [A→α.aβ,b]∈ Ik 且 goto(Ik,a)=Ij, 其
  中 a 为终结符,置 ACTION[I,a]=“ 把状态 j
  和符号 a 移进栈 ” ,简记为 “ sj”;
② 若项目 [A→α.,a]∈ Ik , 则置
  ACTION[I,a]=“ 用产生式 A→α 进行归约 ”
  ,简记为 “ rj”( 假定 A→α 是文法 G’ 的第 j
  条产生式 );
                                          64
③ 若项目 [S’→S.,#]∈ Ik, 则置
ACTION[I,#]=“ 接收 ” ,简记
为 ‘ acc’ ;

④ 若 goto(I,A)=Ij,A 为非终结符,
则置 GOTO(I,A)=j

⑤ 分析表中凡不能用规则① - ④
添入信息的元素均置上 ERROR 。
                            65
构造 LR(1) 分析表的步骤小结


 文法拓广;
 写出基本 LR(1) 项目;

 构造识别活前缀的 DFA ;

 由算法构造 LR(1) 分析表




                        66
LR(0) 、 LR(1) 、 SLR(1) 的比较

   状态集的计算方法和 LR(0) 基本相同
   分析表的构造方法和 LR(0) 基本相同
构造方法的不同点:
   第 2 步处理中归约动作的选择:
    LR(0) 分析考虑所有终结符
    SLR(1) 分析参考 FOLLOW 集
    LR(1) 分析仅考虑 LR(1) 项目中的后继符
     ( 用 FIRST 集近似考虑 )           67
§ 6.7

 LALR(1)
分析表的构造

          68
LALR 分析技术

 Look Ahead LR technique.
 界于 LR(1) 分析器与 SLR(1) 分析器的之
  间的折衷方案。
 利用这种分析技术,构造出的 LALR 分
  析表的状态数等于 SLR 分析表的状态数
  ,比规范 LR 分析表少得多;分析能力
  比 LR 分析器要差一些,但比 SLR 强大
  ,能够处理一些 SLR 分析器难以处理的
  情况。
                           69
同心项目集

    对于两个 LR(1) 项集,如果除了
搜索符(向前看符号)外,其它完全相
同,那么这两个项集被称为同心项目集
。

       同心项目集的心:即对应的
LR(0) 项目集。
                      70
同心项目集的合并

 合并后的项目集的基本部分保持不变。
  基本部分相同项的搜索符被合并。
 原同心项目集之间的 goto 转换关系保持
  不变。
 同心项目集合并后,可能延迟报错的时
  间,但绝不会放过错误,在输入下一个
  符号之前肯定会发现错误。

                      71
合并可能引起的冲突

 合并引起的冲突是指:本来的 LR(1) 项
  目集没有冲突,而合并同心项目集后有
  冲突。
 引起 “ 归约 - 归约 ” 冲突。

  文法 {S’→S S→aAd|bBd|aBe|bAe
      A→c B→c}
  是 LR(1) 文法。
  合并同心集后导致归约 - 归约冲突。 72
LALR 的基本步骤
 首先生成 LR(1) 项集规范族。
 合并同心项目集。并且相应地建立合
  并后的项目集之间的转换关系。合并
  后的项目集的个数和 LR(0) 项目集规
  范族中的项集个数相同。
 根据这个项目集族,构造分析表。




                         73
LALR 分析表构造算法

1. 构造 LR(1) 项目集规范族 C={I0,I1,I2,
  …In} 。
2. 合并 C 中的同心集,记 C’={J0,J1,
  …,Jn} 为合并后的新族。令包含项目
  [S’ → .S,#] 的项目集 Ik 的下标 k 为
  分析器的初态。

                                  74
3. 根据 C’ 构造 ACTION 表:
   ① 若项目 [A→α.aβ,b]∈ Ji 且
   goto(Ji,a)=Ij, 其中 a 为终结符,置
   ACTION[J,a]=“ 把状态 j 和符号 a 移进
   栈 ” ,简记为 “ sj”;
   ② 若项目 [A→α.,a]∈ Ji , 则置
   ACTION[i,a]=“ 用产生式 A→α 进行归约
   ” ,简记为 “ rj”( 假定 A→α 是文法 G’ 的
   第 j 条产生式 );
   ③ 若项目 [S’→S.,#]∈ Ji , 则置
   ACTION[i,#]=“ 接收 ” ,简记为 ‘ acc’ ;
                                      75
4. 构造 GOTO 表:
   假定 J 是由 I1,I2,…,Im 合并后的新项目集
   ,其中,每个 Ii 都是一个 LR(1) 项目集,
   由于 I1,I2,…,Im 同心,因此 goto(I1,X),
   goto(I2,X) ,…,goto(Im,X) 也同心。令 K 是由
   这些同心项目集合并后的项目集,那
   么, goto(J,X)=K 。于是,若 toto(Ji,A)=Jj,
   则置 GOTO[i,A]=j 。
5. 分析表中凡不能用 3 、 4 添入信息的空白格
均置 ERROR 。
                                         76

More Related Content

What's hot

Oracle经典教程
Oracle经典教程Oracle经典教程
Oracle经典教程
yiditushe
 
process
processprocess
process
himmih
 
STL Container Usage Tips
STL Container Usage TipsSTL Container Usage Tips
STL Container Usage Tips
永泉 韩
 
Lambda演算与邱奇编码
Lambda演算与邱奇编码Lambda演算与邱奇编码
Lambda演算与邱奇编码
Qin Jian
 
第六章 函數與巨集
第六章 函數與巨集第六章 函數與巨集
第六章 函數與巨集
shademoon
 
数据结构复习笔记 树和二叉树
数据结构复习笔记 树和二叉树数据结构复习笔记 树和二叉树
数据结构复习笔记 树和二叉树
mengyingchina
 
17第十七讲(第七章中)(2)
17第十七讲(第七章中)(2)17第十七讲(第七章中)(2)
17第十七讲(第七章中)(2)
何青青 Clare
 
锁具装箱
锁具装箱锁具装箱
锁具装箱
visayafan
 

What's hot (16)

1 4對數函數
1 4對數函數1 4對數函數
1 4對數函數
 
認識 C++11 新標準及使用 AMP 函式庫作平行運算
認識 C++11 新標準及使用 AMP 函式庫作平行運算認識 C++11 新標準及使用 AMP 函式庫作平行運算
認識 C++11 新標準及使用 AMP 函式庫作平行運算
 
Oracle经典教程
Oracle经典教程Oracle经典教程
Oracle经典教程
 
第7章 语法制导翻译和中间代码生成
第7章 语法制导翻译和中间代码生成第7章 语法制导翻译和中间代码生成
第7章 语法制导翻译和中间代码生成
 
process
processprocess
process
 
STL Container Usage Tips
STL Container Usage TipsSTL Container Usage Tips
STL Container Usage Tips
 
Hi Haskell
Hi HaskellHi Haskell
Hi Haskell
 
Use Lambdas in Android
Use Lambdas in AndroidUse Lambdas in Android
Use Lambdas in Android
 
Lambda演算与邱奇编码
Lambda演算与邱奇编码Lambda演算与邱奇编码
Lambda演算与邱奇编码
 
第六章 函數與巨集
第六章 函數與巨集第六章 函數與巨集
第六章 函數與巨集
 
第4章 自顶向下的语法分析
第4章 自顶向下的语法分析第4章 自顶向下的语法分析
第4章 自顶向下的语法分析
 
Intro to C++ Basic
Intro to C++ BasicIntro to C++ Basic
Intro to C++ Basic
 
数据结构复习笔记 树和二叉树
数据结构复习笔记 树和二叉树数据结构复习笔记 树和二叉树
数据结构复习笔记 树和二叉树
 
17第十七讲(第七章中)(2)
17第十七讲(第七章中)(2)17第十七讲(第七章中)(2)
17第十七讲(第七章中)(2)
 
第1章 Matlab操作基础
第1章  Matlab操作基础第1章  Matlab操作基础
第1章 Matlab操作基础
 
锁具装箱
锁具装箱锁具装箱
锁具装箱
 

Viewers also liked

July Newsletter
July NewsletterJuly Newsletter
July Newsletter
mjcunny
 
世の中を変える色んな面白い人が持ち時間500秒でチラミセします!Clip「チラミセnight」vol.3
世の中を変える色んな面白い人が持ち時間500秒でチラミセします!Clip「チラミセnight」vol.3世の中を変える色んな面白い人が持ち時間500秒でチラミセします!Clip「チラミセnight」vol.3
世の中を変える色んな面白い人が持ち時間500秒でチラミセします!Clip「チラミセnight」vol.3
schoowebcampus
 

Viewers also liked (17)

Capital Markets Group - 2015 Services
Capital Markets Group - 2015 ServicesCapital Markets Group - 2015 Services
Capital Markets Group - 2015 Services
 
majalah detik_96
 majalah detik_96 majalah detik_96
majalah detik_96
 
Dragon exotics
Dragon exoticsDragon exotics
Dragon exotics
 
Derivatives trading db2 xml
Derivatives trading db2 xmlDerivatives trading db2 xml
Derivatives trading db2 xml
 
《昨年は1万社が合格!》創業時に知っておきたい、経済産業省から700万円の補助金を獲得する方法とは?
《昨年は1万社が合格!》創業時に知っておきたい、経済産業省から700万円の補助金を獲得する方法とは?《昨年は1万社が合格!》創業時に知っておきたい、経済産業省から700万円の補助金を獲得する方法とは?
《昨年は1万社が合格!》創業時に知っておきたい、経済産業省から700万円の補助金を獲得する方法とは?
 
La libre y la tortuga
La libre y la tortugaLa libre y la tortuga
La libre y la tortuga
 
Wishpond 取締役が語る!グローバルキャリア、チャンスの掴み方 〜 新卒の僕がカナダIT企業のCOOになったワケ 先生:赤津慧先生
Wishpond 取締役が語る!グローバルキャリア、チャンスの掴み方 〜 新卒の僕がカナダIT企業のCOOになったワケ 先生:赤津慧先生Wishpond 取締役が語る!グローバルキャリア、チャンスの掴み方 〜 新卒の僕がカナダIT企業のCOOになったワケ 先生:赤津慧先生
Wishpond 取締役が語る!グローバルキャリア、チャンスの掴み方 〜 新卒の僕がカナダIT企業のCOOになったワケ 先生:赤津慧先生
 
Tcc2 versaofinal201201 andre felipe de oliveira lopes
Tcc2 versaofinal201201   andre felipe de oliveira lopesTcc2 versaofinal201201   andre felipe de oliveira lopes
Tcc2 versaofinal201201 andre felipe de oliveira lopes
 
Schoo5
Schoo5Schoo5
Schoo5
 
Gestor de proyecto
Gestor de proyecto Gestor de proyecto
Gestor de proyecto
 
Actualog - Facebook для сложных технических изделий, материалов, оборудования
Actualog - Facebook для сложных технических изделий, материалов, оборудованияActualog - Facebook для сложных технических изделий, материалов, оборудования
Actualog - Facebook для сложных технических изделий, материалов, оборудования
 
Sales Pipeline...Evolve What and How You Sell
Sales Pipeline...Evolve What and How You SellSales Pipeline...Evolve What and How You Sell
Sales Pipeline...Evolve What and How You Sell
 
Matthew Cunningham Sept Newsletter
Matthew Cunningham Sept NewsletterMatthew Cunningham Sept Newsletter
Matthew Cunningham Sept Newsletter
 
July Newsletter
July NewsletterJuly Newsletter
July Newsletter
 
世の中を変える色んな面白い人が持ち時間500秒でチラミセします!Clip「チラミセnight」vol.3
世の中を変える色んな面白い人が持ち時間500秒でチラミセします!Clip「チラミセnight」vol.3世の中を変える色んな面白い人が持ち時間500秒でチラミセします!Clip「チラミセnight」vol.3
世の中を変える色んな面白い人が持ち時間500秒でチラミセします!Clip「チラミセnight」vol.3
 
Yasir Iftikhar CV
Yasir Iftikhar CVYasir Iftikhar CV
Yasir Iftikhar CV
 
MDR 2014 final
MDR 2014 finalMDR 2014 final
MDR 2014 final
 

Similar to 第6章 自底向上的lr分析法 (8)

第11章 目标代码生成
第11章 目标代码生成第11章 目标代码生成
第11章 目标代码生成
 
第2章
第2章第2章
第2章
 
第七章 图[3]
第七章 图[3]第七章 图[3]
第七章 图[3]
 
9789572239940 試閱章節
9789572239940 試閱章節9789572239940 試閱章節
9789572239940 試閱章節
 
系統程式 -- 附錄
系統程式 -- 附錄系統程式 -- 附錄
系統程式 -- 附錄
 
系統程式 - 附錄
系統程式 - 附錄系統程式 - 附錄
系統程式 - 附錄
 
系統程式 -- 附錄
系統程式 -- 附錄系統程式 -- 附錄
系統程式 -- 附錄
 
搜索初步
搜索初步搜索初步
搜索初步
 

More from tjpucompiler (7)

第6章 自底向上的lr分析法
第6章 自底向上的lr分析法第6章 自底向上的lr分析法
第6章 自底向上的lr分析法
 
第10章 代码优化
第10章 代码优化第10章 代码优化
第10章 代码优化
 
第9章 符号表
第9章 符号表第9章 符号表
第9章 符号表
 
第8章 运行时的存储管理
第8章 运行时的存储管理第8章 运行时的存储管理
第8章 运行时的存储管理
 
第2章 文法和语言
第2章 文法和语言第2章 文法和语言
第2章 文法和语言
 
第3章 词法分析
第3章 词法分析第3章 词法分析
第3章 词法分析
 
第1章 概论
第1章 概论第1章 概论
第1章 概论
 

Recently uploaded

1.1.3急救你必须懂四年级设计与工艺练习活页练习单元一四年级设计与工艺急救你必须懂
1.1.3急救你必须懂四年级设计与工艺练习活页练习单元一四年级设计与工艺急救你必须懂1.1.3急救你必须懂四年级设计与工艺练习活页练习单元一四年级设计与工艺急救你必须懂
1.1.3急救你必须懂四年级设计与工艺练习活页练习单元一四年级设计与工艺急救你必须懂
PUAXINYEEMoe
 
法国蒙彼利埃国家高等建筑学院毕业证制作/德语歌德B1证书/加拿大新斯科舍省农业学院文凭加急制作一个
法国蒙彼利埃国家高等建筑学院毕业证制作/德语歌德B1证书/加拿大新斯科舍省农业学院文凭加急制作一个法国蒙彼利埃国家高等建筑学院毕业证制作/德语歌德B1证书/加拿大新斯科舍省农业学院文凭加急制作一个
法国蒙彼利埃国家高等建筑学院毕业证制作/德语歌德B1证书/加拿大新斯科舍省农业学院文凭加急制作一个
michaelell902
 
10.2.1 马来西亚各州名称的由来六年级历史单元练习马来西亚各州名称的由来练习
10.2.1 马来西亚各州名称的由来六年级历史单元练习马来西亚各州名称的由来练习10.2.1 马来西亚各州名称的由来六年级历史单元练习马来西亚各州名称的由来练习
10.2.1 马来西亚各州名称的由来六年级历史单元练习马来西亚各州名称的由来练习
PUAXINYEEMoe
 

Recently uploaded (9)

taibif_資料標準概念介紹_20240509_20240509_20340509.pdf
taibif_資料標準概念介紹_20240509_20240509_20340509.pdftaibif_資料標準概念介紹_20240509_20240509_20340509.pdf
taibif_資料標準概念介紹_20240509_20240509_20340509.pdf
 
1.1.3急救你必须懂四年级设计与工艺练习活页练习单元一四年级设计与工艺急救你必须懂
1.1.3急救你必须懂四年级设计与工艺练习活页练习单元一四年级设计与工艺急救你必须懂1.1.3急救你必须懂四年级设计与工艺练习活页练习单元一四年级设计与工艺急救你必须懂
1.1.3急救你必须懂四年级设计与工艺练习活页练习单元一四年级设计与工艺急救你必须懂
 
法国蒙彼利埃国家高等建筑学院毕业证制作/德语歌德B1证书/加拿大新斯科舍省农业学院文凭加急制作一个
法国蒙彼利埃国家高等建筑学院毕业证制作/德语歌德B1证书/加拿大新斯科舍省农业学院文凭加急制作一个法国蒙彼利埃国家高等建筑学院毕业证制作/德语歌德B1证书/加拿大新斯科舍省农业学院文凭加急制作一个
法国蒙彼利埃国家高等建筑学院毕业证制作/德语歌德B1证书/加拿大新斯科舍省农业学院文凭加急制作一个
 
taibif_開放資料流程-清理資料01-通則_20240509_20240509.pdf
taibif_開放資料流程-清理資料01-通則_20240509_20240509.pdftaibif_開放資料流程-清理資料01-通則_20240509_20240509.pdf
taibif_開放資料流程-清理資料01-通則_20240509_20240509.pdf
 
Math Chapter3-教學PPT第03單元形體關係、體積與表面積Grade Six
Math Chapter3-教學PPT第03單元形體關係、體積與表面積Grade SixMath Chapter3-教學PPT第03單元形體關係、體積與表面積Grade Six
Math Chapter3-教學PPT第03單元形體關係、體積與表面積Grade Six
 
啟思中國語文 - 中二 單元一 - 孟嘗君列傳 - 記敍的方法和人稱1.pptx
啟思中國語文 - 中二 單元一 - 孟嘗君列傳 - 記敍的方法和人稱1.pptx啟思中國語文 - 中二 單元一 - 孟嘗君列傳 - 記敍的方法和人稱1.pptx
啟思中國語文 - 中二 單元一 - 孟嘗君列傳 - 記敍的方法和人稱1.pptx
 
1.🎉“黑客”如何修改成绩?🤔🎉 在这个信息爆炸的时代,我们经常会看到各种作弊手段。但是你知道吗?有一种作弊方式可能比你想象中更巧妙:它就是——黑客![单...
1.🎉“黑客”如何修改成绩?🤔🎉 在这个信息爆炸的时代,我们经常会看到各种作弊手段。但是你知道吗?有一种作弊方式可能比你想象中更巧妙:它就是——黑客![单...1.🎉“黑客”如何修改成绩?🤔🎉 在这个信息爆炸的时代,我们经常会看到各种作弊手段。但是你知道吗?有一种作弊方式可能比你想象中更巧妙:它就是——黑客![单...
1.🎉“黑客”如何修改成绩?🤔🎉 在这个信息爆炸的时代,我们经常会看到各种作弊手段。但是你知道吗?有一种作弊方式可能比你想象中更巧妙:它就是——黑客![单...
 
10.2.1 马来西亚各州名称的由来六年级历史单元练习马来西亚各州名称的由来练习
10.2.1 马来西亚各州名称的由来六年级历史单元练习马来西亚各州名称的由来练习10.2.1 马来西亚各州名称的由来六年级历史单元练习马来西亚各州名称的由来练习
10.2.1 马来西亚各州名称的由来六年级历史单元练习马来西亚各州名称的由来练习
 
1.🎉成绩单,你的成绩! 💡🔥每个人都有自己的成绩单,它记录着我们努力的成果。但有时候,看着这些数字,却发现它们好像在嘲笑我?别担心,让我来告诉你们怎么改...
1.🎉成绩单,你的成绩! 💡🔥每个人都有自己的成绩单,它记录着我们努力的成果。但有时候,看着这些数字,却发现它们好像在嘲笑我?别担心,让我来告诉你们怎么改...1.🎉成绩单,你的成绩! 💡🔥每个人都有自己的成绩单,它记录着我们努力的成果。但有时候,看着这些数字,却发现它们好像在嘲笑我?别担心,让我来告诉你们怎么改...
1.🎉成绩单,你的成绩! 💡🔥每个人都有自己的成绩单,它记录着我们努力的成果。但有时候,看着这些数字,却发现它们好像在嘲笑我?别担心,让我来告诉你们怎么改...
 

第6章 自底向上的lr分析法

  • 2. 在第 5 章的自底向上分析中的 关键问题是寻找可归约串。 简单优先分析方法、算符优 先分析方法,基本上都是从左到右 地向前看若干个输入符号,找出句 柄 ( 或其变型 — 最左素短语 ) 的尾, 然后回头 ( 从右到左 ) 查看已扫描过 的符号,找出句柄 ( 或其变型 — 最左 素短语 ) 的头。 这实际上已不是严格地从左 到右地查看源程序进行归约了。 2
  • 3. LR 分析法是严格的规范归约 LR 分析法是一种自底向上的语法 分析方法,它严格地从左到右地读入输 入符号串中的符号,且最多向前看确定 个数 (K 个 ) 的符号,就能无回溯地识别 给定的符号串。 3
  • 4. 它与算符优先分析法一样,也 通过当前输入符号和栈顶符号 ( 状态 ) 相比较,根据栈中的符号串和向前查 看的 k(k≥0) 个输入符号,就能唯一确 定分析器的动作是移进还是归约,以 及用哪个产生式进行归约。 4
  • 5. 本章主要内容 本章主要介绍 LR 分析的基本思 想和当 K≤1 是 LR 分析方法的基本构造 原理和方法。 组成:总控程序 + LR 分析表 + 分析 栈 5
  • 6. 分析表的构造方法: 规范的 LR 法 : LR(0) ,能力最弱,理论上最重要; LR(1) ,它功能最强,但代价也最大。 简单的 LR 法: 简称 SLR ,最容易实现,但功能最弱 。 向前看的 LR 法: 简称 LALR ,功能和代价处于前两者 6 之间。
  • 8. 在语法分析中,句柄是逐步形成 的。 据此,可以用 “ 状态” 的概念来 描述不同时刻所形成的那部分句柄。 把每个句柄的识别过程划分为 若干状态,在每个状态下从左到右识 别句柄的一个符合。 8
  • 9. 在规范归约过程中,一方面记住已 移进和归约出的整个符号串,即记住 “ 历 史” ,另一方面根据所用的产生式推测未 来可能碰到的输入符号,即对未来进行 “ 展望” 。 当一串貌似句柄的符号串呈现于 分析栈的顶端时,根据所记载的 “ 历史 ” 和 “ 展望 ” 以及 “ 现实” 三方面的材料,来 确定栈顶的符号串是否构成句柄。 9
  • 10. 但 “ 展望 ” 材料的汇集是很困难的 ,因为根据 “ 历史 ” 推测未来,即使是推 测未来一个符号也存在非常多的可能。 10
  • 11. LR 分析法的实现原理 为了记住分析的 “ 历史 ” 和汇集 “ 展望 ” 的信息, LR 分析法这样处理: 将归约过程的 “ 历史 ” 和 “ 展望 ” 材料综合抽象成某些状态,存放在一个 状态栈中,栈中每个状态都概括了从分 析开始直到某一归约阶段的全部 “ 历史 ” 和 “ 展望 ” 材料。 11
  • 12. LR 分析法的每一步工作都是由栈 顶状态和当前输入符号所唯一确定的 。 一个 LR 分析器实质上是一个 带先进后出栈的确定的有限自动机。 12
  • 14. LR 分析法的实现 LR 分析法也是一种表驱动的分析 方法,有一个分析栈、一个总控程序和 一个分析表。 特殊性 栈 = 状态栈 + 文法符号栈 分析表 = 动作表 (ACTION) + 状态转移表 (GOTO) 总控程序都一样 文法不同,分析表不同 LR 分析表是 LR 分析器的核心部分 14
  • 15. LR 分析器的逻辑结构 输入串 a … a … a # 1 i n 状态符号栈 Sn Xn 总控程序 输出 Sn-1 Xn-1 … … … … … … S1 X1 动作表 状态转移表 分析表 S0 action goto # 15
  • 16. ACTION 表 ACTION 表是一个状态及终结符的 二维矩阵; ACTION[si,a] 定义了在栈顶 状态 si 下,当前输入符为 a 时应采取的 动作,不外乎下列四种: 16
  • 17. ① 移进:若 ACTION[Si ,a]=sj(shift) , 将状态 sj 及当前输入符 a 移入栈顶。 ② 归约:若 ACTION[Si ,a] =rj(reduce) ,将栈顶内容按第 j 个产 生式归约。 ③ 接受:若 ACTION[Si ,a] =acc ,则 分析成功,正常停止。 ④ 报错:若 ACTION[Si ,a] =error , 语法出错,进行出错处理。 17
  • 18. GOTO 表 GOTO 表是一个状态及非终结符的 二维矩阵; GOTO[Si,X] 定义了当栈顶 状态遇到当前符号时应转向的状态。 18
  • 19. LR 分析法的分析过程 总控程序对任何 LR 分析法都 适用。它从输入串中读入当前输入符 a ,然后由栈顶状态 si 与当前输入字符 a 查看 ACTION 表,决定应采取何种动 作。 19
  • 20. 若为 sj ,则将状态 j 及当前输入符 a 移入栈 顶。 若为 rj ,则按第 j 个产生式 A→β 归约,若 β 的长度为 r ,则从状态栈和文法符号栈中 自栈顶向下去掉 r 个符号,并把 A 移入文 法符号栈内, sj=GOTO[si , A] 移进状态栈。 其中 si 为修改后的栈顶状态。 若为 acc ,则分析成功,结束。 其他转错误处理程序。 20
  • 21. 对输入串 abbcde# 的 LR 分析过 步骤 符号栈 输入符号 动作 状态栈 ACTION GOTO 程 串 1) # abbcde# 移进 0 S2 2) #a bbcde# 移进 02 S4 3) #ab bcde# 归约 (A→ b) 024 r2 3 4) #aA bcde# 移进 023 S6 5) #aAb cde# 归约 (A→ Ab) 0236 r3 3 6) #aA cde# 移进 023 S5 7) #aAc de# 移进 0235 S8 8) # aAcd e# 归约 (B→ d) 02358 r4 7 9) #aAcB e# 移进 02357 S9 10 ) #aAcBe # 归约 (S→ aAcBe) 023579 r1 1 11 ) #S # 接受 01 acc Si: 移进,将状态 i 和输入符进栈 ri: 归约,用第 i 个产生式归约,同时状态栈与符号栈退出相应个符号 21 ,并把 GOTO 表相应状态和第 i 个产生式的左部非终结符入栈。
  • 23. 首先讨论一种只概括 “ 历史 ” 资 料而不包含推测性 “ 展望 ” 材料的 “ 状态 ” 。 我们希望仅由这种简单状态就能识别呈 现在栈顶的句柄。 在讨论之前,需要定义一个重 要概念,即文法的规范句型的 “ 活前缀” 。 23
  • 24. 规范句型的活前缀  字 ( 符号串 ) 的前缀:字的前缀是指该字的 任意首部。  活前缀:是指规范句型的活前缀,它不包含 该句型的句柄右边的任何符号。  在活前缀的右边添上一些终结符号后,总可 以构成一个规范句型。 LR 识别过程中,栈里面的符号 ( 自栈底而 上 ) 就是一个活前缀,把输入串的剩余部 分配上后应成为一个规范句型。因此,只 要输入串已扫描过的部分能构成一个活前 缀,则意味着所扫描过的这一部分没有错 24 误。
  • 25. 活前缀和句柄的关系 文法 G[S]: 若 S => αAω =>αβω r 是 αβ 的前缀 ,则称 r 是 G 的一个活前缀。 活前缀已含有句柄的全部符号,表明产生 式 A→β 的 右部 β 已出现在栈顶。 活前缀只含句柄的一部分符号表明 A→β1β2 的右部子串 β1 已出现在栈顶,期 待从输入串中看到 β2 推出的符号。 活前缀不含有句柄的任何符号,此时期望 A→β 的右部所推出的符号串。 25
  • 26. 对规范句型活前缀的识别 对于一个文法 G ,可以构造一 DFA 去识别给定文法的所有规范句型的活前缀,进 而由此构造文法的 LR 分析表,用来指导对句 柄的识别 — 可根据分析栈的栈顶状态了判断是 否得到句柄,并进行归约。只要输入串的已扫 描的部分 ( 符号栈中的内容 ) 可构成一个活前 缀,则说明所扫描过的部分没有错误。 这样,对句柄的识别就变成了对规范 句型活前缀的识别。因此,活前缀反映了句柄 的识别状态。 26
  • 27. LR(0) 项目  定义:在文法的每一个产生式的右部适 当位置添加一个圆点 “ .” ,则一个 LR(0) 项目。  A → xyz 的 LR(0) 项目: 1. A → · xyz 2. A → x · yz 注意:一个产生式可对应的 3. A → xy · z 项目为它的右部符号长度加 1 ,对空产生式 A→ε 仅有 4. A → xyz · 项目 A→· 。 27
  • 28. 直观地,一个项目指明了在分 析过程的某一时刻,已经看到的一个产 生式的多少。 即在 LR(0) 项目 中, “ ·” 左部符号串表示已被识别出来 的句柄符号。 “ ·” 右部符号串表示待识 别的符部分。 可以由文法的所有 LR(0) 项目, 构造识别文法所有活前缀的 DFA 。 28
  • 29. 根据圆点所在的位置和圆点后 是终结符还是非终结符或为空把项目分 为以下几种: 移进 项目,形如 A →α • a β 待约 项目,形如 A →α • Bβ 归约 项目,形如 A →α • 接受 项目,形如 S’ →S • 29
  • 30. 构造识别活前缀的 NFA  文法 G[S] 的拓广: G’[S’]=G[S]+{S’ → S}  文法的每个项目为 NFA 的一个状态。  确定状态之间的转换关系  按规则可对文法 G’ 的所有项目对应的 状态构造出识别活前缀的 NFA 。 30
  • 31. NFA 中初终态的确定 G’[S’]=G[S]+{S’ → S}  由于 S’ 仅在第一个产生式的左部 出现,因此规定项目 1 为初态;  其余每个状态都为活前缀的识别态 ;  圆点在最后的项目为句柄识别态;  第一个产生式的句柄识别态为句子 的识别态。 31
  • 32. LR(0) 项目集规范族 提出 “ LR(0) 项目集规范族 ” 的原因 若按以上方法先构造 NFA ,然 后再确定化为 DFA ,这样工作量较大 ,不可取。 对于构成识别一个文法活前 缀的 DFA 项目集 ( 状态 ) 的全体称为 这个文法的 LR(0) 项目集规范族。 32
  • 33. LR(0) 项目集规范族的构造 可利用闭包函数 (CLOSURE) 求出 LR(0) 项目集规范族中的每个项目 集 (DFA 的状态 ) ,然后根据转换函数 (goto) 直接构造 DFA 。 33
  • 34. 构造步骤  对文法进行拓广;  构造拓广文法的 LR(0) 项目集规范族 (由初始项目出发,利用 CLOSURE 和 goto 函数);  将 LR(0) 项目集规范族中的每个项目 集作为 DFA 的状态,将 goto 函数作 为状态转换函数,构造出的 DFA 即为 所求。 34
  • 35. 项目集 I 的闭包 CLOSURE(I) 设 I 是文法 G’( 拓广文法 ) 的任一项目集 ,则定义和构造 CLOSURE(I) 的规则如下: ① 属于 I 的任何项目也属于 CLOSURE(I) ; ② 若 A → α .Bβ 属于 CLOSURE(I) ,那么,对 于任何关于 B 的产生式 B→ γ , 项目 B→ .γ 也 属于 CLOSURE(I) ; ③ 重复②直到 CLOSURE(I) 不再增大为止。此 CLOSURE(I) 即为所求的一个项目子集,将其 作为 DFA 的一个状态。 35
  • 36. 项目集闭包的例子  文法: 若 I={E ’ →.E} 0. E ’ → E CLOSURE(I) 为 : ’ →.E E 1. E → E+T 2. E → T E→.E+T 3. T → T*F E→.T 4. T → F T→.T*F T→.F 5. F →(E) F→.i 6. F → i F→.(E) 36
  • 37. goto(I,X) 函数  如果 LR(0) 项目集规范族中的每个项目集 看做 DFA 一个状态,则项目集规范族的 goto 函数把这些项目集连接成一个 DFA 。  定义:设 I 是一个项目集 ,X 是任一文法符 ,则 goto(I,X) 定义为: goto(I,X)=CLOSURE(J), 其中 J={ 任何具有 [A → αX.β] 的项目 | [A → α.Xβ] ∈ I } X I: A→α·Xβ J: A→αX·β 37
  • 38. 重要结论 构造拓广文法的项目集规范族 C 时,其中的项目集可看作一个 DFA 的状态,该 DFA 能够识别文法的所有 活前缀。 C 上的 goto 函数可以看作 DFA 的状态转换函数。 初始状态: CLOSURE({S ’ →.S}) 38
  • 39. LR(0) 文法 如果文法 G’ 的项目集规范族的 每个项目集中不存在下述冲突项目: ① 移进项目和归约项目并存, ② 多个归约项目并存, 则称文法 G’ 为 LR(0) 文法。 注意:只有对于 LR(0) 文法,才能构 造它的 LR(0) 分析表。 39
  • 40. LR(0) 分析表的构造 设文法 G’ 的项目集规范族 C={I0,I1,…,In}, 令其中每个项目集的下标作 为分析器的状态。 令包含项目 [S’ → .S] 的项目 集 Ik 的下标 k 为分析器的初态。 构造 LR(0) 分析表的步骤如 下: 40
  • 41. ① 若项目 A→α.aβ∈ Ii 且 移进 项目 goto(Ii,a)=Ij, 其中 a 为终结符,置 ACTION[i,a]=“ 把状态 j 和符号 a 移进栈 ” ,简记为 “ sj”; 归约 项目 ② 若项目 A→α.∈ Ii , 则对于任何输 入符 a 或结束符 # ,置 ACTION[i,a]=“ 用产生式 A→α 进 行归约 ” ,简记为 “ rj”( 假定 A→α 41 是文法 G’ 的第 j 条产生式 );
  • 42. 接受 ③ 若项目 S’→S.∈ Ii ,则置 项目 ACTION[i,#]=“ 接收 ” ,简记 为 ‘ acc’ ; ④ 若 goto(I,A)=Ij , A 为非终结符 ,则置 GOTO(i,A)=j ⑤ 分析表中凡不能用规则① - ④ 添入信息的元素均置上 ERROR 。 42
  • 43. 构造 LR(0) 分析表的步骤小结  文法拓广、产生式编号;  利用 CLOSURE 和 goto 函数,求出项 目集规范族 C;  构造识别活前缀的 DFA ;  由算法构造 LR(0) 分析表。 43
  • 44. § 6.4 SLR 分析表的构造 44
  • 45. 使用 SLR(1) 的原因 例: G: (0) S’→S (1) S→rD (2) D→D,i (3) D→i LR ( 0 )项目集规范族 I0: S’→ . S I3: S→r D . S→ . r D D→D . i I1: S’→S . I4: D→i . I2: S→r . D I5: D→D . i D→ . D i I6: D→Di . D→ . I 其中 I3 中含有移进 / 归约冲突。 文法不是 LR(0) 的,如何解决? 45
  • 46. SLR(1) 分析法 若 LR(0) 项目集规范族中有 项目集 IK 含移进 / 归约、归约 / 归约冲 突: IK :{X→α.bβ, A → γ . , B →δ. } 若满足 FOLLOW(A) ∩FOLLOW(B) =φ FOLLOW(A) ∩ { b } =φ FOLLOW(B) ∩ { b} =φ 46 冲突即可解决。这就是 SLR(1) 分析
  • 47. 当在状态 Ik 时面临某输入符号 a 时,则动作可由下规定决策。 若 a=b ,则 action [ k,b ] = 移进 。 若 a ∈FOLLOW (A) ,则 action [ k,a ] = 用 A → γ 归约。 若 a ∈FOLLOW (B) ,则 action [ k,a ] = 用 B→δ 归约。 能用 SLR(1) 技术解决冲突的文 法称为 SLR(1) 文法。 47 SLR(1) 文法是无二义的。
  • 48. SLR 分析表 移进 ① 若项目 A→α.aβ∈ Ii 且 项目 goto(Ii,a)=Ij, 其中 a 为终结符,置 ACTION[i,a]=“ 把状态 j 和符号 a 移进栈 ” ,简记为 “ sj”; ( 同 LR(0)) 归约 ② 若项目 A→α .属于 Ii, 那么, 项目 对任何输入符号 a, a∈ FOLLOW(A), 置 ACTION[i, a] 为 “ 用产生式 A→α 进行规约 ” ,简记为 “ rj”; 其中,假 定 A→α 为文法 G’ 的第 j 个产生式 48
  • 49. 接受 ③ 若项目 S’→S.∈ Ii ,则置 项目 ACTION[i,#]=“ 接收 ” ,简记 为 ‘ acc’ ; ( 同 LR(0)) ④ 若 goto(I,A)=Ij , A 为非终结符 ,则置 GOTO(i,A)=j ( 同 LR(0)) ⑤ 分析表中凡不能用规则① - ④ 添入信息的元素均置上 ERROR 。 ( 同 LR(0)) 49
  • 50. 按上述算法构造的含有 ACTION 和 GOTO 两部分的分析表, 如果每个入口不含多重定义,则称它 为文法 G 的一张 SLR 表。 具有 SLR 表的文法 G 称为一 个 SLR ( 1 )文法。 数字 1 的意思是,在分析过程 中顶多只要向前看一个符号。 50
  • 51. § 6.6 LR(1) 分析表的构造 51
  • 52. 用 SLR(1) 也不能解决的冲突 文法 G:(0)S’→S (1) S→aAd (2) S→bAc (3)S→aec (4) S→bed (5) A→e LR(0) 项目集规范族(识别 G 的活前缀的 DFA) : I0: S’→ . S I1: S’→S . I2: S→a . Ad S→ . aAd S→a . ec S→ . bAc A→ . e S→ . aec S→ . bed 52
  • 53. I3: S→b . Ac I4: I5: S→b . ed S→aA . d S→ae . c A→ . e A→e . I6: I7: I8: S→bA . c S→be . d S→aAd . A→e . 53
  • 54. 上例的 SLR 分析表 ACTION GOTO a c e b d # S A 0 S2 S3 1 1 acc 2 S5 4 3 S7 6 4 S8 5 r5 r5/S9 r5 r5 r5 r5 6 S10 7 r7 r7 r7 r7 r7/S11 r7 8 r1 r1 r1 r1 r1 r1 9 r3 r3 r3 r3 r3 r3 10 r2 r2 r2 r2 r2 r2 11 r4 r4 r4 r4 r4 r4 54
  • 55. 对问题的进一步分析 对于 SLR 分析法而言,若项目 [A→ α .] ∈ Ii ,则对于 a ∈ FOLLOW(A), 规定 ACTION[I,a]=“ 用 A→ α 归约 ” 。 有时,当状态 i 出现在栈顶时, 栈里的符号串组成的活前缀 βα 未必允许把 α 归约为 A ,因为可能根本就不存在一个规 范句型含有前缀 “ βA a” 。在这种情况下, 用 A→ α 进行归约未必有效。 55
  • 56. 不能用 SLR(1) 解决的原因 I5: S →ae . c A →e . R R R S’==>S==>aAd==>aed R R S’==>S==>aec I7: S →be . d A →e . R R R S’==>S==>bAc==>bec R R S’==>S==>bed 哪些输入符号能跟在句柄之后! 56
  • 57. 解决方案 让每个状态携带更多的信息, 以帮助 LR 分析器解决语法分析过程中 可能面临的移进 - 归约冲突,并尽可能 排除不合适的归约动作。 必要时需要对状态进行分裂, 以便 LR 的每个状态都恰好指明:当那 些输入符号紧跟 在句柄 α 之后时,才 允许利用产生式 A→ α 进行归约。 57
  • 58. 为此,需要重新定义项目,使 得每个项目包含两个部分 : 第一部分就是原来的项目自身 , 第二部分由一个终结符号 ( 或 #) 组成。 58
  • 59. LR(1) 项目 LR(0) 项 目 定义: [ A → α.β, a ] 在原来的 LR(0) 项目中加一 个向前搜索符 a ,这样得到的项目 称为 LR(1) 项目。 59
  • 60. 向前搜索符的意义 向前搜索符 a 只对归约项目 [ A → α. , a ] 有意义,它表示当它所 属的状态处于栈顶,且下一个输入符 为 a 时,才可以将栈顶符号 α 归约为 A 。 除此之外的其他符号出现, 即使 FOLLOW(A) 中的符号,也不归 约。 在其他项目中, a 只是起传递 60 作用。
  • 61. LR(1) 分析法 若 A →α .B β ∈ 项目集 I 则 B → . γ ( B → γ 是一产生式) ) I 把 FIRST(β) 中的符号作为用 B → γ 归约的搜索符 , 称为向前搜索符 ,作为归约时查看的符号集合用以代替 SLR(1) 分析中的 FOLLOW 集,把此搜 索符号的集合也放在相应项目的后面, 这种处理方法即为 LR(1) 分析法。 61
  • 62. 构造 LR(1) 项目集规范族 1. 构造 LR(1) 项目集的 closure(I) (1) I 的任何项目属 closure(I) ; (2) 若 [A →α .B β , a]∈ closure(I) , B→ γ 是一产生式,那么对于 FIRST(βa) 中 的每个终结符 b ,如果 [B→ . . ,b] 不 在 closure(I) 中,则把它加进去; (3) 重复 (1)(2) ,直至 closure(I) 不再增大 。 62
  • 63. 2. 构造 GO 转换函数 若 I 是一个项目集, X 是一个文法符号 GO(I, X)= closure(J) 其中 J={ 任何形如 [A→αX . β,a] 的项 目∣ [A→α.Xβ,a]∈ I} LR(I) 项目规范族 C 的构造算法类同 LR(0) 的,只是初始时: C={ closure( { S’→ . S , # } ) }; 63
  • 64. LR(1) 分析表的构造 设文法 G’ 的项目集规范族 C={I0,I1, …,In}, 令其中每个项目集的下标作为分析器 的状态,令包含项目 [S’ → .S,#] 的项目集 Ik 的下标 k 为分析器的初态。构造 LR(1) 分析 表的步骤如下: ① 若项目 [A→α.aβ,b]∈ Ik 且 goto(Ik,a)=Ij, 其 中 a 为终结符,置 ACTION[I,a]=“ 把状态 j 和符号 a 移进栈 ” ,简记为 “ sj”; ② 若项目 [A→α.,a]∈ Ik , 则置 ACTION[I,a]=“ 用产生式 A→α 进行归约 ” ,简记为 “ rj”( 假定 A→α 是文法 G’ 的第 j 条产生式 ); 64
  • 65. ③ 若项目 [S’→S.,#]∈ Ik, 则置 ACTION[I,#]=“ 接收 ” ,简记 为 ‘ acc’ ; ④ 若 goto(I,A)=Ij,A 为非终结符, 则置 GOTO(I,A)=j ⑤ 分析表中凡不能用规则① - ④ 添入信息的元素均置上 ERROR 。 65
  • 66. 构造 LR(1) 分析表的步骤小结  文法拓广;  写出基本 LR(1) 项目;  构造识别活前缀的 DFA ;  由算法构造 LR(1) 分析表 66
  • 67. LR(0) 、 LR(1) 、 SLR(1) 的比较  状态集的计算方法和 LR(0) 基本相同  分析表的构造方法和 LR(0) 基本相同 构造方法的不同点:  第 2 步处理中归约动作的选择: LR(0) 分析考虑所有终结符 SLR(1) 分析参考 FOLLOW 集 LR(1) 分析仅考虑 LR(1) 项目中的后继符 ( 用 FIRST 集近似考虑 ) 67
  • 69. LALR 分析技术  Look Ahead LR technique.  界于 LR(1) 分析器与 SLR(1) 分析器的之 间的折衷方案。  利用这种分析技术,构造出的 LALR 分 析表的状态数等于 SLR 分析表的状态数 ,比规范 LR 分析表少得多;分析能力 比 LR 分析器要差一些,但比 SLR 强大 ,能够处理一些 SLR 分析器难以处理的 情况。 69
  • 70. 同心项目集 对于两个 LR(1) 项集,如果除了 搜索符(向前看符号)外,其它完全相 同,那么这两个项集被称为同心项目集 。 同心项目集的心:即对应的 LR(0) 项目集。 70
  • 71. 同心项目集的合并  合并后的项目集的基本部分保持不变。 基本部分相同项的搜索符被合并。  原同心项目集之间的 goto 转换关系保持 不变。  同心项目集合并后,可能延迟报错的时 间,但绝不会放过错误,在输入下一个 符号之前肯定会发现错误。 71
  • 72. 合并可能引起的冲突  合并引起的冲突是指:本来的 LR(1) 项 目集没有冲突,而合并同心项目集后有 冲突。  引起 “ 归约 - 归约 ” 冲突。 文法 {S’→S S→aAd|bBd|aBe|bAe A→c B→c} 是 LR(1) 文法。 合并同心集后导致归约 - 归约冲突。 72
  • 73. LALR 的基本步骤  首先生成 LR(1) 项集规范族。  合并同心项目集。并且相应地建立合 并后的项目集之间的转换关系。合并 后的项目集的个数和 LR(0) 项目集规 范族中的项集个数相同。  根据这个项目集族,构造分析表。 73
  • 74. LALR 分析表构造算法 1. 构造 LR(1) 项目集规范族 C={I0,I1,I2, …In} 。 2. 合并 C 中的同心集,记 C’={J0,J1, …,Jn} 为合并后的新族。令包含项目 [S’ → .S,#] 的项目集 Ik 的下标 k 为 分析器的初态。 74
  • 75. 3. 根据 C’ 构造 ACTION 表: ① 若项目 [A→α.aβ,b]∈ Ji 且 goto(Ji,a)=Ij, 其中 a 为终结符,置 ACTION[J,a]=“ 把状态 j 和符号 a 移进 栈 ” ,简记为 “ sj”; ② 若项目 [A→α.,a]∈ Ji , 则置 ACTION[i,a]=“ 用产生式 A→α 进行归约 ” ,简记为 “ rj”( 假定 A→α 是文法 G’ 的 第 j 条产生式 ); ③ 若项目 [S’→S.,#]∈ Ji , 则置 ACTION[i,#]=“ 接收 ” ,简记为 ‘ acc’ ; 75
  • 76. 4. 构造 GOTO 表: 假定 J 是由 I1,I2,…,Im 合并后的新项目集 ,其中,每个 Ii 都是一个 LR(1) 项目集, 由于 I1,I2,…,Im 同心,因此 goto(I1,X), goto(I2,X) ,…,goto(Im,X) 也同心。令 K 是由 这些同心项目集合并后的项目集,那 么, goto(J,X)=K 。于是,若 toto(Ji,A)=Jj, 则置 GOTO[i,A]=j 。 5. 分析表中凡不能用 3 、 4 添入信息的空白格 均置 ERROR 。 76