Search code examples
while-loopcompiler-constructionantlr4

ANTLR4 generating code for the last expression entered in curly braces


I'm building a language primarily used for calculation purposes. It is a small language with C like syntax but extremely limited functionality. For the past few days, I've been trying to generate code that is encapsulated in curly braces however whenever I enter expressions in curly braces, the code generated is always for the last expression entered. It is supposed to work on a while loop.

For example:

while( true )
{
    // some expressions (not using any variables for simplicity)
    5 + 9;
    8 - 10;
    4 * 6;
}

However the code generated only takes into account the last expression (4 * 6) in this case.

The link to the code: https://codeshare.io/GL0xRk

And also, the code snippet for handling curly braces and some other relative code:

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");
}
;

And the compiler code generated:

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

I have a feeling that the $code is always reinitialized. Or maybe it's because I have instruction* in two different rules. I'm not sure how else to handle this problem. All help is much appreciated.

Thank you


Solution

  • Anyway, it looks like your problem is that $instruction in block's action only refers to the last instruction because the block is outside of the *, so the action only gets run once.

    You can either move the action inside the * like you did in the calcul rule or you can put all the instructions in a list with instructions+=instruction* and then use $instructions in the action (or better: a listener or visitor).

    PS: I strongly recommend to use a listener or visitor instead of having actions all over your grammar. They make the grammar very hard to read.