How To Build a Yacc?(3)

在(2)中,我们阐述了一个简单高效的分析方法,最终产生一个文法的最左推导(即每次优先扩展左边的NONTERMINAL)

但是递归下降算法有些许局限性,比如:对于两个不同的NONTERMINAL,如果他们的FIRST集合有交集的话,就会产生歧义,很显然,当目前的符号分别属于两个不同的NONTERMINAL的FIRST集合时,就无法决定采用哪个产生式了。

我们来考虑另外一种分析方法,与递归下降相反,它最终产生一个文法的最右推导。我们称这种方法为LR分析。

LR分析基于一种有穷确定性自动机(DFA)原理,根据语法规则来创建一个DFA, 然后判断输入的符号流是否最后落入这个DFA的ACCEPT状态。

如何根据语法规则建立DFA?

DFA是一个状态集合,这些状态由某些确定的有向边连接;DFA由一个初始状态开始,接受一个符号,进入下一个状态。那么LR分析中的DFA状态是什么? 想象一个当前推导状态这个概念,即对于一个文法来说,当它识别了一些符号流以后,进入到一个什么样的状态。这个状态要么还剩下一些符号有待识别,要么已经 完成。

以前面的文法为例:
初始时候:
一个符号都没有识别,DFA需要识别整个文法的初始符号。我们标记为:
S = # function_decl  (I1)
将'#'定义为“当前识别位置”,S是一个虚拟符号,我们将这个表达式定义为一个项目(item) ,这个项目认为,没有识别一个符号,DFA需要识别的是整个function_decl代表的符号串。
由于我们每次只从符号流中取出一个符号,因此将DFA一步就将整个function_decl全部识别是不可能的,只能将function_decl展 开,看看function_decl下一个要识别的TERMINAL是什么,这就引出了闭包(closure)的概念: 一个状态的closure集合这样定义的,遍历这个状态中的所有item,如果#后面紧接的是一个NONTERMINAL, 那么将这个NONTERMINAL的所有产生式的初始化项目加入到这个集合中。

比如I1的closure集合S1为:
S := # function_decl                  (I1)
function_decl := #
function func_name ( argment_list );  (I2)

这就是初始状态(S1)

继续推导(S1)以后的状态,我们要求解后续状态,主要方法是看当前位置(#)后面紧接的符号,如果符号流中下一个符号与之相同,那么当前位置后移一位,DFA进入了下一个状态(S2), 而由状态(S1)到(S2)的边的输入符号,就是#后面的符号。

那么如果下一个符号是 function , 那么(S1)进入下一个状态(S2):
function_decl :=  function # func_name ( argment_list );  (I3)
对S2求closure:得出:
function_decl :=  function # func_name ( argment_list );  (I3)
func_name := # id                                                               (I4)


目前,DFA成为如下的状况:
S1  (function)  -->  S2     (意思是:状态S1当输入符号function后变迁到S2)

新的问题产生了:S1中还有一个I1 中#后面是NONTERMINAL function_decl,
每次只取一个符号,如何才能从
S := # function_decl  直接输入一个 function_decl而直接进入到 S :=  function_decl # ? (DFA的终止状态)

也就是说,当我们处于状态S1(
S := # function_decl)时,什么时候才能认为已经输入了 function_decl这个NONTERMINAL了呢。这涉及到另外一个概念:规约(reduction):
当DFA运行到一个状态(SX),SX中含有一个Item已经到达末尾,诸如:
function_decl :=  function  func_name ( argment_list ); #  那么我们认为DFA已经识别/输入了一个等同的NONTERMINALfunction_decl。

先不考虑reduction在什么时候进行,一会在讨论分析算法的时候再讨论它。

那么由S1,我们还能推导出另一个状态S3:
S :=  function_decl #                        (I5)
这是DFA的终止接受状态。

根据上面的规则,我们由S2可以一直往下推导DFA中所有的状态,一直到新的状态中每个ITEM都是终止状态(#在末尾)。

阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页