2
votes

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 ?

1

1 Answers

2
votes

I found the solution. Actually, input.Rewind() does not act like a goto, as I first expected. It just simply restores the input buffer to a previous state, defined by input.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 :

for i=1:8
    y(i) = a(i) + i;
endfor i=1:8
    y(i) = a(i) + i;
endfor i=1:8
    y(i) = a(i) + i;
endfor i=1:8
    y(i) = a(i) + i;
endfor i=1:8
    y(i) = a(i) + i;
endfor i=1:8
    y(i) = a(i) + i;
endfor i=1:8
    y(i) = a(i) + i;
endfor i=1:8
    y(i) = a(i) + i;
end

Of course, since no NEWLINE followed 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) :

forloop
    @init {int mark = input.Mark();}
    : 'for' IDENT '=' i1=constant ':' i2=constant NEWLINE
        {
            string c = $IDENT.text;
            if (!IsConst(c)) {
                AddConst(c, $i1.value);
            }
        }
      statements? 'end'
        {
            if (constants[c] < $i2.value) {
                SetConst(c, constants[c] + 1);
                input.Rewind(mark);
            }
        }
    ;