一、FIRST集
定义:
("=*>" 符号意为“经过任意步”)
设G=(Vt,Vn,S,P),令G是一个不含左递归的文法, 对G的所有非终结符的每个候选a定义它的终结首符集First(a)为:First(a)={a|a=*>a,aa,aaa.....,a∈Vt}
特别的,若a=*>ε则规定ε∈First (a)
规则
- 如果 X 是终结符号,那么FIRST(X)={X}
- 如果 X 是非终结符号,且 X -> Y1Y2Y3…Yk 是产生式,如果a在FIRST(Yi)中,且 ε 在FIRST(Y1),FIRST(Y2),…,FIRST(Yi-1)中,那么a也在FIRST(X)中;
- 如果ε 在FIRST(Y1),FIRST(Y2),…,FIRST(Yk)中(全部都有),那么ε在FIRST(X)中;
- 如果X是非终结符号,且有X->ε,那么ε在FIRST(X)中
理解规则:
First(a)就是从a可能推导出的所有开头为终结符号和可能的ε所构成的集合。但是!如果产生式形如A→BC B→ε C→c,这时ε不在First(A)中; 假如上述产生式的 C→c|ε,这时由于B、C都能够推导出ε,所以相当于A→ε,所以这时的 ε在First(A)中!!!
eg:
有语句A->a|B|c
B->b|ε
那么First(A)为{a,b,c}
First(B)为{b,ε}
first集还是很好理解的, 就是非终结符推导出的首个终结符的所有可能的一个集合
二、Follow集
定义:
我们设S是不含左递归文法G的开始符号,对于G的任何非终结符A,我们定义
Follow(A)={a∣S⇒...Aa...,a∈Vt}
follow集求解规则:
- (1)对于文法的开始符号S,置#于Follow(s)中;
- (2)若A->aBb 是一个产生式,则把First(b)-{ϵ }加入到Follow(B)中
- (3)A->aB是一个产生式,或A->aBb是一个产生式且b=>ϵ ,则把Follow(A)加入到Follow(B)中
对于三条规则的解释:
(以定义中的产生式A->aBb举例,此时的a,b都是终结符与非终结符的集合,而不只是个终结符!!)
- 对于首先要求解的文法开始符号(如:S)的follow集我们应该将#加入到它的Follow集中
- 如果某条产生式在右边存在我们要求解follow的非终结符(如:A->aBb 中的 B ),而且非终结符后面存在终结符或者非终结符的集合(如:A->aBb 中的 b ),那么我们就将跟在该非终结符后面的符号(如:此时的 b )的First集(如果含有ϵ)去掉ϵ,再将其加入到要求解的Follow(如:A->aBb 中的 B )集合中。
- 如果某条产生式右边存在我们要求解follow的非终结符而且非终结符后面不存在终结符或者非终结符的集合(如 A->aB ); 又或者存在终结符或者非终结符的集合(如:A->aBb 中的 b )但是该集合可以推出ϵ( b=>ϵ )。那么则将该条产生式左边的非终结符的Follow集加入到要求解的Follow集中。
eg:
A->aBC|ϵ ,B->b|ϵ ,C->Ac|ϵ 此时的a,b,c为终结符,A,B,C为非终结符
这时的Follow(A)={#,c} ,
Follow(B)=Follow(A)+First(C)-{ϵ},
Follow(C)=Folllow(A)
小结
经过上面的学习此时你应该已经明白First和Follow的求解方法,如果还有不明白的可以在下方留言我会回复,也可以去找题目进行练习,在练习中查漏补缺、加深理解。如果发现我的错误还请指出,多谢。谢谢大家观看。