FIRST集

可以理解为当前非终结符可以出现的开始符号(终结符)的集

求解方法:

步骤:
1.若X->a..,则将终结符a加入FIRST(X)中;
2.若X->e ,则将终结符e加入FIRST(X)中(e表示空集);
3.若 X->BCD…E,则将First(B)所有元素(除了空集)加入 First(X),然后检测First(B),若First(B)中不存在空集, 即e,则停止,若存在则向B的后面查看,将First(C)中所有元素(除了空集)加入First(X),然后再检测First(C)中是否有e…直 到最后,若E之前的所有非终结符的First集中都含有e,则检测到E时,将First(E)也加入First(X),若First(E)中含有e,则将 e加入First(X)。
  • 前两条都挺容易理解的,第三条解释一下:一段文法,如果前面的非终结符号不能推出空集,那么后面的非终结符号所产生的终结符号就永远不可能成为文法的首符,于是就需要特殊考虑空集的情况。

举例:

例如文法:

  • 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集,我们可以理解为当前候选式(右式)的非终结符后出现的总结符号集。

求解方法:

步骤:
1.对文法开始符号S,置#于FOLLOW(S)中;
2.对于产生式:A->aBC,将除去空集e的First(C)加入Follow(B)中;
3.对于产生式:A->aB或者A->aBC,(其中C可以推导出空串,C=>*e),则将Follow(A)加入Follow(B)中。
  • Follow(B)是B推出的串末端后的字符集合,在A->aBC的情形下,B推出串末端后的字符集,也就是C推出串首部字符的集合,即First(C)中除去e的集合。
    A->aB ,那么A推出字串的末端后字符集合,与B推出字串的末端后字符集合,是等价的就可以把Follow(A)赋值给Follow(B)。

举例:

例如文法:

  • S→ABc
  • A→a|ε
  • B→b|ε

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

例如:A->aB | CD
这里面包含了组成First(A)的两种情况:
1.以终结符开头, 当然要把这个终结符放到A的First里
2.以非终结符开头, 先把C的First放到A的First里,再看如果C的First中有空的话就把D的First放到A的First里,如果D也有空的话往后依次类推
技巧:First一般从下往上找。如果要找A的First,我们要找A的定义式,即A在左边的式子,看着他的右边来找。

Follow

如S->(L) | aL | LC
找Follow的三种情况:先在候选式(右边)中找到该非终结符,如L(注意例中只有一个定义,但找Follow要看到所有右边出现该非终结符的)
1.如果L的右边是终结符, 那么这个终结符加入L的Follow
3.如果L的右边是非终结符, 那么把这个非终结符的First除去空加到L的Follow中
3.如果L处在末尾, 那么,'->'左边符号的Follow成为L的Follow
4.另外要注意的是:开始符号的Follow中要加上‘#’
技巧:Follow一般从上往下找。如果要找L的Follow,要从式子的右边找到L,然后来找L的Follow,这与First是不同的。

本文所用参考资料1
本文所用参考资料2

在此感谢以上两位前辈。

Q.E.D.