📜  编译器设计中的回补

📅  最后修改于: 2022-05-13 01:56:17.139000             🧑  作者: Mango

编译器设计中的回补

Backpatching 基本上是一个完成未指定信息的过程。此信息属于标签。它基本上在代码生成过程中使用适当的语义动作。它可以在 goto 语句中指示标签的地址,同时为给定的表达式生成 TAC。这里基本上使用了两遍,因为在一遍中分配这些标签语句的位置非常具有挑战性。它可以在第一轮中使这些地址无法识别,然后在第二轮中填充它们。 Backpatching 是在不完整的转换和信息中填补空白的过程。

需要Backpatching:

Backpatching 主要用于两个目的:

1. 布尔表达式:

布尔表达式是其结果可以为真或假的语句。以数学家 George Boole 命名的布尔表达式是一个计算结果为真或假的表达式。让我们看一些常见的语言示例:

  • 我最喜欢的颜色是蓝色的。 → 真的
  • 我害怕数学。 → 假
  • 2 大于 5。 → false

2. 控制语句流

在程序中执行语句的过程中,需要控制控制语句的流向。例如:

控制语句流

控制语句流

使用 backpatching 的一次性代码生成:

在单程中,回补可用于创建布尔表达式程序以及控制语句流。非终结符 B 的综合属性 truelist 和 falselist 用于处理布尔语句跳转代码中的标签。如果 B 为真,控制应该转到的标签应该添加到 B.truelist,它是跳转或条件跳转指令的列表。 B.falselist 是指令列表,当 B 为假时,这些指令最终获得分配控制的标签。为 B 生成程序时,存在到 true 和 false 的跳转以及标签字段留空。列表 B.truelist 和 B.falselist 分别包含这些早期跳转。

例如,一条语句 S 有一个综合属性 S.nextlist,它表示在 S 的代码之后立即跳转到指令的列表。它可以将指令生成到指令数组中,标签用作索引。我们利用三个函数来修改跳转列表:

  • Makelist (i):创建一个仅包含 i 的新列表,该列表是指令数组的索引,并且 makelist 还返回指向新生成列表的指针。
  • Merge(p1,p2):连接 p1 和 p2 指向的列表,并返回一个指向连接列表的指针。
  • Backpatch (p, i):插入 i 作为目标标签,用于 p 指向的记录上的每个指令。

布尔表达式的回补:

使用翻译技术,它可以在自底向上解析期间为布尔表达式创建代码。在语法中,非终结标记 M 创建一个语义动作,该动作在适当的时间获取要创建的下一条指令的索引。

例如, Backpatching 使用布尔表达式产生规则表:

第一步:生成生产表

回补生产台

回补生产台

第 2 步:我们必须使用回补找到给定表达式的 TAC(三地址代码):

A < B OR C < D AND P < Q
给定示例的三个地址代码

给定示例的三个地址代码

第 3 步:现在我们将为表达式制作解析树:

示例的解析树

示例的解析树

控制语句的流程:

控制语句是那些改变语句执行顺序的语句。 If、If-else、Switch-Case 和 while-do 语句就是示例。布尔表达式常用于计算机语言中

  • 改变控制流:布尔表达式是改变语句中控制流的条件表达式。这种布尔语句的值隐含在程序的位置中。例如,如果 (A) B,如果到达语句 B,则表达式 A 必须为真。
  • 计算逻辑值:在自下而上的解析过程中,它可以通过翻译机制为布尔语句生成代码。语法中的非终结标记 M 建立了一个语义动作,该动作在适当的时刻形成以下指令的索引。

Backpatching 的应用:

  • Backpatching 用于在一次传递中转换控制流语句。
  • Backpatching 用于在自底向上解析期间为布尔表达式生成四元组。
  • 它是在代码生成过程中填充标签的未指定信息的活动。
  • 它有助于解决已植入代码中的正向分支。