3.4 自下而上分析

 

思维导图: 

自下而上分析:探索编译原理中的移进-归约分析

3.4 自下而上分析简介

在编译原理中,自下而上分析是一种重要的语法分析方法,它以一种从叶节点到根节点的逆序方式构建分析树,逐步将输入串归约为文法的起始符号。本节将重点介绍这种分析的一种典型风格——移进-归约分析,这是编译器中最常用的LR分析方法,将在后续的3.5节中进行深入讨论。

3.4.1 归约的过程

移进-归约分析的核心思想是将输入串逐步归约成文法的开始符号。在这个过程中,分析器会反复执行两种操作:移进和归约。移进操作是指将输入串的下一个符号读入并将其加入到当前分析的符号串中。归约操作则是分析过程的关键,它涉及到将当前符号串中的一部分替换为某个文法产生式的左部符号,这一部分恰好匹配该产生式的右部。

以文法规则为例,来看看归约是如何进行的:

  • 文法规则示例:

    S → aABe
    A → Abc | b
    B → d
    
  • 归约示例:

    考虑句子abbcde,按照下述步骤可以归约为S

    1. 扫描abbcde,寻找匹配某产生式右部的子串。这里,子串bd都可匹配,选择最左边的b。因为有A → b,所以用A替换它,得到aAbcde
    2. 现在,子串Abcbd分别匹配一个产生式的右部。选择Abc(因为A → Abc),替换后得到aAde
    3. 由于有B → d,用B替换d,得到aABe
    4. 最后,用S替换aABe

    这样,归约序列abbcde → aAbcde → aAde → aABe → S表示了从abbcdeS的归约过程。实际上,这些归约步骤描绘了abbcde的最右推导过程的逆过程。

句柄的概念

在移进-归约分析中,句柄是进行归约操作的关键概念。一个句柄可以被理解为在某一步归约中,能够被直接替换为某个产生式左部的那部分输入串。句柄的选择直接影响归约的正确性和分析过程的效率。

通过上述例子和讨论,我们可以看到自下而上分析,尤其是移进-归约分析,在编译器设计中的重要性。它为理解和实现编译器提供了一种基础且强大的框架。在接下来的讨论中,我们将进一步探索LR分析及其变种,深入理解它们在解决语法分析问题中的独特优势。

3.4.2 句柄的进一步探索

句柄的非形式定义

在编译原理中,理解句柄的概念是分析句型结构的关键。非形式地,一个句型的句柄是该句型中与某个产生式右部匹配的子串。重要的是,这个子串的归约代表了最右推导过程的逆过程中的一步。虽然在很多情况下,句型中与产生式A→β右部匹配的最左子串β即为句柄,但这并不是绝对的。有时,用这个产生式归约后得到的串可能无法进一步归约到开始符号,如例3.17所示。

句柄的形式定义

形式上,一个右句型(最右推导所得句型)γ的句柄是一个产生式的右部β,以及在γ中的位置,其中该位置上的串β可以被替换为产生式的左部A,从而得到最右推导的前一个右句型。这个定义说明,句柄不仅与产生式的右部匹配,而且它的选择对于实现最右推导具有决定性意义。

句柄和文法二义性

当一个文法是二义的,即一个句子可能有多个最右推导时,句柄可能不是唯一的。每个右句型在无二义的文法中才有唯一的句柄。这一点对于编译器的设计和实现具有重要意义,因为编译器需要确定性地解析程序代码。

示例3.18:句柄在不同推导中的应用

考虑以下文法及其最右推导的例子,展示了句柄的概念和重要性:

  • 文法规则:

    E → E + E
    E → (E)
    E → E * E
    E → id
    
  • 最右推导示例:

    E开始,可以推导出多种形式的表达式,例如E * E + id。在这个过程中,句柄是推导过程中能够匹配产生式右部的那部分表达式。如id在表达式id * id + id中就是一个句柄。

  • 文法的二义性:

    文法示例展示了二义性如何影响句柄的确定。在不同的推导中,句柄可能是不同的部分,这取决于操作符的优先级和结合规则。如E * E + id在一种推导中,E * E是句柄,而在另一种推导中,id可能是句柄。

这个例子说明了句柄概念在语法分析中的核心作用,特别是在处理具有二义性的文法时。通过准确识别句柄,编译器可以正确归约句型,进而有效地进行语法分析。

3.4.3 实现移进-归约分析的栈机制

在编译原理中,移进-归约分析是通过栈来实现的,这种方法解决了如何确定句型中待归约子串的问题,以及如何在多个可能的产生式中选择正确的产生式以进行归约。这一节将详细解释栈在移进-归约分析中的作用和操作流程。

栈的使用

使用栈来保存文法符号,而输入缓冲区则保存待分析的字符串。栈底用$标记,这同样用于标记输入串的右端。初始时,栈为空,待分析的字符串位于输入缓冲区。通过这种设置,分析器能够按顺序处理输入串的符号,并按需进行移进或归约操作。

移进-归约分析过程

移进-归约分析的过程中,分析器执行以下基本动作:

  1. 移进(Shift):把下一个输入符号移进栈顶。
  2. 归约(Reduce):当栈顶形成句柄时,确定句柄的范围,并选择合适的非终结符来替换句柄。
  3. 接受(Accept):当栈中只含开始符号且输入串为空时,分析成功。
  4. 报错(Error):发现语法错误时,调用错误恢复例程。

这种方法的一个关键优点是句柄最终总会出现在栈顶,而不是深埋在栈内部。这意味着分析器在归约之前只需将足够的符号移进栈顶,而无需深入栈内部查找句柄。

示例3.19:移进-归约分析器的动作

以文法规则(3.10)和输入串id * id + id为例,我们可以观察到分析器如何逐步分析输入串。考虑到输入可能有多种最右推导,分析器可能采取不同的动作序列。以下是可能的动作序列之一:

  1. 移进:将id移进栈。
  2. 归约:使用E → id归约。
  3. 移进:将*和下一个id移进栈。
  4. 归约:再次使用E → id归约。
  5. 移进:将+和最后一个id移进栈。
  6. 归约:使用E → id归约。
  7. 归约:使用E → E + E归约。
  8. 归约:使用E → E * E归约。
  9. 接受:分析成功。

通过这个示例,我们可以看到移进-归约分析器如何通过栈的操作来实现对输入串的分析,从而实现对程序代码的语法分析。这种方法的有效性依赖于对栈的合理使用,以及对移进和归约动作的正确选择。

 

3.4.4 移进-归约分析的冲突

在移进-归约分析中,存在两种主要的冲突:移进-归约冲突归约-归约冲突。这些冲突发生时,分析器难以决定应当执行移进操作还是归约操作,或者在多个可能的产生式中选择哪一个进行归约。这类冲突通常出现在非LR文法中,即那些不能用标准的LR分析方法分析的文法。

移进-归约冲突

移进-归约冲突发生在分析器根据栈中的内容和下一个输入符号,难以决定是应该将输入符号移进栈中,还是应该执行归约操作的情形。这种类型的冲突直接关联到文法的二义性。

  • 例子:考虑悬空else问题的文法,其中if-then-else语句的二义性导致了移进-归约冲突。分析器在遇到如下情形时无法决定if expr then stmt是否应当作为句柄进行归约,还是应该将接下来的else部分移进栈中。

归约-归约冲突

归约-归约冲突发生在分析器可以通过多个产生式对栈顶的符号串进行归约时。这意味着存在多个产生式的右部匹配栈顶的情况,而分析器需要选择其中的一个进行归约。

非LR文法

一些语法构造属于非LR文法,即它们不能被标准的LR(k)分析方法分析。对于任何k值,没有二义文法是LR(k)的,因为二义性本身就导致了分析过程中的不确定性。

解决方案

尽管存在这些冲突,移进-归约分析仍然可以用来分析某些二义文法,例如通过采用优先移进策略来解决悬空else问题。此外,可以通过修改文法或使用更智能的词法分析器来减轻或解决这些冲突。例如,通过改变产生式的定义或者在词法分析阶段使用符号表信息,可以帮助分析器在遇到潜在的归约-归约冲突时做出更准确的决策。

例3.21的情境

在处理过程调用和数组元素引用时,分析器可能无法仅凭栈中的信息决定使用哪个产生式进行归约,因为过程调用和数组引用在语法上可能非常相似。解决这一问题的一个方法是通过词法分析器返回更具体的标记(如procid而不是通用的id),这要求词法分析器在返回标记之前访问符号表。

总之,移进-归约分析的冲突突显了编译器设计中的一些挑战,尤其是在处理具有二义性或复杂语法结构的语言时。通过精心设计文法、优化分析器策略,以及在必要时利用额外的语言信息,可以有效地解决这些冲突。

 

  • 19
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

夏驰和徐策

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值