第四章 語法分析(下)——LR文法
文章目錄
概述
在LR(k)文法中,L指對輸入進行從左到右的掃描,R表示反向構造一個最右推導序列。k表示在做出語法分析決定時向前看k個輸入符號。
常用的LR(k)文法包括:
- SLR:簡單LR
- LR(1):規範LR
- LALR:向前看LR(Look ahead)
基本概念
移動-歸約語法分析技術
- 移入shift:將下一個輸入符號移到棧的頂端。
- 歸約reduce
- 接受accept:宣佈語法分析過程成功完成
- 報錯error
衝突:
非LR文法中會存在移入/歸約衝突或者歸約/歸約衝突。
(衝突一定發生在歸約時)
SLR
SLR表驅動分析過程:
- 構造增廣文法
- 狀態內部擴充套件和狀態之間的擴充套件
- 構建文法分析表
下面將根據分析過程依次講述其中的概念。
增廣文法
G的增廣文法G’是在G中加上新開始符號S’和產生式S’->S而得到的文法。引入這個新的開始產生式的目的是告訴語法分析器何時應該停止語法分析並宣稱接受輸入符號串。
狀態內部擴充套件
狀態內部的擴充套件就是寫出項集族的閉包(CLOSURE)
首先我們理解項的概念:
一個文法G的一個LR(0)項是G的一個產生式再加上一個位於它的體中某處的點。
比如,A->XYZ產生了四個項:
- A-> · XYZ
- A-> X · YZ
- A-> XY · Z
- A-> XYZ ·
產生式A->ε只生成一個項A->·
然後我們來了解一下如何構造項集的閉包
狀態之間的擴充套件
狀態之間的擴充套件就是移點,即GOTO函式
GOTO(I, X)被定義為I中所有形如[A->α · Xβ]的項所對應的項[A-αX·β]的集合的閉包。
比如對集合 I { [E->E·+T] },GOTO(I, +) = { [E->E+·T] }
構建分析表
LR語法分析表由state、ACTION和GOTO三部分組成
ACTION
構造SLR語法分析表
SLR分析例項
這是龍書上的習題。
我們按照步驟來:
第一步 構造增廣文法:
S’ -> S
S -> Aa
S -> bAc
S -> dc
S -> bda
A -> d
第二步 構造項集族閉包和狀態之間的擴充套件
第三步,構建語法分析表
可見在表中存在移入/歸約衝突,所以該文法不是SLR文法。
LR(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集得出的)
LR(1)項集的閉包
CLOSURE(I)按如下方式構造:
- I的任何專案都屬於CLOSURE(I)
- 若有專案[A→α•Bβ,a ]屬於CLOSURE(I),B→γ 是文法中的產生式,β∈V*,b∈FIRST(βa), 則[B→•γ,b]也屬於CLOSURE(I)中。
- 重複b)直到CLOSURE(I)不再增大為止。
構建LR(1)語法分析表
文法分析表由State、Action、GOTO組成
Si表示移入到狀態Ii,Ri表示按照第i個產生式進行歸約。
如果一個文法的LR(1)分析表中不含多重入口時(或任何一個LR(1)專案集中無移進/歸約或歸約/歸約的衝突,則稱該文法為LR(1)文法.
LR(1)分析例項
第一步 構建增廣文法
S’->S
S->Aa
S->bAc
S->Bc
S->bBa
A->d
B->d
第二步 構建項集閉包和和狀態轉換
第三步 構建語法分析表
表中不存在衝突,所以是LR(1)文法