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

查看:29
本文介绍了使用 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 对于初学者,然后我想重申 statements 解析,同时增加我的 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天全站免登陆