Yacc/Bison语义值通过规则中途更改

Yacc/Bison语义值通过规则中途更改,bison,yacc,Bison,Yacc,另一方面: While0: ... jne EndWhile1 ... jmp While0 EndWhile0: 整数应该保持不变。我想不出语义值会发生变化的任何原因。有人能给我指出正确的方向吗?在减少整个规则之前,不会设置迭代的语义值,此时$$可用于在操作代码中引用它。在操作代码段中使用$$实际上是指规则的隐式部分完成部分;只有在结束语句的操作中,非终端将$$引用迭代 这是因为yacc/bison在内部实现为规则形式的级联规则,只在最后执行操作 那么,试试这个: While2: ... j

另一方面:

While0:
...
jne EndWhile1
...
jmp While0
EndWhile0:

整数应该保持不变。我想不出语义值会发生变化的任何原因。有人能给我指出正确的方向吗?

在减少整个规则之前,不会设置迭代的语义值,此时$$可用于在操作代码中引用它。在操作代码段中使用$$实际上是指规则的隐式部分完成部分;只有在结束语句的操作中,非终端将$$引用迭代

这是因为yacc/bison在内部实现为规则形式的级联规则,只在最后执行操作

那么,试试这个:

While2:
...
jne EndWhile2
...
jmp While0
EndWhile0:
iteration\u stmt:WHILE{$$=LabelSeed;LabelSeed++;
fprintf(fp,“而%i:\n”,$);
}
“('expression')”{fprintf(fp,“cmp%s,1\n”,regToString($3));
fprintf(fp,“jne EndWhile%i\n”,$1);
下一步--;
}
语句{fprintf(fp,“jmp While%i\n”,$1);
fprintf(fp,“EndWhile%i:\n”,$1);
}
; 

其中,第一个$$为WHILE标记加载语义值,其他操作可以引用该语义值。

谢谢!这修复了我程序中的另一个小错误,因为我把值堆栈搞乱了。只是想让其他人知道,我所做的是创建一个子规则来执行第一个操作,并使用该规则来保存LabelSeed。基本上和你的想法一样,只是我不需要在lex中设置值<代码>whilesubroutine:WHILE{$$=LabelSeed++;fprintf(fp,“WHILE%i:\n”,$$);}将具有中间规则操作的规则分解为具有结束操作的简单规则级联不是完全等价的。根据一些模糊的情况,语法变得模棱两可。对于终端,由于默认规则{$$=$1;},Lex中设置的值成为语义值
While2:
...
jne EndWhile2
...
jmp While0
EndWhile0:
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);
                                    }
                ;