FIRST集合意義明確,求解直觀,不再贅述
FOLLOW集的不動點算法
先給出僞碼:
//init
foreach(nonterminal N)
FOLLOW(N) = {}
//開始符號S
FOLLOW(S) = { $ }
while(somw set is changing)
foreach (production p: N->β1 ... βn)
temp = FOLLOW(N)
foreach (βi from βn downto β1)
if(βi == a...)
temp = {a}
if(βi == M...)
FOLLOW(M) ∪= temp
if(M is not NULLABLE)
temp = FIRST(M)
else
temp ∪= FIRST(M)
爲什麼這樣做呢?
因爲如果有N->β1 …βn-2 βn-1βn
-
如果βn-1是一個終結符,那麼一定會有一個句型根據廣義推導,使得βn-1跟在βn-2後,所以應該有
βn-2 ∈ FOLLOW(βn-1)
-
如果βn-1是一個非終結符,並且βn-1推不出ε,那麼有, FIRST(βn-1) ∈ FOLLOW(βn-2)
-
如果βn-1是一個非終結符,並且βn-1可以經過若干推導產生ε,也即 ε∈FIRST(βn-1), FIRST(βn-1) ∈ FOLLOW(βn-2),並且βn-1可以推到產生ε,FIRST(βn) 也可以加入FOLLOW(βn-2)
注意上述推導都是逆序遍歷每一個產生式。
還是不懂?沒關係,我們來看一個例子,直觀的感受一下這個算法。
設有文法G[S]
求每個非終結符FOLLOW集
FIRST(S)={( , )}
FIRST(A)={( , )}
FIRST(A’)={ i,ε }
FIRST(B)={( , )}
FIRST(B’)={ +,ε }
FIRST©={( , )}
開始求解FOLLOW集:
第一次遍歷 | 第二次遍歷 | 第三次遍歷(沒有變化,算法終止) | |
---|---|---|---|
FOLLOW(S) | { $ } | { $ } | { $ } |
FOLLOW(A) | { $ , * } | { $ , * } | { $ , * } |
FOLLOW(A’) | { $ } | { $ , * } | { $ , * } |
FOLLOW(B) | { $ , i } | { $ , i , * } | { $ , i , * } |
FOLLOW(B’) | { $ , i } | { $ , i , * } | { $ , i , * } |
FOLLOW© | { $, *,+ , i } | { $, *,+ , i } | { $, *,+ , i } |