代码之家  ›  专栏  ›  技术社区  ›  Aurelien Ribon

用ANTLR解析循环

  •  2
  • Aurelien Ribon  · 技术社区  · 14 年前

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

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

    我的规则如下(操作在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'
    ;
    

    statements i is a constant which value is 1 首先,我想重申 正在分析,同时递增 i 不变。

    重申一下,我使用了input.Mark()和input.Rewind(),但它并没有像我预期的那样工作,而且ANTLR引发了一些错误,告诉我一些“NEWLINE”标记在'for'关键字处不存在。

    1 回复  |  直到 14 年前
        1
  •  2
  •   Aurelien Ribon    14 年前

    我找到了解决办法。 input.Rewind() 不会表现得像 goto input.Mark() .

    因此,当到达for循环的末尾时,如果条件仍然为真,我将整个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
    

    NEWLINE

    解决方案是简单地告诉ANTLR for循环不需要后跟 换行 . 它就像一个魅力,但我不太满意这个结果。。。

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