Loops 用ANTLR解析循环
我想使用ANTLR解析一个简单的类似matlab的for循环 循环如下所示:Loops 用ANTLR解析循环,loops,antlr,Loops,Antlr,我想使用ANTLR解析一个简单的类似matlab的for循环 循环如下所示: for i=1:8 y(i) = a(i) + i; end 我想解析循环并解析8次y(I)=a(I)+I语句,以便对每个语句执行一些操作 我的规则如下(操作在C中描述): forloop @初始化 { 字符串c=“”; int-mark=input.mark(); } @之后 { if(常数[c]
for i=1:8
y(i) = a(i) + i;
end
我想解析循环并解析8次y(I)=a(I)+I
语句,以便对每个语句执行一些操作
我的规则如下(操作在C中描述):
forloop
@初始化
{
字符串c=“”;
int-mark=input.mark();
}
@之后
{
if(常数[c]<$i2.值){
SetConst(c,常数[c]+1);
输入。倒带(标记);
}
}
:'对于'IDENT'=“i1=常量”:'i2=常量换行符
{
c=$IDENT.text;
如果(!IsConst(c)){
AddConst(c$i1.值);
}
}
声明?
“结束”
;
实际上,当ANTLR解析语句
规则时,它会触发一些操作。因此,在这里,我告诉ANTLR,I是一个常量,首先它的值是1,然后我想重复语句
解析,同时增加我的I
常量
重申一下,我使用了input.Mark()和input.Rewind(),但它并没有像我预期的那样工作,并且ANTLR引发了一些错误,告诉我一些“换行符”标记在“for”关键字处不存在
如果我想触发一些操作直到循环结束,我如何处理循环解析?我找到了解决方案。
实际上,input.Rewind()
的行为不像我第一次预料的那样。它只是简单地将输入缓冲区恢复到以前的状态,由input.Mark()
定义
因此,当到达for循环的末尾时,如果条件仍然为true,我将整个for循环重新注入输入缓冲区
但是!在另一条规则中,我告诉ANTLR for循环后面必须跟一个换行符。在我的例子中,通过回注,第一次循环通过后紧接着第二次循环通过,导致这种构造:
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
当然,由于前7个循环后面没有换行符,所以ANTLR报告了一个错误
解决方案是简单地告诉ANTLR for循环后面不需要紧跟换行符
。它像一个魅力,但我不太满意这个结果
最终的for循环规则如下所示(这只是一个代码清理):
forloop
@init{int mark=input.mark();}
:'对于'IDENT'=“i1=常量”:'i2=常量换行符
{
字符串c=$IDENT.text;
如果(!IsConst(c)){
AddConst(c$i1.值);
}
}
声明?”结束'
{
if(常数[c]<$i2.值){
SetConst(c,常数[c]+1);
输入。倒带(标记);
}
}
;
但是,每次倒带后,用这种方法倒带不会将c循环计数器重新初始化为$1.5的值?
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
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);
}
}
;