[编译原理]求First Set,Follow Set最正确、最简单的方法
时间:2010-10-22 来源:Latifrons
网上看了国内外N多个版本,都或多或少的有错误或者是省略,步骤有的也非常复杂。
我研究了很久,结合多个版本,得出了求LL(1)文法的First Set,Follow Set最正确最简单的方法
首先约定几点:
大写字母为非终结符
小写字母为终结符(即最终的字符)
如果一个位置上既可以放大写字母也可以放小写字母,表示为A1,A2....
一个非终结符为Nullable代表它能够推导出空(暂时用#表示)
First Set:较容易,网上的版本也基本都正确。
1,终结符的First Set是自己,如First(a)={a}
2,对于每个产生式,形如X->A1A2A3A4(注意A1,A2,A3,A4可以是非终结符,也可以是终结符)
2.1,将First(A1)加入到First(X),如果A1是Nullable的,继续,否则停止。
2.2,将First(A2)加入到First(X),如果A2是Nullable的,继续,否则停止。
以此类推,如果到了最后一个符号(例子中的A4)仍为Nullable,则将空字符#加入First(X),此时X已经成为Nullable
循环执行每一个产生式(对于每个产生式可能需要执行N多次),直到First集不再发生变化。
Follow Set:网上的版本五花八门,算出的结果各不相同,很多CSDN上用户上传的程序也都是错误。
1,Follow Set仅针对于非终结符,但是可以通过以下方法类似地推导出终结符的Follow Set,不过推出来也没用
2,首先将$加入到起始非终结符。
3,对于每个非终结符X,观察产生式右侧的表达式中X的右侧所有字符串s(例如E->TXaB,右侧字符串为aB,如果产生式右侧无X则忽略),s可以为空
3.1,如果s为空或者s是Nullable的(不仅仅是s的开头是Nullable,必须s的全部是Nullable),则将产生式左侧的非终结符E的Follow Set加入到X的Follow Set (Follow(E)=>Follow(X))
3.2,如果s不为空,则将First(s)加入到Follow(X)
4,循环执行每一个产生式(对于每个产生式可能需要执行N多次),直到Follow集不发生变化。
grammar
E -> T X X -> + E | #
T -> ( E ) | int Y Y -> * T | #
Follow sets
Follow( E ) = {), $}
Follow( X ) = {$, ) }
Follow( T ) = {+, ) , $}
Follow( Y ) = {+, ) , $}