一、FOLLOW集的定义
对于非终结符号A,FOLLOW(A)被定义为:可能在某些句型中紧跟在A右边的终结符号的集合(为什么说是可能?因为在一些推导出来的文法符号串中,该非终结符号A可能在最右边,比如:A—>+TA)。
如果存在S=>αAaβ(推导若干次)这样的推导,终结符号a就在FOLLOW(A)中,其中α和β是文法符号串。
如果A和a之间存在一些文法符号,这样的话这些符号会推导得到ε并消失。
另外,如果A是某些句型的最右符号,那么$也在FOLLOW(A)中。
二、FOLLOW集的计算方式
计算所有非终结符号A的FOLLOW(A)集合时,应不断应用下面的规则,知道再没有新的终结符号可以被加入到任意FOLLOW集合中为止。
1)将$放到FOLLOW(S)中,其中S是开始符号,而$是输入右端的结束标记
2)如果存在一个产生式A—>αBβ,那么FIRST(β)中除了ε之外的所有符号都在FOLLOW(B)中
3)如果存在一个产生式A—>αB,或存在产生式A—>αBβ且FIRST(β)包含ε,那么FOLLOW(A)中的所有符号都在FOLLOW(B)中(同时FOLLOW(B)中也有FOLLOW(A)的所有符号)。
三、FOLLOW集实例分析
我们给出一个文法G(E):
①E → TE’
②E’ → +TE’
③E’ →ε
④T → F T’
⑤T’ → *F T’
⑥T’ →ε
⑦F → (E)
⑧F → id
左侧非终结符号分别为:E、E’、T、T’、F
我们先给出他们的FIRST集:
N | FIRST(N) |
---|---|
E | {(,id } |
E’ | {+,ε } |
T | {(,id } |
T’ | {*,ε } |
F | {(,id } |
我们先来看E,我们发现E在第⑦条产生式中出现,
E的后跟符号为 ),并且E为开始符号,因此 :
N | FOLLOW(N) |
---|---|
E | {),$ } |
我们再来看E’,该非终结符号出现在①、②条产生式中,
我们先来看第①条:E → TE’
此时,根据第3)条规则,FOLLOW(E’) U= FOLLOW(E),即:FOLLOW(E’) = { ),$ }
我们再来看第②条产生式:E’ → +TE’ ,由于左侧文法符号也是E’,而根据第3)条规则,FOLLOW(E’) U= FOLLOW(E’),没有什么实际的意义。综上:
N | FOLLOW(N) |
---|---|
E’ | {),$ } |
接着是T,T出现在①、②的产生式右侧,而①、②两条产生式中T的后跟符号都是E’ ,因此,根据第2)条规则:FIRST(E’ )中除ε之外的所有符号都在FOLLOW(T)中。所以:
N | FOLLOW(N) |
---|---|
T | { + } |
但是根据第3)条规则,因为FIRST(E’)中包含ε,所以FOLLOW(T)中也有FOLLOW(E)的元素,综上:
N | FOLLOW(N) |
---|---|
T | { +,),$ } |
我们再来看T’,在右侧的产生式中T’出现在第④、⑤条产生式中。
对于第④条产生式,我们可以根据第3)条规则可知:FOLLOW(T’) U= FOLLOW(T),
对于第⑤条产生式,我们可以得到:FOLLOW(T’) U= FOLLOW(T’),但这并没有什么意义。
因此:
N | FOLLOW(N) |
---|---|
T’ | { +,),$ } |
最后,我们来看F。
我们观察第④、⑤条产生式:
对于第④条产生式,由第2)条规则可知:FOLLOW(F) U= FIRST(T’ ),
N | FOLLOW(N) |
---|---|
T’ | { * } |
同时,因为FIRST(T’ )中包含ε,所以根据第3)条规则可知:FOLLOW(F) U= FOLLOW(T)
N | FOLLOW(N) |
---|---|
T’ | { *,+,),$ } |
对于第⑤条产生式,与上面同理,没有什么意义。
综上:
N | FOLLOW(N) |
---|---|
T’ | { *,+,),$ } |
现在我们得到了所有的FOLLOW集:
N | FOLLOW(N) |
---|---|
E | { ),$ } |
E’ | { ),$ } |
T | { +,),$ } |
T’ | { +,),$ } |
F | { *,+,),$ } |