自頂向下語法分析LL(1)

自頂向下分析法就是從文法的開始符號出發,不斷建立直接推導,試圖構造一個最左推導序列,最終由它推導出與輸入符號串完全匹配(相同)的句子。
從語法樹的角度看,自頂向下分析法就是以開始符號爲根節點,試圖向下構造一棵語法樹,其端末結符號串與輸入符號串相同。
能使用自頂向下分析技術的文法正是LL(1)文法.

LL(1)文法

LL(1)的含義:第1個L表明自頂向下分析是從左向右掃描輸入串,第2個L表明分析過程中將用最左到推倒,1表明只需向右看一個符號便可決定如何推倒即選擇哪個產生式(規則)進行推導,類似也可以有LL(k)文法,也就是需要向前查看k個符號才能確定選用哪個產生式。

若文法G[S]爲
S->AB
S->bC
A->ε
A->b
B->ε
B->aD
C->AD
C->b
D->aS
D->c

判斷別步驟

1.求出能推出ε的非終結符

非終結符 S A B C D
初值 - - - - -
第一次掃描 - y y - n
第二次掃描 y y y n n

2.求first集,非終結符第一個的終結符集合

非終結符 中間集 最終集
S first(A)-{ε} U first(B) -{ε} U {b} U {ε} {ε, b,a}
A {ε, b} {ε, b}
B {ε, a} {ε, a}
C first(A)-{ε} U first(D) U {b} {a, b,c}
D {a,c} {a,c}

3.求follow集,非終結符跟着的第一個的終結符集合

(1) 對於文法的開始符號 S,置 # 到 FOLLOW(S) 中;
(2)若 A -> αBaβ 是一個產生式,a 爲終結符,則把 a加至 FOLLOW(B) 中;
(3)若 A -> αBβ 是一個產生式,則把 FIRST(β) - {ε} 加至 FOLLOW(B) 中;
(4)若 A -> αB 是一個產生式,或 A -> αBβ 是一個產生式,而 β =*> ε, 則把 FOLLOW(A) 加至FOLLOW(B) 中

非終結符 規則 中間集 最終集
S (1),(4 D->aS) {#} U follow(D) {#}
A (3,4 S->AB), (3 C->AD) first(B)-{ε} U follow(S) U first(D) {a,#,c}
B (4 S->AB) follow(S) {#}
C (4 S->bC) follow(S) {#}
D (4 B->aD),(4 C->AD) follow(B) U follow© {#}

4.求select集,每個式子對應的終結符

產生式 中間集 最終集
S->AB fisrt(AB) - {ε} U follow(S) {a,b,#}
S-bC first(bC) {b}
A->ε fisrt(ε) - {ε} U follow(A) {a,#,c}
A->b fisrt(b) {b}
B->ε fisrt(ε) - {ε} U follow(B) {#}
B->aD fisrt(aD) {a}
C->AD fisrt(AD) - {ε} {a,b,c}
C->b fisrt(b) {b}
D->aS fisrt(aS) {a}
D->c fisrt© {c}

LL(1)文法的判別,從上表格最終集中得出
select(S->AB) ∩ select(S->bC) = {b} 不爲空,當終結符爲S時,講入符號爲b時,不知道選用哪個式子
select(A->ε) ∩ select(A->b) = {}爲空
select(B->ε) ∩ select(B->aD)= {}爲空
select(C->AD) ∩ select(C->b)= {b}不爲空,同上
select(D->aS) ∩ select(D->c)= {}爲空

從非LL(1)文法到LL(1)文法的等價轉換

由LL(1)文法定義可知,若方法中有直接或間接左遞歸或者有左公共因子則肯定不是LL(1)文法,因而我們高潮消除文法中的左遞歸,撮左公共因子進行等價轉換。

問題1:左遞歸問題
若採用自頂向下的語法分析,應消除文法中存在的左遞歸。

因爲左遞歸的存在,有可能使推導不能結束,分析陷入循環狀態。 例如:
A → Aβ (A∈VN , β∈VT*) 直接左遞歸
A → Bβ B->Aα (A,B∈VN , α,β∈VT*) 間接左遞歸

左遞歸還比較好理解,例如:我需要匹配的字符串是 bsd 就需要從左端 b 開始是被,推導時,先用 A -> Aa 推導 AAa,此時不符合條件,但因爲還有非終結符,不能結束,而是繼續推導。此時就會陷入死循環。

  1. 消除直接左遞歸

P→Pα1 / Pα2 /…/ Pαn / β1 / β2 /…/βm
其中,αi(I=1,2,…,n)都不爲ε,而每個βj(j=1,2,…,m)都不以P開頭,將上述規則改寫爲如下形式即可消除P的直接左遞歸:
P→β1 P’ / β2 P’ /…/βm P’
P’→α1P’ / α2 P’ /…/ αn P’ /ε
例:
S->Sa
S->b
可以改寫爲
S->bS’
S’->aS’|ε

  1. 消除間接左遞歸

消除間接左遞歸的方法是,把間接左遞歸文法改寫爲直接左遞歸文法,然後用消除直接左遞歸的方法改寫文法。
消除左遞歸算法:
(1) 把文法G的所有非終結符按任一順序排列,例如,A1,A2,…,An。
(2) for (i=1;i<=n;i++){
     for (j=1;j<=i-1;j++){
      把形如Ai→Ajγ的產生式改寫成Ai→δ1γ /δ2γ /…/δkγ
      其中Aj→δ1 /δ2 /…/δk是關於的Aj全部規則;
      消除Ai規則中的直接左遞歸;
   }
(3) 化簡由(2)所得到的文法,即去掉多餘的規則。
例:
A->Ba
A->aB
B->Ac
B->d
首先,令非終結符的排序爲A,B。對於A,不存在直接左遞歸。把A代入到B中的相關規則中得
B->Bbc
B->d|aBc
B存在直接左遞歸。在消除了B的直接左遞歸後,得到整個文法爲:
B->(aBc|d)B’
B->bcB’|ε
最終得:
A->Ba
A->aB
B->(aBc|d)B’
B->bcB’|ε

問題2:左公共因子問題
若採用自頂向下的語法分析,應消除文法中存在的左公因子。

因爲左公因子的存在,使式子select存在不爲空集的情況如
A → αβ | αγ
select(A → αβ) ∩ select(A → αγ) 不爲空

提取公因式

A→αβ1 |αβ2|αβ3|…|αβn,提取左公因子後變爲
A->α(β1|β2|β3|…|βn),再引出非終結符A’
A->αA’
A’->β1|β2|β3|…|βn
例:
S->aSb
S->aS
S->ε
提取左公因式
S->aS(b|ε)
S->ε
進一步變換
S->aSA
A->b|ε
S->ε

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章