使用ANTLR解析循环 [英] Parsing a loop with ANTLR

查看:34
本文介绍了使用ANTLR解析循环的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用ANTLR解析一个类似于Matlab的简单for循环.

I want to parser a simple matlab-like for-loop, using ANTLR.

循环就像:

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

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

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.

我的规则如下(动作在C#中进行了描述):

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'
;

实际上,当ANTLR解析 statements 规则时,它会触发一些操作.因此,在这里,我告诉ANTLR,对于初学者来说, i是一个常量,其值为1 ,然后我想重申 statement 的解析,同时增加我的 i常量.

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.

重申一下,我使用input.Mark()和input.Rewind(),但是它不能按我预期的那样工作,并且ANTLR引发了一些错误,告诉我在该处不存在一些"NEWLINE"令牌"for"关键字.

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 ?

推荐答案

我找到了解决方案.实际上,正如我首先期望的那样, input.Rewind()的行为不像 goto .它只是将输入缓冲区还原到由 input.Mark()定义的先前状态.

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

因此,当到达for循环的末尾时,如果条件仍然成立,我会将整个for循环重新注入到输入缓冲区中.

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.

但是!在另一条规则中,我告诉ANTLR,必须在for循环后跟一个NEWLINE.在我的情况下,通过重新注入,立即进行第一次循环,然后进行第二次循环,从而得到以下构造:

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

当然,由于没有 NEWLINE 遵循前7个循环,因此ANTLR报告了错误.

Of course, since no NEWLINE followed the first 7th loops, ANTLR reported an error.

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

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

最终的for循环规则如下所示(这只是代码清除):

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

这篇关于使用ANTLR解析循环的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆