回补如何与标记一起使用?

boa*_*oaz 2 language-agnostic compiler-construction bison intermediate-language

我在互联网上搜索过,无法找到关于回调如何工作的正确解释?

能否请您解释一下回补是如何工作的?它如何与标记一起使用

我知道它有两种主要类型的标记:

  1. 有下一个四边形
  2. 有下一个列表

我找到了这段代码,他们在这段代码中输入一个输入文件并使用RISKI语言创建一个文件.

在他们的第一次滚动中他们有:

PROGRAM : N FUNCTION M MAIN_FUNCTION
Run Code Online (Sandbox Code Playgroud)

你可以看到N和M是标记(它们是空卷).

ric*_*ici 8

一次性代码生成在为条件生成代码时存在一个小问题.一个典型的if陈述:

if CONDITION then ALTERNATIVE_1 else ALTERNATIVE_2
Run Code Online (Sandbox Code Playgroud)

需要编译成这样的东西:

  compute CONDITION
  JUMP_IF_TRUE label1
  JUMP_IF_FALSE label2

label1:
  code for ALTERNATIVE_1
  JUMP label3

label2:
  code for ALTERNATIVE_2
  JUMP label3

label3:
  next statement
Run Code Online (Sandbox Code Playgroud)

但是当CONDITION生成代码时,不知道在哪里label1和哪个label2,并且当生成ALTERNATIVE_1ALTERNATIVE_2生成代码时,不知道在哪里label3.

一种方法是使用符号名称作为标签,如上面的伪代码,并在知道它们时填写实际值.这需要在跳转语句中存储符号名称,这会使数据结构复杂化(特别是,您不能只使用二进制汇编程序代码).它还需要第二次传球,只是为了填补跳跃目标.

一种(可能)更简单的方法是只记住跳转语句的地址,并在知道目标地址时进行补丁.这称为"回调",因为您返回并修补生成的代码.

事实证明,在许多情况下,您最终会有多个分支到同一个标签.一个典型的案例是"短路"布尔,如C系列&&||运营商.例如,扩展原始示例:

if (CONDITION_1 and CONDITION_2) or CONDITION_3 then ALTERNATIVE_1 else ALTERNATIVE_2

  compute CONDITION_1
  JUMP_IF_TRUE label1
  JUMP_IF_FALSE label2

label1:
  compute CONDITION_2
  JUMP_IF_TRUE label3
  JUMP_IF_FALSE label2

label2:
  compute CONDITION_3
  JUMP_IF_TRUE label3
  JUMP_IF_FALSE label4

label3:
  code for ALTERNATIVE_1
  JUMP label5

label4:
  code for ALTERNATIVE_2
  JUMP label5

label5:
  next statement
Run Code Online (Sandbox Code Playgroud)

事实证明,对于简单语言,只需要记住两个不完整的跳转语句(通常称为"true"和"false").因为可能有多个跳转到同一目标,所以这些跳转实际上是不完整跳转语句的链接列表,其中目标地址用于指向列表中的下一个跳转.因此,backpatching遍历列表,修补正确的目标并使用原始目标查找需要修补的上一个语句.

你所谓的标记(它是yacc/bison所称的"中规则制作"的实例)并不与回调真正相关.它们可用于多种用途.在一次性代码生成中,通常需要在规则中间执行某些操作,而回调只是一个示例.

例如,在假设if语句中,有必要在CONDITION解析之前初始化backpatch列表,然后在THENand ELSE子句的开头处进行backpatch .(另一个backpatch将在整个if语句的解析结束时触发,但那个将在规则的finnal操作中.)

在规则中间执行操作的最简单方法是插入中间规则操作,这相当于使用操作插入空的"标记"生成,如您指向的示例bison文件中所示.