1. 程式人生 > >LR(1) 分析例子

LR(1) 分析例子

6.4 LR(1) 分析 

  本節介紹比SLR(1)功能更強的LR(1)分析法。
  例如下列文法G′為:
  (0) S′→S
  (1) S→aAd
  (2) S→bAc
  (3) S→aec
  (4) S→bed 
  (5)A →e
  我們首先用S′→·S作為初態集的專案,然後用閉包函式和轉換函式構造識別文法G′的識別活字首的有限自動機DFA見P143如圖7.11所示,可以發現在專案集I5和I7中存在移進和歸約衝突。
  I5:S→ae·c    I7:S→be·d
  A→e·       A→e·
  而歸約專案左部非終結符的FOLLOW(A)={c,d}
  在I5中,FOLLOW(A)∩{c}={c,d}∩{c}≠∅     
  在I7中,FOLLOW(A) ∩{d}={c,d}∩{d}≠

     
  因此I5,I7中衝突不能用SLR(1)方法解決。只能考慮用下面將要介紹的LR(1)方法解決。  
  由於用SLR(1)方法解決動作衝突時,對於歸約專案A→α·,只要當前面臨輸入符為a∈FOLLOW(A)時,就確定採用產生式A→α進行歸約,但是如果棧中的符號串為βα,歸約後變為βA,再移進當前符a,則棧裡變為βAa,而實際上βAa未必為文法規範句型的活字首。 
    例如:在識別表示式文法的活字首DFA中,(見圖7.10)在專案集I2存在移進-歸約衝突,即{E→T· T→T·*F}若棧頂狀態為2,棧中符號為#T,當前輸入符為‘)’,而‘)’屬FOLLOW(E)中,這時按SLR(1)方法應用產生式E→T進行歸約,歸約後棧頂符號為#E,而再加當前符‘)’後,棧中為#E)不是表示式文法規範句型的活字首。 因此這個歸約是多餘的。因此可以看出SLR(1)方法雖然相對LR(0)有所改進,但仍然存在著多餘歸約,也說明SLR(1)方法向前檢視一個符號的方法仍不夠確切,LR(1)方法恰好是要解決SLR(1)方法在某些情況下存在的無效歸約問題。
    若[A→α·Bβ]∈專案集I,則[B→·γ](B→γ為一產生式)也包含在I中,不妨考慮,把FIRST(β)作為用產生式B→γ歸約的搜尋符,稱為向前搜尋符,作為歸約時檢視的符號集合,用以代替SLR(1)分析中的FOLLOW集,把此搜尋符號的集合也放在相應專案的後面,這種處理方法即為LR(1)方法。(SLR(1)和LR(1)的區別在於LR(1)多使用了一個預判資訊,即專案後面的符號如A →·e,c中的c,這個預判資訊是用first集而非follow集得出的

1. LR(1)專案集族的構造

  構造LR(1)專案集的閉包函式CLOSURE(I)按如下方式構造:
  a) I 的任何專案都屬於CLOSURE(I)
  b) 若有專案[A→α·Bβ,a ]屬於CLOSURE(I), B→γ 
            是文法中的產生式,β∈V*,b∈FIRST(βa), 則 
             [B→·γ,b]也屬於CLOSURE(I)中。
  c) 重複b)直到CLOSURE(I)不再增大為止。
  例:已知拓展文法為:
  (0) S′→S
  (1) S→aAd 
  (2) S→bAc
  (3) S→aec
  (4) S→bed 
  (5) A →e
  LR(1)專案集和轉換函式如下:


2.構造LR(1)分析表:


  如果一個文法的LR(1)分析表中不含多重入口時(或任何一個LR(1)專案集中無移進—歸約或歸約—歸約的衝突,則稱該文法為LR(1)文法.
  例:G(S):S → BB     B→aB      B →b

  I0:S'→.S   S →.BB    B →.aB      B →.b
  I1:S' →S.
  I2:S →B.B    B→.aB    B→.b
  I3:B→a.B     B→.aB     B→.b 
  I4:B→aB.  
  I5: B→b.
  I6: S→BB.

  例:G(S):S → BB     B→aB      B →b 
  拓展文法 : (0)S' → S   (1) S → BB   (2) B→aB     (3) B →b 

  對於該例題,只要仔細分析該文法的LR(1)每個專案集的專案,不難發現,即使不考察搜尋符,它的任何專案都沒有衝突,因此它實際上是一LR(0)文法,可以構造一個LR(0)專案集.可以得知它的LR(0)分析器只含7個狀態,而現在LR(1)分析器卻含有10個狀態,其中I3和I6,I4和I7,I8和I9分別為同心集。