1.为什么要引入FIRST集的概念?
- 因为有公共左因子的问题,公共左公因子是指在文法的产生式集合中,某个非终结符的多个候选式具有相同的前缀。
- 一般来说,公共左公因子的产生式为
A→αβ1│αβ2 - 如果有公共左因子的问题,那么只能采取试探的方法来分析每一个候选式,分析的过程很可能产生回溯,回溯分析法是一种不确定的方法。
- 若所有候选式都没有公共左因子就可以选择惟一匹配的候选式,不会产生(公共左公因子引起的)回溯。
- 为了消除回溯,对任何一个非终结符和当前的待匹配符号,期望
- 要么只有一个候选式可用
- 要么没有候选式可用
因此引入以下FIRST集合的概念:
- 对
α∈(VT⋃VN)∗ ,有FIRST(α)={a|α⟹∗a⋅⋅⋅,a∈VT}
特别地,若α⟹∗ε ,则ε∈FIRST(α)
因此对于每一文法符号
使用下列规则,直至每个FIRST集不再增大为止:
- 若
X∈VT ,则FIRST(X)={X} (意思是如果X 是终结符,则其FIRST 集合为其自身); -
若
X∈VN ,那么X 的产生式分以下三种情况:-
X→ε - 则
ε∈FIRST(X) -
X→a⋅⋅⋅ - 则
a∈FIRST(X) -
X→Y⋅⋅⋅ ,且Y∈VN 则
FIRST(Y)–{ε}⊆FIRST(X) -
特例:
X→Y1Y2⋅⋅⋅Yi−1Yi⋅⋅⋅Yk
且Y1,Y2,⋅⋅⋅Yi−1∈VN
Y1,Y2,⋅⋅⋅Yi−1⟹∗ε - 则
FIRST(Yj)–{ε}⊆FIRST(X)(1≤j≤i−1),FIRST(Yi)⊆FIRST(X)
- 则
-
特别地,当
Y1Y2⋅⋅⋅Yi−1Yi⋅⋅⋅Yk⟹∗ε - 则
ε∈FIRST(X)
- 则
-
结论:针对无空产生式的文法G,同一非终结符的任两个产生式的右部符号串的FIRST集无交集,即可进行确定的自顶向下分析。
2.为什么要引入FOLLOW集的概念?
考虑文法G[S]:
求得各终结符和符号串的FIRST集合如下:
若输入串
从以上推导过程中可以看到,在第2步到第3步的推导中,即
语法树如下所示:
很显然,我们从以上叙述中可以得出:
当某一非终结符的产生式中含有空产生式时,它的非空产生式右部的开始符号集两两不相交,并与在推导过程中紧跟该非终结符右部可能出现的终结符集也不相交,则仍可构造确定的自顶向下分析。因此,引入了一个文法符号的后跟符号集合。
引入以下FOLLOW集的概念:
- 对
A∈VN ,有FOLLOW(A)={a|S⟹∗⋅⋅⋅Aa⋅⋅⋅,a∈VT}
若S⟹∗⋅⋅⋅A ,则规定#∈FOLLOW(A)
这里用#作为输入串的结束符,也称为输入串括号。
因此对于每一文法符号
就是考察A在产生式右端的出现情况,哪些终结符号可以跟随在A后面?
使用下列规则,直至每个FOLLOW集不再增大为止:
- 首先,设S为文法的开始符号,把
{#} 加入FOLLOW(S) 中(这里#为句子括号) - 若
B→αAβ 是一个产生式,则FIRST(β)−{ε}⊆FOLLOW(A) - 如果
B→αA 或者B→αAβ 且β⟹∗ε ,则FOLLOW(B)⊆FOLLOW(A) - 解释: 因为在推导过程中可能出现如下的句型序列:
-
S⇒∗⋅⋅⋅α1Bβ1⋅⋅⋅⇒⋅⋅⋅α1αAββ1⋅⋅⋅⇒⋅⋅⋅α1αAβ1⋅⋅⋅
例题:
非终结符 | FIRST | FOLLOW |
---|---|---|
A | {a, b, c, d, g} | {f, #} |
B | {b, |
{a, c, d, g, f, #} |
C | {a, c, d} | {c, d, g} |
D | {d, |
{a, b, c, g, f, #} |
E | {c, g} | {a, c, d, g, f, #} |
对于FIRST集合,解释其中的FIRST(A)的求解。
-
A→BCc 属于上述产生式的特例情况,很显然B⇒∗ε,C⇏∗ε ,因此(FIRST(B)−{ε})⋃FIRST(C)⊆FIRST(A) -
A→gDB 属于上述产生式的第二种情况,因此g∈FIRST(A) - 最后得出:
FIRST(A)=(FIRST(B)−{ε})⋃FIRST(C)⋃{g} - 而
FIRST(B)={b,ε},FIRST(C)={a,c,d} - 故
FIRST(A)={a,b,c,d,g}
对于FOLLOW集合,有如下的计算情况:
3.为什么要引入SELECT集的概念?
由于从2中我们得出结论:
当某一非终结符的产生式中含有空产生式时,它的非空产生式右部的开始符号集两两不相交,并与在推导过程中紧跟该非终结符右部可能出现的终结符集也不相交,则仍可构造确定的自顶向下分析。
因此当文法中含有形如:
的产生式时,其中
也即是
SELECT集合定义如下:
一个产生式的选择符号集SELECT。给定上下文无关文法的产生式
A→α,A∈VN,α∈V∗ ,若α⇏∗ε ,则SELECT(A→α)=FIRST(α) 。如果
α⇒∗ε ,则SELECT(A→α)=(FIRST(α)−{ε})⋃FOLLOW(A) 。
因此一个上下文无关文法是LL(1)文法的充分必要条件是,对每个非终结符A的两个不同产生式,
其中
再次回到上述例题
非终结符 | FIRST | FOLLOW |
---|---|---|
A | {a, b, c, d, g} | {f, #} |
B | {b, |
{a, c, d, g, f, #} |
C | {a, c, d} | {c, d, g} |
D | {d, |
{a, b, c, g, f, #} |
E | {c, g} | {a, c, d, g, f, #} |
右部产生式 | FIRST |
---|---|
BCc | {a, b, c, d} |
gDB | { g } |
bCDE | { b } |
|
{ |
DaB | {a, d} |
ca | { c } |
dD | { d } |
gAf | { g } |
c | { c } |
因此根据以上所求得的FIRST集和FOLLOW集,可求得各产生式的SELECT集合如下:
由上可知,有相同左部产生式的SELECT集合的交集为空,所以文法是LL(1)文法。