看了好多求FIRST集和FOLLOW集的方法,这里是自己总结的,也是认为最实用的办法
FIRST集
求谁的FIRST集,要找谁在左侧的产生式,拿书上的例子来说(编译原理,陈火旺,第三版),其中@为空的意思
E->TE'
E'->+TE'|@
T->FT'
T'->*FT'|@
F->(E)|i
然后要看产生式右侧,
1、若产生式右侧以终结符开头,就把这个终结符放入X的FIRST集中
比如:F->(E)|i
因为“(”和“i”都为终结符,所以FIRST(F)={(,i}。
同理FIRST(E’)={+,@},FIRST(T’)={*,@}。
2、若产生式右侧以其他非终结符开头(X->YZ),就把这个非终结符(Y)的FIRST集放入X的FIRST集中,如果Y的FIRST集中有空,就把它下一个非终结符(Z)的FIRST集放入X的FIRST集中,循环直到终结符或结束。
比如:E->TE’和T->FT’,先说第一个,
由于E->TE’,所以我们要把FIRST(T)放入FIRST(E)中,由于FIRST(T)不知道,所以先去求FIRST(T)。
由于T->FT’,所以我们要把FIRST(F)放入FIRST(T)中,所以FIRST(T)={(,i},所以FIRSTt(E)={(,i}。
FOLLOW集
求谁的FOLLOW集,要找谁在右侧的产生式,还是这个例子
E->TE'
E'->+TE'|@
T->FT'
T'->*FT'|@
F->(E)|i
1、若X为文法的开始符号,那么#属于FOLLOW(X)。
2、其实所有产生式都可以看做是E->yXz形式,其中X为所求非终结符,y、z可以是终结符,可以是非终结符,也可以是空。
3、把FIRST(z)的非空元素加入FOLLOW(X)中。
4、如果z->空或z为空,就把FOLLOW(E)加入到FOLLOW(X)中
5、重复上述步骤至FOLLOW集不在增大
6、FOLLOW集中没有@,遇到@请自动忽略
(1)比如先求FOLLOW(E),发现在产生式F->(E)|i中可求,且E为文法开始符号,所以FOLLOW(E)=FIRST())={),#}。
(2)求FOLLOW(E’),发现在产生式E->TE’ 和E’->+TE’|@中可求,由E->TE’可得FOLLOW(E’)包含FOLLOW(E),由E’->+TE’|@可得FOLLOW(E’)包含FOLLOW(E’),所以FOLLOW(E’)={),#}。
(3)求FOLLOW(T),由产生式E->TE’和E’->+TE’|@得,FOLLOW(T)包含FIRST(E’),由产生式E’->+TE’|@可知E’->@,所以FOLLOW(T)包含FOLLOW(E’),所以FOLLOW(T)={+,),#}。
(4)求FOLLOW(T’),由产生式T->FT’可得,FOLLOW(T’)包含FOLLOW(T),所以FOLLOW(T’)={+,),#}。
(5)求FOLLOW(F),由产生式T->FT’可得,FOLLOW(F)包含FIRST(T’),由产生式T’->*FT’|@可知T’->@,所以FOLLOW(F)包含FOLLOW(T’),所以FOLLOW(F)={+,),#,*
}。