重写修改的goto语义的算法

str*_*cer 5 algorithm programming-languages goto

我用一种旧的自我构思的脚本语言得到了大量遗留代码,我们将其编译/转换为javascript.

该语言有条件跳转,跳转到标签.与常见的goto语句的区别在于,不能进行向后跳转.该语言中没有嵌套的if语句和循环.

由于goto中不存在goto,我正在寻找一种转换goto mylabelmylabel:进入语义等效结构的算法.

我想使用ifs但发现它不是微不足道的,因为goto标签的任意嵌套.

例:

if cond1 goto a
do something1
if cond2 goto b
do something2
a:
do something3
if cond3 goto c
do something4
c:
do something5
b:
Run Code Online (Sandbox Code Playgroud)

可以改写为:

lbl_b=false;
lbl_c=false;

lbl_a = cond1;
if (!cond1) {
  do something1;
  lbl_b = cond2;
  if (!lbl_b) {
    do something2;
  }
}
if (!lbl_b) {
  do something3;
  lbl_c = cond3;
  if (!lbl_c) {
    do something4;
  }
  do something5;
}
Run Code Online (Sandbox Code Playgroud)

但是,我无法从中推导出一般算法.

flo*_*olo 2

这通常称为Goto Removal,我们只有一次学生工作,其任务是为 C 实现它。一般来说,您必须使用循环(遗憾的是我们没有将该工作放到网上)。但由于你有只能向前跳跃的限制,所以相对容易:

对所有行进行一次解析并收集所有标签。为每个标签创建一个标志“skip_to_label”。在开始时将所有标志初始化为 false。当您满足标签 X 的条件 goto 时,您现在将在每一行前面添加“if not skip_to_label”,直到标签行,并将标志设置为 true。

这应该已经足够并且可以工作了,但当然不是很理想。

如何优化它:不必预先添加 if,只需为每一行维护一组标志,也不必将某些内容设置为 false,只需为行添加集合中相应的标志即可。

现在,您可以为包含所有行的组创建 if,其中集合不会更改,条件是集合的布尔标志。

您给定代码的示例:

set                    your code
empty                  if cond1 goto a 
skip_to_a,             do something1
skip_to_a,             if cond2 goto b
skip_to_a, skip_to_b   do something2
skip_to_a, skip_to_b   a:
skip_to_b              do something3
skip_to_b, skip_to_c   if cond3 goto c
skip_to_b, skip_to_c   do something4
skip_to_b, skip_to_c   c:
skip_to_b              do something5
skip_to_b              b:
Run Code Online (Sandbox Code Playgroud)

现在,您可以在每行前面写入 if(s),或者从顶部开始并创建一个 if 块,只要集合保持不变即可。

因此,当你开始时,你的第一个是空的,它是一个条件跳转,所以你设置你的标志

if cond1 goto skip_to_a=true;
Run Code Online (Sandbox Code Playgroud)

现在集合发生了变化,并且您使用集合的 if 引入了您的块:

if (!skip_to_a) BEGIN
   do something1
   if cond2 skip_to_b=true;
   END
Run Code Online (Sandbox Code Playgroud)

集合中的下一个更改,因此新的 if 块:

if (!skip_to_a and !skip_to_b) BEGIN
   do something2
   END
Run Code Online (Sandbox Code Playgroud)

等等(我想你现在明白了)。

编辑:正如人们可以很好地看到示例中的集合一样,通常不可能使用嵌套的 if 来对其进行建模,例如,带有skip_to_a的行和带有skip_to_b的行重叠,但两者都不包含另一个完整的行。

  • 您可以使用单个整数变量来代替布尔标志,指示您要使用哪个标签。那么第 N 个块前面的条件就只是 `if (skip_to <= N)`,并且 `goto Mth_label` 被替换为 `skip_to = M`。 (2认同)