Compiler construction FOR循环控制流的回补

Compiler construction FOR循环控制流的回补,compiler-construction,bison,intermediate-language,Compiler Construction,Bison,Intermediate Language,我正在寻找在for-LOOP中的Backpatching 我知道IF-THEN-ELSE的这种方法是这样的: IF '(' expr M ')' stmt N ELSE L stmt L { backpatch($4, $9 - $4); backpatch($7, $11 - $7); } 您可以在回答中使用以下标记: FOR '(' expr ';' L expr M N ';' L expr N ')' L stmt N L 请解释一下你的答案。对于expr1';'L1 e

我正在寻找在for-LOOP中的Backpatching

我知道IF-THEN-ELSE的这种方法是这样的:

IF '(' expr M ')' stmt N ELSE L stmt L
{
   backpatch($4, $9 - $4);
   backpatch($7, $11 - $7);
}
您可以在回答中使用以下标记:

FOR '(' expr ';' L expr M N ';' L expr N ')' L stmt N L
请解释一下你的答案。

对于expr1';'L1 expr2';'L2 expr3 N1 L3 stmt N2 我们将有这样的场景:

backpatch( $14 , $8 - $14 );
backpatch( $10 , $5 - $10 ); 
backpatchlist( $6.truelist , $12 );
backpatchlist( $6.falselist , pc );
第一行:当我们在循环N2的末尾时,我们必须跳转到循环L2的增量部分的第一行来计算expr3 第二行:在计算expr3之后,必须跳转到测试表达式部分expr2的第一行 第三行:若expr2的计算结果为真,则跳转到循环体L3的第一行以计算stmt。 第四行:如果expr2的求值为false,则循环处理已完成,我们必须跳转循环后的第一条指令,这条指令可由pc访问。 在这种情况下,标记必须定义为:

L1,L2,L3 :  { 
              $$ = pc;
            }

N1       :  {
             emit(pop);
             $$ = pc;
             emit3(goto_, 0);
            }

N2       : { 
             $$ = pc;
             emit3(goto_, 0);
           }

您用于此任务的软件是什么?哪个版本的yacc?你有IF-THEN-ELSE版本的源代码吗?backpatchx,y的参数是什么?我假设$N是对语法符号的引用。旁白:为什么有L stmt L而不仅仅是stmt L?@battlmonstr:L显然是一条规则,它为分支目的插入一个标签,因此我们需要在else语句之前插入一个标签,用于将测试的假部分分支到,在else语句之后插入一个标签,用于将N分支到。然而,在我看来,这整个问题都是家庭作业。这看起来很像家庭作业问题。请阅读并相应地修改您的问题;在高级语言的中级表达中没有理由这样做。回接允许指令(如跳转)引用稍后出现的标签。当我们组装跳转时,标签的地址是未知的,所以我们只需为地址/偏移量加上零或其他什么,并保留一个记录。稍后,当我们看到标签,并且它的地址被分配时,我们将该地址放回跳转指令中:这是回补。语法产品的语义值似乎是指令地址?奇怪的