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
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.