使用ANTLR解析循环 [英] Parsing a loop with 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屋!