语法分析——自下而上分析

语法分析——自下而上分析

一、规约

        自下而上分析法是一种“移进-归约”法。这种方法的大意是,用一个寄存符号的先进后出栈,把输入符号一个一个地移进到栈里,当栈顶形成某个产生式的一个候选式时,即把栈顶的这一部分替换成(归约为)该产生式的左部符号。

       对于自下而上的分析法,边输入单词符号(移进符号栈),边归约。也就是在从左到右移进输入串的过程中,一旦发现栈顶呈现可归约串就立即进行归约。

二、规范规约

       在形式语言中,最右推导常被称为规范推导。由规范推导所得的句型称为规范句型。如果文法G是无二义的,那么,规范推导(最右推导)的逆过程必是规范归约(最左归约)。  

三、符号栈的使用与语法树的表示

       栈是语法分析的一种基本数据结构。在解释“移进-归约”的自下而上分析过程时我们就已经提到了符号栈。一个“移进-归约”分析器使用了这样的一个符号栈和一个输入缓冲区。今后我们将用一个不属于文法符号的特殊符号‘#’作为栈底符,即在分析开始时预先把它推进栈;同时,也用这个符号作为输入串的“结束符”,即无条件地将它置在输入串之后,以示输入串的结束。

        “移进” 指把输入串的一个符号移进栈。

       “归约”指发现栈顶呈可归约串,并用适当的相应符号去替换这个串(这两个问题都还没有解决)。

       “接受”指宣布最终分析成功,这个操作可看作是“归约”的一种特殊形式。

       “出错处理”指发现栈顶的内容与输入串相悖,分析工作无法正常进行,此时需调用出错处理程序进行诊察和校正,并对栈顶的内容和输入符号进行调整。

四、LR分析法

        规范归约(最左归约—最右推导的逆过程)的关键问题是寻找句柄。在一般的“移进-归约”过程中,当一串貌似句柄的符号串呈现于栈顶时,我们有什么方法可以确定它是否为相对于某一产生式的句柄呢?LR方法的基本思想是,在规范归约过程中,一方面记住已移进和归约出的整个符号串,即记住“历史”,另一方面根据所用的产生式推测未来可能碰到的输入符号,即对未来进行“展望”。当一串貌似句柄的符号串呈现于分析栈的顶端时,我们希望能够根据所记载的“历史”和“展望”以及“现实”的输入符号等三方面的材料,来确定栈顶的符号串是否构成相对某一产生式的句柄。

        LR分析法的这种基本思想是很符合哲理的。因而可以想象,这种分析法也必定是非常通用的。正因如此,实现起来也就非常困难。作为归约过程的“历史”材料的积累虽不困难(实际上,这些材料都保存在分析栈中),但是,“展望”材料的汇集却是一件很不容易的事情。这种困难不是理论上的,而是实际实现上的。因为,根据历史推测未来,即使是推测未来的一个符号,也常常存在着非常多的不同可能性。因此,当把“历史”和“展望”材料综合在一起时,复杂性就大大增加。如果简化对“展望”资料的要求,我们就可能获得实际可行的分析算法。

        后面所讨论的LR方法都是带有一定限制的。

       一个LR分析器实质上是一个带先进后出存储器(栈)的确定有限状态自动机。我们将把“历史”和“展望”材料综合地抽象成某些“状态”。分析栈(先进后出存储器)用来存放状态。栈里的每个状态概括了从分析开始直到某一归约阶段的全部“历史”和“展望”资料。任何时候,栈顶的状态都代表了整个的历史和已推测出的展望。因此,在任何时候都可从栈顶状态得知你所想了解的一切,而绝对没有必要从底而上翻阅整个栈。LR分析器的每一步工作都是由栈顶状态和现行输入符号所唯一决定的。为了有助于明确归约手续,我们把已归约出的文法符号串也同时放在栈里(显然它们是多余的,因为它们已被概括在“状态”里了)。于是,我们可以把栈的结构看成是:

        栈的每一项内容包括状态s和文法符号X两部分。(s0,#)为分析开始前预先放到栈里的初始状态和句子括号。栈顶状态为sm,符号串X1X2…Xm是至今已移进归约出的部分。

五、LR分析中的出错处理

在LR分析过程中,当我们处在这样一种状态下,即输入符号既不能移入栈顶,栈内元素又不能归约时,就意味着发现语法错误。发现错误后,便进入相应的出错处理子程序。处理的方法分为两类:第一类多半使用插入、删除或修改的办法。如在语句a[1,2:=3.14;中插入一个]。如果不可能使用这种办法,则采用第二类办法。第二类处理办法包括在检查到某一不合适的短语时,它不能与任一非终结符可能推导出的符号串相匹配。




猜你喜欢

转载自blog.csdn.net/qq_41613456/article/details/80368902