最近学习到First集 Follow集 Select集感到比较困难,查询了多篇文章,做下此学习笔记
整合了下面多篇大佬文章,在此做学习笔记记录:
first集&follow集&select集.
[编译原理]FIRST集合FOLLOW集的介绍和求解.
编译原理 First集 Follow集 select集 通俗易懂的讲解 + 实例.
正文开始
一些符号和定义:
一般大写字母表示非终结符,小写字母表示终结符。
文法式一套有限的规则,可以创建无限符合此规则的句子。
First 集
定义:
FIRST(α)是α的所有可能推导的开头终结符或可能的ε。
注意区分上面的alpha和a,first(α)表示以α开始符号的集合,α所有可能推导的开头终结符或者式ε.
求解规则:
小结:
1、对于终结符而言,FIRST集中的元素只有它本身
2、对于非终结符而言,如果开始符是终结符或者空符号串ε,则加入其FIRST集中;若开始符是非终结符,则要加入它的不含ε的FIRST集,并考虑其为ε时的情况。
技巧:
First一般从下往上找。
如果要找A的First,我们要找A的定义式,即A在左边的式子,看着他的右边来找。
Follow集
定义:
FOLLOW(A)是所有该文法开始符推导的句型中出现在紧跟A之后的终结符或 “#”。
其中S表示文法的开始符号,非终结符A后面跟着的终结符或‘#’集合,且式紧挨着A的
如果文法的开始符号S,把#加入到follow(S)
如果A->αBβ是一个产生式,把first(β){ε}加入到follow(B)中.(first(β){ε}表示把first(β)中去掉ε)
如果A->αB是一个产生式,或A->αBβ是一个产生式且β->ε,则把follow(A)加入到follow(B)中。
**注意,**A->αBβ,α可以是终结符也可以为非终结符也可以为空,β可以为终结符或者非终结符,但是不能为空且B后面要有符号;
求解规则:
如S->(L) | aL | LC
找Follow的三种情况:
先在候选式(右边)中找到该非终结符,如L(注意例中只有一个定义,但找Follow要看到所有右边出现该非终结符的)
如果L的右边是终结符, 那么这个终结符加入L的Follow
如果L的右边是非终结符, 那么把这个非终结符的First除去空加到L的Follow中
如果L处在末尾,那么,’->'左边符号的Follow成为L的Follow
小结:
1、FOLLOW集对于非终结符而言,是非终结符的全部后跟符号的集合,如果后跟终结符则加入,如果后跟非终结符,则加入该非终结符的不含空符号串的FIRST集,特别地,文法的识别符的FOLLOW集需要额外的加入‘#’。
技巧
Follow一般从上往下找。
如果要找L的Follow,要从式子的右边找到L,然后来找L的Follow,这与First是不同的。
SELECT集
定义
给定上下文无关文法的产生式A→α, A∈VN,α∈V*
若α不能推导出ε则:SELECT(A→α)=FIRST(α)
如果α能推导出ε则:SELECT(A→α)=(FIRST(α) –{ε})∪FOLLOW(A)
需要注意的是,SELECT集是针对产生式而言的。
意义
给定输入的表达式字符串需要根据表达式的字符串中的字符用来寻找正确的产生式,即输入的表达式字串中的字符作为key,产生式作为value,那么这个select集就是构造的map
举例①
文法:
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}
举例②:写出下面文法中所有非终结符的FIRST集
E → TE’
E’ → +E|ε
T → FT’
T’ → T|ε
F → PF’
F’ → *F’|ε
P → (E)|a|b|^
规则:
FIRST(E’) = {+ , ε} 规则(1.1)(1.2)
FIRST(F’) = {* , ε} 规则(1.1)(1.2)
FIRST(P) = {( , a , b , ^} 规则(1.1)
FIRST(F) = FIRST(PF’) = FIRST(P)\{ε}= {( , a , b , ^} 规则(1.3) FIRST(P)不包含ε
FIRST(T) = FIRST(FT’) = FIRST(F)\{ε}= {( , a , b , ^} 规则(1.3) FIRST(F)不包含ε
FIRST(E) = FIRST(TE’) = FIRST(T)\{ε}= {( , a , b , ^} 规则(1.3) FIRST(T)不包含ε
FIRST(T’) = {FIRST(T)\{ε}} ∪ {ε} = {( , a , b , ^ ,ε} 规则(1.2)(1.3) FIRST(T)不包含ε
举例③:写出下面文法中求FIRST(S),FIRST(A),FIRST(B)
G: S → BA
A → BS|d
B → aA|bS|c
FIRST(A) = {FIRST(B)/{ε}}∪{d} = {a, b, c, d}
FIRST(S) = {FIRST(B)/{ε}} = {a, b, c}
FIRST(B)={a, b, c}
举例④:写出下面文法中所有非终结符的FIRST集
E → TE’
E’ → +E|ε
T → Fd
F → PF’
F’ → *F’|ε
P → (E)|a|b|ε
答案:
FIRST(E) = FIRST(TE’) = FIRST(T) = {( , a, b, *, d}
FIRST(E’) = {+, ε}
FIRST(T) = FIRST(Fd)
= {FIRST(F)\{ε}}∪{d}
= {(, a, b, *, d}
FIRST(F) = FIRST(PF’)
= {FIRST(P)\{ε}}∪{FIRST(F’)\{ε}}∪{ε}
= {(, a, b, *, ε}
FIRST(F’) = {*, ε}
FIRST(P) = {(, a, b, ε}
举例⑤:写出下面文法中所有非终结符的FOLLOW集
G: E → TE’
E’ → +TE’|ε
T → FT’
T’ → *FT’|ε
F → (E)|i
已知:
FIRST(E) = FIRST(T) = FIRST(F) = {(, i}
FIRST(E’) = {+, ε} FIRST(T’) = {*, ε}
规则:
1、由规则(2.1),对文法开始符E,置#于FOLLOW(E)中
# ∈ FOLLOW(E)
2、E在产生式F → (E)|i 的右部出现,由规则(2.2),结合步骤1
FOLLOW(E) = {#,)}
3、E’在产生式E → TE’和 E’ → +TE’|ε的右部出现,由规则(2.3)
FOLLOW(E’) = FOLLOW(E)∪FOLLOW(E’) = {#,)}
4、T在产生式 E → TE’和E’ → +TE’|ε 的右部出现,由规则(2.2),再由规则(2.3)
FOLLOW(T) = {FIRST(E’)/{ε}}∪FOLLOW(E)∪FOLLOW(E’) = {+,#,)}
5、T’在产生式T → FT’ 和T’ → *FT’|ε 的右部出现,由规则(2.3)
FOLLOW(T’) = FOLLOW(T)∪FOLLOW(T’) = {+,#,)}
6、F在产生式T → FT’ 和T’ → FT’|ε的右部出现,由规则(2.2),再由规则(2.3)
FOLLOW(F) = {FIRST(T’)/{ε}}∪FOLLOW(T)∪FOLLOW(T’) = {,+,#,)}
举例⑥:求SELECT集
G(E):E->TE'
E'->+TE' | ε
T->FT'
T'->*FT' | ε
F->(E) | i
对应的first集合:
first(E) = {i, (}
first(T) = {i, (}
first(E') = {+, ε}
first(T') = {*, ε}
first(F) = {(, i}
对应的follow 集合:
follow(E) = {#, )} // E作为开始符,且在F->(E) | i 产生式中,E后存在 ) 符号
follow(E') = {#, )} // 根据规则 A->αB,则E->TE'将follow(E)加入到follow(E')
follow(T) = {+, #, )} // 有E->TE',根据A->αBβ规则,有α为空,E'->ε,此时将follow(E)加入follow(T),根据E'->+TE' | ε将first(+)\{ε}加入follow(T)
follow(T') = {+, #, )} // T->FT'将follow(T)加入
follow(F) = {(*,+,#,)} // T->FT',根据A->αBβ,α为空,T'->ε,将follow(T)加入;T'->*FT' | ε,根据A->αBβ,将first(T') / {ε} 加入
上面已经计算过这个例子的first和follow集
答案:
select(E->TE') = {i, (} // T无法推出ε,所以取first(T)
select(E'->+TE') = {+} // 直接取first(+)
select(E'->ε) = {#, )} // 注意候选式要分开计算,因为是ε所以取follow(E')
select(T) = {(,i} // first(F)
select(T'->*FT') = {*} // first(*)
select(T'->ε) = {+, #, )} // follow(T')
select(F->(E)) = {(} // first(()
select(F->i) = {i} // first(i)