I want to parser a simple matlab-like for-loop, using ANTLR.
The loop is like :
for i=1:8
y(i) = a(i) + i;
end
I want to parse the loop and parse 8 times the y(i) = a(i) + i statement, in order to do some actions on each statement.
My rule is as follows (actions are described in C#) :
forloop
@init
{
string c = "";
int mark = input.Mark();
}
@after
{
if (constants[c] < $i2.value) {
SetConst(c, constants[c] + 1);
input.Rewind(mark);
}
}
: 'for' IDENT '=' i1=constant ':' i2=constant NEWLINE
{
c = $IDENT.text;
if (!IsConst(c)) {
AddConst(c, $i1.value);
}
}
statements?
'end'
;
Actually, when ANTLR parses the statements rule, it triggers some actions. So, here, I tell ANTLR that i is a constant which value is 1 for starters, and then I want to reiterate the statements parsing, while incrementing my i constant.
To reiterate, I use input.Mark() and input.Rewind(), but it does not work as I expect, and some error is raised by ANTLR, telling me that some “NEWLINE” tokens are not present at the ‘for’ keyword.
How can I handle loop-parsing if I want to trigger some actions until the loop is over ?
I found the solution.
Actually,
input.Rewind()does not act like agoto, as I first expected. It just simply restores the input buffer to a previous state, defined byinput.Mark().So, when reaching the end of my for-loop, if the condition was still true, I reinjected the whole for-loop into the input buffer.
BUT ! In another rule, I told ANTLR that a for-loop MUST be followed by a NEWLINE. And in my case, through the reinjection, the first-pass-for-loop was immediatly followed by the second-pass-for-loop, resulting in this construction :
Of course, since no
NEWLINEfollowed the first 7th loops, ANTLR reported an error.The solution was to simply tell ANTLR that a for-loop needs not to be followed by a
NEWLINE. It works like a charm, but I’m not that much satisfied by this result…The final for-loop rule looks like (this is just a code cleanup) :