使用 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
对于初学者,然后我想重申 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屋!