一、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集合可以知道:一个非终结符号使用哪一个产生式可以得到一个输入符号。

presto 怎样将集合中的数据拆分_presto 怎样将集合中的数据拆分