求解规则: (口诀:FIRST看左,FOLLOW看右)
(1) FIRST集
① 看产生式的左部,记作A。 找到产生式左部全为A的生产式。
② 下面求FIRST(A)
如果当前产生式为 A ---> ε,ε为空串。则直接把ε加入FIRST(A)中。
如果当前产生式为 A ---> εB,ε为空串,B为任意终结符、非终结符。则把ε和FIRST(B)加入FIRST(A)中。 (终结符的FIRST集就是它自身,即FIRST(a) = a)
如果当前产生式为 A ---> αB,α为终结符。则直接把α加入FIRST(A)中。
如果当前产生式为 A ---> BC,B为非终结符。则把FIRST(B)加入到FIRST(A)中。
递归的求解FIRST(B),直到得到终结符。
(2)FOLLOW集
① 求FOLLOW(B),看产生式的右部。 找到产生式右部中包含B的全部生产式。
② 下面求FOLLOW(B)
对于FOLLOW(S),直接把“#”加入FOLLOW(S)。 S为开始符号。
对于当前产生式 A ---> αB,把FOLLOW(A)加入到FOLLOW(B)中,即FOLLOW(B) = FOLLOW(A)
对于当前产生式 A ---> αBβ,β --->* ε(β为非终结符并且能经过N步推导到达ε),把FOLLOW(A)加入到FOLLOW(B)中。
对于当前产生式 A ---> αBβ,再细化情况。
a) 如果β为终结符,直接把β加入FOLLOW(B)中。
b) 如果β为非终结符,就把 FIRST(β)- ε 加入到FOLLOW(B)中。 (注意:FIRST(β)要去空)
(3)SELECT集(对产生式而言)
对于产生式 A ---> α
① ε ∈ FIRST(α)
则 SELECT(A ---> α)= [ FIRST(α) - ε ] ∪ FOLLOW(A)
② ε 不属于 FIRST(α)
则 SELECT(A ---> α)= FIRST(α)
(4)如何判断文法是不是LL(1)文法?
求左部相同的产生式的SELECT集的交集。
如果全为空集 Ф,则该文法是LL(1)文法。
如果不是空集,则该文法不是LL(1)文法。、
(注意:这两个产生式 A ---> α , A ---> β 中,α和β不能同时推为ε。)
例题1:给定文法G[s]
S ---> aH
H ---> aMd | d
M ---> Ab | ε
A ---> aM | e
判别G[s]是否为LL(1)文法。如果是,做出它的预测分析表。
步骤1:求FIRST集
FIRST(S) = { a }
FIRST(H) = { a,d }
FIRST(M) = { FIRST(A),ε } = { a,e,ε }
FIRST(A) = { a,e }
步骤2:求FOLLOW集
FOLLOW(S)= { # }
FOLLOW(H)= { FOLLOW(S) } = { # }
FOLLOW(M)= { d,FOLLOW(A) } = { d,b }
FOLLOW(A)= { b }
步骤3:求SELECT集
SELECT(S ---> aH)= { FIRST(aH) } = { a }
SELECT(H ---> aMd)= { FIRST(aMd) } = { a }
SELECT(H ---> d)= { FIRST(d) } = { d }
SELECT(M ---> Ab)= { FIRST(A) } = { a,e }
SELECT(M ---> ε)= { [ FIRST(ε) - ε ] ∪ FOLLOW(M) } = { d,b }
SELECT(A ---> aM)= { FIRST(aM) } = { a }
SELECT(A ---> e)= { FIRST(e) } = { e }
步骤4:判断文法是不是LL(1)文法
SELECT(H ---> aMd)∩ SELECT(H ---> d) = Ф
SELECT(M ---> Ab)∩ SELECT(M ---> ε)= Ф
SELECT(A ---> aM)∩ SELECT(A ---> e)= Ф
全部的交集都是空集,因此该文法是LL(1)文法!
步骤5:构造LL(1)预测分析表(根据SELECT集)
产生式中,全部的终结符作为列(SELECT值),全部的非终结符作为行(产生式左部)。
如果某一个产生式的左部为 S, SELECT(S)= { a }
就在 第 S 行, 第 a 列 填写 该产生式的右部 ---> aH
按照上述规则,画出LL(1)预测分析表如下:
a | d | b | ε | e | |
S | ---> aH | ||||
H | ---> aMd | ---> d | |||
M | ---> Ab | ---> ε | ---> ε | ---> Ab | |
A | ---> aM | ---> e |
至此,LL(1)预测分析表构造完成!
我们老师给出的LL(1)预测分析表构造算法不需要写出SELECT集合。
在这里也贴一下。