iteration_stmt : WHILE {$$ = LabelSeed; LabelSeed++;
fprintf(fp, "While%i:\n", $$);
}
'(' expression ')' {fprintf(fp, "cmp %s, 1\n", regToString($<n>3));
fprintf(fp, "jne EndWhile%i\n", $$);
NextReg--;
}
statement {fprintf(fp, "jmp While%i\n", $$);
fprintf(fp, "EndWhile%i:\n", $$);
}
;
我尝试使用 iteration_stmt 的语义值来跟踪 LabelSeed 值,但它的值并不是&# 39;在其他2个动作中保持不变。例如,在一种情况下,我的输出是:
While0:
...
jne EndWhile1
...
jmp While0
EndWhile0:
在另一个中:
While2:
...
jne EndWhile2
...
jmp While0
EndWhile0:
整数应该保持不变。我无法想到语义价值会发生变化的任何原因。有人能指出我正确的方向吗?
答案 0 :(得分:0)
整个规则减少之前,不会设置 iteration_stmt 的语义值,此时可以使用$$在动作代码中引用它。您在动作代码段中使用$$实际上是指隐式的部分完成的规则部分;仅在结束语句的操作中,非终端将$$引用 iteration_stmt 。
这是因为内部yacc / bison将rules with mid-rule actions实现为常规形式的级联规则,仅在最后执行操作。
所以,试试这个:
iteration_stmt : WHILE {$$ = LabelSeed; LabelSeed++;
fprintf(fp, "While%i:\n", $$);
}
'(' expression ')' {fprintf(fp, "cmp %s, 1\n", regToString($<n>3));
fprintf(fp, "jne EndWhile%i\n", $1);
NextReg--;
}
statement {fprintf(fp, "jmp While%i\n", $1);
fprintf(fp, "EndWhile%i:\n", $1);
}
;
第一个$$加载 WHILE 标记的语义值,其他操作可以引用该标记。