使用ANTLR解析循环

时间:2010-04-20 11:53:48

标签: loops antlr

我想使用ANTLR解析一个简单的类似matlab的for循环。

循环就像:

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

我想解析循环并解析y(i) = a(i) + i语句的8倍,以便对每个语句执行一些操作。

我的规则如下(操作在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'
;

实际上,当ANTLR解析statements规则时,它会触发一些操作。所以,在这里,我告诉ANTLR i is a constant which value is 1为初学者,然后我想重申statements解析,同时递增我的i常数。

重申一下,我使用input.Mark()和input.Rewind(),但是它没有按照我的预期工作,并且ANTLR引发了一些错误,告诉我一些“NEWLINE”令牌不存在于'for'keyword。

如果我想在循环结束之前触发某些操作,我该如何处理循环解析?

1 个答案:

答案 0 :(得分:2)

我找到了解决方案。 实际上,正如我最初的预料,input.Rewind()并不像goto那样行事。它只是简单地将输入缓冲区恢复到由input.Mark()定义的先前状态。

因此,当到达for循环结束时,如果条件仍为真,我将整个for循环重新注入输入缓冲区。

但是!在另一个规则中,我告诉ANTLR必须在for循环后跟一个NEWLINE。在我的情况下,通过重新注入,第一次通过循环后立即进行第二次循环,导致这种结构:

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

当然,由于没有NEWLINE跟随前7个循环,ANTLR报告错误。

解决方案是简单告诉ANTLR for循环不需要跟NEWLINE。它就像一个魅力,但我对这个结果并不满意......

最终的for循环规则看起来像(这只是代码清理):

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