编译原理 First集 Follow集 select集 通俗易懂的讲解 + 实例

First集Follow集通俗易懂的讲解加实例

First

如A->aB | CD

这里面包含了组成First(A)的两种情况:
以终结符开头,当然要把这个终结符(a)放到A的First里
以非终结符开头,先把C的First放到A的First里

再看如果C的First中有空(∈)的话就把D的First放到A的First里(因为如果C的First为空,那么D的First就有可能紧挨着A,所以就要添进A的Fisrt),如果D也有空的话往后依次类推

小结:
1、对于终结符而言,FIRST集中的元素只有它本身
2、对于非终结符而言,如果开始符是终结符或者空符号串ε,则加入其FIRST集中;若开始符是非终结符,则要加入它的不含ε的FIRST集,并考虑其为ε时的情况。

技巧:First一般从下往上找。
如果要找A的First,我们要找A的定义式,即A在左边的式子,看着他的右边来找。

Follow

如S->(L) | aL | LC

找Follow的三种情况:
先在候选式(右边)中找到该非终结符,如L(注意例中只有一个定义,但找Follow要看到所有右边出现该非终结符的)

如果L的右边是终结符,    那么这个终结符加入L的Follow

如果L的右边是非终结符, 那么把这个非终结符的First除去空加到L的Follow中

如果L处在末尾,那么,'->'左边符号的Follow成为L的Follow

另外要注意的是:
    开始符号的Follow中要加上‘#’        

小结:
1、FOLLOW集对于非终结符而言,是非终结符的全部后跟符号的集合,如果后跟终结符则加入,如果后跟非终结符,则加入该非终结符的不含空符号串的FIRST集,特别地,文法的识别符的FOLLOW集需要额外的加入‘#’。

技巧:Follow一般从上往下找。
如果要找L的Follow,要从式子的右边找到L,然后来找L的Follow,这与First是不同的。

举个栗子:

文法:
S→ABc
A→a|ε
B→b|ε

First集合求法:

能由非终结符号推出的所有的开头符号或可能的ε,但要求这个开头符号是终结符号。

如此题A可以推导出a和ε,所以FIRST(A)={a,ε};同理 FIRST(B)={b,ε};S可以推导出aBc,还可以推导出bc,还可以推导出c,所以FIRST(S)={a,b,c}

Follow集合的求法:

紧跟随其后面的终结符号或#。但文法的识别符号包含#,在求的时候还要考虑到ε。

具体做法是把所有包含你要求的符号的产生式都找出来,再看哪个有用。 Follow(S)={#}
如求A的Follow集 产生式:S→ABc A→a|ε ,但只有S→ABc 有用。跟随在A后年的终结符号是FIRST(B)={b,ε},当FIRST(B)的元素为ε时,跟随在A后的符号就是c,所以 Follow(A)={b,c} 同理Follow(B)={c}

SELECT集

1、定义:

给定上下文无关文法的产生式A→α, A∈VN,α∈V*, 若α不能推导出ε,则SELECT(A→α)=FIRST(α)   
如果α能推导出ε则:SELECT(A→α)=(FIRST(α) –{ε})∪FOLLOW(A)
需要注意的是,SELECT集是针对产生式而言的。

2、LL(1)文法:

① 一个上下文无关文法是LL(1)文法的充分必要条件是:对每个非终结符A的两个不同产生式,A→α, A→β,满足SELECT(A→α)∩SELECT(A→β)=空集 其中α,β不同时能推导出ε。
② LL(1)文法的含义:
第一个L 从左到右扫描输入串
第二个L 生成的是最左推导
1 向右看一个输入符号便可决定选择哪个产生式。
③LL(1)文法的判别:当我们需选用自顶向下分析技术时,首先必须判别所给文法是否是LL(1)文法。因而我们对任给文法需计算FIRST、FOLLOW、SELECT集合,进而判别文法是否为LL(1)文法。

3.求解示例:

1、文法G [S]为:
  S→AB
  S→bC
  A→ε
  A→b
  B→ε
B→aD
C→AD
C→b
D→aS
D→c
求每个产生式的SELECT集,并判断文法G是否为LL(1)文法?
解:SELECT(S→AB)=(FIRST(AB)-{ε})∪FOLLOW(S)={b,a,#}   
SELECT(S→bC)=FIRST(bC)={b}   
SELECT(A→ε)=(FIRST(ε) -{ε})∪FOLLOW(A)={a,c,#}   
SELECT(A→b)=FIRST(b)={b}   
SELECT(B→ε)=(FIRST(ε) -{ε})∪FOLLOW(B)={#}   
SELECT(B→aD)=FIRST(aD)={a}   
SELECT(C→AD)=FIRST(AD)={a,b,c}   
SELECT(C→b)=FIRST(b)={b}   
SELECT(D→aS)=FIRST(aS)={a}   
SELECT(D→c)=FIRST(c)={c}

由以上计算结果可得相同左部产生式的SELECT交集为:   

SELECT(S→AB)∩SELECT(S→bC)={b,a,#}∩{b}={b}≠ф   
SELECT(A→ε)∩SELECT(A→b)={a,c,#}∩{b}=ф   
SELECT(B→ε)∩SELECT(B→aD)={#}∩{a}=ф   
SELECT(C→AD)∩SELECT(C→b)={b,a,c}∩{b}={b}≠ф   
SELECT(D→aS)∩SELECT(D→c)={a}∩{c}=ф   
由LL(1)文法定义知该文法不是LL(1)文法,因为具有相同左部其产生式的SELECT集的交集不为空。

小结:
1、Select集的作用是将first集和follow集进行合并,如果两个文法的左端都是A,若他们的select集交集为空,表明他们是两个无关的,不会产生不确定性的文法,反之,则表明文法不是LL(1)文法。

你可能感兴趣的:(编译原理)