LR0, SLR1,LR1与LALR1分析的构造

前情提要

  • A 代 表 非 终 结 符 A代表非终结符 A

  • a 代 表 变 量 a代表变量 a

  • 项目集闭包

    • 内核项: 初始项 S ′ → . S S' \rightarrow .S S.S以及点不在最左端的所有项
    • 非内核项: 除了初始项 S ′ → . S S' \rightarrow .S S.S以外点在最左端的所有项

计算First集

  1. 算法开始 , 令 i = 1 i=1 i=1
  2. 判断X类型
    1. X是终结符, First(X)=X
    2. X是非终结符且 X → Y 1 Y 2 . . . Y n , n ≥ 1 X \rightarrow Y_1Y_2...Y_n, n \geq1 XY1Y2...Yn,n1
      1. if ε ∉ F i r s t ( Y i ) \varepsilon \notin First(Y_i) ε/First(Yi)
        • F i r s t ( X ) = F i r s t ( X ) ∪ F i r s t ( Y i ) First(X) = First(X) \cup First(Y_i) First(X)=First(X)First(Yi)
      2. if ε ∈ F i r s t ( Y i ) \varepsilon \in First(Y_i) εFirst(Yi)
        • F i r s t ( X ) = F i r s t ( X ) ∪ { F i r s t ( Y i ) − { ε } } First(X) = First(X) \cup \lbrace First(Y_i)- \lbrace \varepsilon \rbrace \rbrace First(X)=First(X){First(Yi){ε}}
        • i = i + 1 i=i+1 i=i+1
        • goto 算法开始
    3. X → ε X \rightarrow \varepsilon Xε, 将 ε \varepsilon ε加入到First(X)中
  3. 算法结束

计算Follow集

  1. #放入Follow(S)中, S为文法的开始符号, #为结束符
  2. 若存在 A → α B β A \rightarrow \alpha B \beta AαBβ, 那么 F o l l o w ( B ) = F i r s t ( β ) − { ε } Follow(B) = First(\beta) - \lbrace \varepsilon \rbrace Follow(B)=First(β){ε}
  3. A → α B A \rightarrow \alpha B AαB或者 ( A → α B β A \rightarrow \alpha B \beta AαBβ ε ∈ F i r s t ( β ) \varepsilon \in First(\beta) εFirst(β)) , 那么 F o l l o w ( B ) = F o l l o w ( B ) ∪ F o l l o w ( A ) Follow(B) = Follow(B) \cup Follow(A) Follow(B)=Follow(B)Follow(A)

  • 例子
    1. S → A B S \rightarrow AB SAB
    2. A → ε ∣ a A \rightarrow \varepsilon|a Aεa
    3. B → ε ∣ b B \rightarrow \varepsilon| b Bεb
    • First(S) = { a , b , ε } \lbrace a,b, \varepsilon \rbrace {a,b,ε}

LR(0)

  • LR0_CLOSURE(I)

    • LR0_CLOSURE(I)->Set_Items
      • J = I;
      • repeat
        • for A → α . B β ∈ J A\rightarrow \alpha . B \beta \in J Aα.BβJ
          • for B → . γ B \rightarrow .\gamma B.γ in G
            • if B → . γ B \rightarrow .\gamma B.γ not in J
              • B → . γ B \rightarrow .\gamma B.γ加入J中
      • until 在某一轮中没有新的项加入到J
  • LR0_Items(G’)

    • LR0_Items(G’)
      • C = {LR0_CLOSURE({[ S ′ → . S S' \rightarrow .S S.S]})}
      • repeat
        • for I in C
          • for 每个文法符号X
            • if G O T O ( I , X ) ≠ ∅ GOTO(I,X) \neq \emptyset GOTO(I,X)= 且 不在C中
              • GOTO(I,X)加入C中
      • until 在某一轮中没有新的项加入到C
  • LR(0)分析表的构建

    • 构造文法G’的项目集规范族 C = { I 0 , I 1 , I 2 . . . , I n } C = \lbrace I_0,I_1,I_2..., I_n\rbrace C={I0,I1,I2...,In}
      • if [ A → α . a β ] ∈ I i [A\rightarrow \alpha .a \beta] \in I_i [Aα.aβ]Ii并且 G O T O ( i , a ) = j GOTO(i,a)=j GOTO(i,a)=j, 则Action[i,a]=sj
      • if [ S → S ′ . ] ∈ I i [S\rightarrow S'.] \in I_i [SS.]Ii, 则Action[i,#]=Acc
      • if [ A → α . ] ∈ I i [A\rightarrow \alpha.] \in I_i [Aα.]Ii, 则for a ∈ T a \in T aT, 令Action[i,a]=r A → α . A\rightarrow \alpha. Aα.
      • if G O T O ( I i , A ) = I j GOTO(I_i,A)=I_j GOTO(Ii,A)=Ij, 令GOTO[i,A]=j

SLR(1)

  • SLR(1)分析表的构建
    • 构造文法G’的项目集规范族 C = { I 0 , I 1 , I 2 . . . , I n } C = \lbrace I_0,I_1,I_2..., I_n\rbrace C={I0,I1,I2...,In}
      • if [ A → α . a β ] ∈ I i [A\rightarrow \alpha .a \beta] \in I_i [Aα.aβ]Ii并且 G O T O ( i , a ) = j GOTO(i,a)=j GOTO(i,a)=j, 则Action[i,a]=sj
      • if [ S → S ′ . ] ∈ I i [S\rightarrow S'.] \in I_i [SS.]Ii, 则Action[i,#]=Acc
      • if [ A → α . ] ∈ I i [A\rightarrow \alpha.] \in I_i [Aα.]Ii, 则for a ∈ F o l l o w ( A ) a \in Follow(A) aFollow(A), 令Action[i,a]=r A → α . A\rightarrow \alpha. Aα.
      • if G O T O ( I i , A ) = I j GOTO(I_i,A)=I_j GOTO(Ii,A)=Ij, 令GOTO[i,A]=j
        其余与LR(0)相同

LR(1)

  • LR1_CLOSURE(I)

    • repeat
      • for ∀ [ A → α . B β , a ] ∈ I \forall[A \rightarrow \alpha.B \beta, a] \in I [Aα.Bβ,a]I
        • for ∀ [ B → γ ] ∈ G ′ \forall [B\rightarrow \gamma] \in G' [Bγ]G
          • for ∀ b ∈ F i r s t ( β a ) \forall b \in First(\beta a) bFirst(βa)
            • [ B → . γ , b ] [B \rightarrow .\gamma,b ] [B.γ,b]加入集合I中
    • untilI中不能加入更多的项
    • return I
  • LR1_GOTO(I,X)

    • J = {}
    • for ∀ [ A → α . X β , a ] ∈ J \forall [A \rightarrow \alpha.X \beta, a] \in J [Aα.Xβ,a]J
      • [ A → α X . β , a ] [A \rightarrow \alpha X.\beta, a] [AαX.β,a]加入集合J中
    • return LR1_CLOSURE(J)
  • items(G’)

    • C = LR1_CLOSURE( { [ S ′ → . S , ♯ ] [S'\rightarrow .S,\sharp] [S.S,]})
    • repeat
      • for ∀ I ∈ C \forall I \in C IC
        • for 每个文法符号X
          • if G O T O ( I , X ) ≠ ∅ GOTO(I,X) \neq \empty GOTO(I,X)=且不在C中
            • GOTO(I,X)加入C中
    • until 不再有新的项加入到C
  • LR(1)分析表的构建

    • 构造文法G’的LR(1)项目集规范族 C ′ = { I 0 , I 1 , I 2 . . . , I n } C' = \lbrace I_0,I_1,I_2..., I_n\rbrace C={I0,I1,I2...,In}
      • if [ A → α . a β , b ] ∈ I i [A\rightarrow \alpha .a \beta, b] \in I_i [Aα.aβ,b]Ii并且 G O T O ( i , a ) = j GOTO(i,a)=j GOTO(i,a)=j, 则Action[i,a]=sj
      • if [ S → S ′ . , ♯ ] ∈ I i [S\rightarrow S'., \sharp] \in I_i [SS.,]Ii, 则Action[i,#]=Acc
      • if [ A → α . , a ] ∈ I i [A\rightarrow \alpha., a] \in I_i [Aα.,a]Ii, 则令Action[i,a]=r A → α . A\rightarrow \alpha. Aα.
      • if G O T O ( I i , A ) = I j GOTO(I_i,A)=I_j GOTO(Ii,A)=Ij, 令GOTO[i,A]=j

LALR(1)

传播法

  • 确定向前看符号:look_ahead(K,X)

    • 输入: 项目集I的内核K, 文法符号X
    • 算法描述
      • for ∀ [ A → α . β ] ∈ K \forall [A \rightarrow \alpha.\beta] \in K [Aα.β]K
        • J = LR1_CLOSURE({[ A → α . β , ♯ A \rightarrow \alpha.\beta, \sharp Aα.β,]})
        • if [ B → γ . X δ , a ] ∈ J [B \rightarrow \gamma.X \delta, a ] \in J [Bγ.Xδ,a]J
          • [ B → γ X . δ , a ] ∈ G O T O ( I , X ) [B \rightarrow \gamma X. \delta, a ] \in GOTO(I,X) [BγX.δ,a]GOTO(I,X)中的a是自发生成
          • //build 自发生成表
        • if [ B → γ . X δ , ♯ ] ∈ J [B \rightarrow \gamma.X \delta, \sharp ] \in J [Bγ.Xδ,]J
          • 向前看符号从I中 A → α . β A \rightarrow \alpha.\beta Aα.β传播到GOTO(I,X)中的项 B → γ X . δ B \rightarrow \gamma X. \delta BγX.δ之上
          • //build 传播表
    • 输出: 自发生成表, 传播表
  • 计算LALR(1)项目集族内核

    • let C = G的LR(0)项目集族 , 并删除其中的非内核项
    • let table = {}; let broadcast = {}
    • for ∀ X ∈ V N ∪ V T \forall X \in V_N \cup V_T XVNVT
      • for ∀ K ∈ C \forall K \in C KC
        • let tmp_table, tmp_broadcast = look_ahead(K,X)
        • table.extend(tmp_table);
        • broadcast.extend(tmp_broadcast);
    • 传播
      • for ∀ ( i t e m i , i t e m j s ) ∈ b r o a d c a s t \forall (item_i, item_js ) \in broadcast (itemi,itemjs)broadcast
        • for ∀ i t e m j ∈ i t e m j s \forall item_j \in item_js itemjitemjs
          • i t e m i item_i itemi的展望符传播到 i t e m j item_j itemj中去
  • LALR(1)分析表的构建

    • 构造文法G’的LALR(1)项目集规范族 C ′ = { I 0 , I 1 , I 2 . . . , I n } C' = \lbrace I_0,I_1,I_2..., I_n\rbrace C={I0,I1,I2...,In}
      • if [ A → α . a β , b ] ∈ I i [A\rightarrow \alpha .a \beta, b] \in I_i [Aα.aβ,b]Ii并且 G O T O ( i , a ) = j GOTO(i,a)=j GOTO(i,a)=j, 则Action[i,a]=sj
      • if [ S → S ′ . , ♯ ] ∈ I i [S\rightarrow S'., \sharp] \in I_i [SS.,]Ii, 则Action[i,#]=Acc
      • if [ A → α . , a s ] ∈ I i [A\rightarrow \alpha., as] \in I_i [Aα.,as]Ii, 则for ∀ a ∈ a s \forall a \in as aas: then Action[i,a]=r A → α . A\rightarrow \alpha. Aα.
        • //as是展望符的集合
      • if G O T O ( I i , A ) = I j GOTO(I_i,A)=I_j GOTO(Ii,A)=Ij, 令GOTO[i,A]=j

参考

龙书

你可能感兴趣的:(rust)