一、SELECT集的定义
给定文法的产生式 A →α,A∈VN, α∈V*
重要的一点,SELECT集是针对产生式而言的。
我们也可有认为SELECT集是FIRST集推广到了串上。
二、SELECT集的计算方式
1)若 α≠*> ε,则SELECT(A →α)= FIRST(α)
2)若 α=*> ε,则SELECT(A →α)= FIRST(α)∪FOLLOW(A)
SELECT集的伪代码实现
foreach(production p)//初始化
SELECT(p) = {}
calculte_SELECT(production p: N->β1...βn)//计算产生式p的SELECT集
foreach(βi from β1 to βn)
if(βi == a...)//如果βi的首字符是一个终结符
SELECT(p) U= { a }//注意:这里是SELECT(p)而不是SELECT(N)
return;
if(βi == M...)//如果βi的首字符是一个非终结符
SELECT(p) U= FIRST(M)//将M的FIRST集加入到SELECT(p)中
if(M is not NULLABLE)//同时,如果M不能推出空的话SELECT集计算结束,否则继续循环
return;
//如果对于该产生式最右边的符号仍能推出空的话
SELECT(p) U= FOLLOW(N)
三、SELECT集实例分析
我们给出一个文法G(E):
①E → TE’
②E’ → +TE’
③E’ →ε
④T → F T’
⑤T’ → *F T’
⑥T’ →ε
⑦F → (E)
⑧F → id
在这个文法中能推出ε的产生式的左部为:{ E’,T’ }
我们给出这个文法的FIRST集与FOLLOW集:
N | FIRST(N) |
E | {(,id } |
E’ | {+,ε } |
T | {(,id } |
T’ | {*,ε } |
F | {(,id } |
N | FOLLOW(N) |
E | { ),$ } |
E’ | { ),$ } |
T | { +,),$ } |
T’ | { +,),$ } |
F | { *,+,),$ } |
下面,我们来计算这个文法的SELECT集。
我们看第①条产生式:①E → TE’
根据1)规则:SELECT(①) U= FIRST(T)
同时,因为FIRST(T)中没有ε ,所以第一条产生式的SELECT计算就结束了。
p | SELECT(p) |
E → TE’ | { (,id } |
第②条产生式:E’ → +TE’
产生式的右部首符号为+,是一个终结符,根据1)规则我们可以得到:
p | SELECT(p) |
E’ → +TE’ | { + } |
第③条产生式:E’ →ε ,我们发现该产生式推出一个空,那么根据规则2),我们可以得到
p | SELECT(p) |
E’ →ε | { ε,),$ } |
第④条产生式:T → F T’
根据规则1),SELECT(T) U= FIRST(F),因为F不能推出ε,所以我们计算得到SELECT(T):
p | SELECT(p) |
T → F T’ | { (,id } |
第⑤条产生式:T’ → *F T’ ,与第②条产生式同理
p | SELECT(p) |
T’ → *F T’ | { * } |
第⑥条产生式:T’ →ε ,与第③条产生式同理
p | SELECT(p) |
T’ →ε | { ε,+,),$ } |
第⑦条产生式:F → (E),产生式右侧第一个符号是一个终结符,因此,根据规则1)我们可以得到:
p | SELECT(p) |
F → (E) | { ( } |
第⑧条产生式也同理:
p | SELECT(p) |
F → id | { id } |
∴该文法的SELECT集为:
id | p | SELECT(p) |
① | E → TE’ | { (,id } |
② | E’ → +TE’ | { + } |
③ | E’ →ε | { ε,),$ } |
④ | T → F T’ | { (,id } |
⑤ | T’ → *F T’ | { * } |
⑥ | T’ →ε | { ε,+,),$ } |
⑦ | F → (E) | { ( } |
⑧ | F → id | { id } |
四、构造预测分析表
现在,我们可以根据SELECT集来构造该文法的预测分析表。
也就是说,我们根据SELECT集合可以知道:一个非终结符号使用哪一个产生式可以得到一个输入符号。