我正在构建一种主要用于计算目的的语言。它是一种小语言,语法类似C,但功能极其有限。在过去的几天里,我一直在尝试生成封装在大括号中的代码,但是每当我在大括号中输入expressions
时,生成的代码始终用于输入的最后一个表达式。它应该在while
循环中工作。
例如:
while( true )
{
// some expressions (not using any variables for simplicity)
5 + 9;
8 - 10;
4 * 6;
}
但是,在这种情况下,生成的代码仅考虑最后一个表达式 (4 * 6(。
代码链接:https://codeshare.io/GL0xRk
此外,用于处理大括号和其他一些相关代码的代码片段:
calcul returns [String code]
@init
{
$code = new String();
}
@after
{
System.out.print($code);
for( int i = 0; i < getvarg_count(); ++i )
{
System.out.println("POP");
}
System.out.println("HALT");
}
: (decl
{
// declaration
$code += $decl.code;
})*
NEWLINE*
{
$code += "";
}
(instruction
{
// instruction, eg. x = 5; 7 * 4;
$code += $instruction.code;
System.err.println("instruction found");
})*
;
whileStat returns [String code]
: WHILE '(' condition ')' NEWLINE* block
{
int cur_label = nextLabel();
$code = "LABEL " + cur_label + "n";
$code += $condition.code;
$code += "JUMPF " + (cur_label + 1) + "n";
$code += $block.code;
$code += "JUMP " + cur_label + "n";
$code += "LABEL " + (cur_label + 1) + "n";
}
;
block returns [String code]
@init
{
$code = new String();
}
: '{' instruction* '}' NEWLINE*
{
System.err.println("block found");
$code += $instruction.code;
System.err.println("curly braces for while found");
}
;
并且生成的编译器代码:
while(true)
{
5+9;
8-10;
4*6;
}
block found
curly braces for while found
instruction found
LABEL 0
PUSHI 1
JUMPF 1
PUSHI 4
PUSHI 6
MUL
POP
JUMP 0
LABEL 1
HALT
我有一种感觉,$code
总是被重新初始化。或者也许是因为我instruction*
了两个不同的规则。我不确定如何处理这个问题。非常感谢所有的帮助。
谢谢
无论如何,看起来你的问题是block
操作中的$instruction
仅引用最后一条指令,因为块在*
之外,因此该操作仅运行一次。
您可以像在calcul
规则中一样在*
内移动操作,也可以将所有说明放在带有instructions+=instruction*
的列表中,然后在操作中使用$instructions
(或者更好的是:侦听器或访问者(。
PS:我强烈建议使用听众或访问者,而不是在整个语法中进行操作。它们使语法非常难以阅读。