ANTLR4 为花括号中输入的最后一个表达式生成代码
ANTLR4 generating code for the last expression entered in curly braces
我正在构建一种主要用于计算目的的语言。它是一种具有类似 C 语法但功能极其有限的小型语言。在过去的几天里,我一直在尝试生成封装在大括号中的代码,但是每当我在大括号中输入 expressions
时,生成的代码总是针对最后输入的表达式。它应该在 while
循环中工作。
例如:
while( true )
{
// some expressions (not using any variables for simplicity)
5 + 9;
8 - 10;
4 * 6;
}
然而,生成的代码只考虑了本例中的最后一个表达式 (4 * 6)。
link 代码:
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:我强烈建议使用侦听器或访问器,而不是在整个语法中使用操作。它们使语法很难阅读。
我正在构建一种主要用于计算目的的语言。它是一种具有类似 C 语法但功能极其有限的小型语言。在过去的几天里,我一直在尝试生成封装在大括号中的代码,但是每当我在大括号中输入 expressions
时,生成的代码总是针对最后输入的表达式。它应该在 while
循环中工作。
例如:
while( true )
{
// some expressions (not using any variables for simplicity)
5 + 9;
8 - 10;
4 * 6;
}
然而,生成的代码只考虑了本例中的最后一个表达式 (4 * 6)。
link 代码: 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:我强烈建议使用侦听器或访问器,而不是在整个语法中使用操作。它们使语法很难阅读。