代码之家  ›  专栏  ›  技术社区  ›  Chris Farmer Marcelo Cantos

如何对一个规则中可以匹配多个项的每个项执行ANTLR解析器操作?

  •  4
  • Chris Farmer Marcelo Cantos  · 技术社区  · 14 年前

    我正试图编写一个与事物列表相匹配的ANTLR解析器规则,我想编写一个解析器操作,它可以独立地处理列表中的每个项。

    这些规则的一些示例输入是:

    $(A1 A2 A3)
    

    我希望得到一个包含三个列表的评价者 MyIdentEvaluator 对象——A1、A2和A3各一个。

    以下是我的语法片段:

    my_list returns [IEvaluator e]
        : { $e = new MyListEvaluator(); }
          '$'
          LPAREN
          op=my_ident+ { 
                         /* want to do something here for each 'my_ident'. */ 
                         /* the following seems to see only the 'A3' my_ident */
                         $e.Add($op.e);
                       }
          RPAREN
        ;
    
    my_ident returns [IEvaluator e]
        : IDENT { $e = new MyIdentEvaluator($IDENT.text); }
        ;
    

    我想 my_ident 定义正确,因为我可以看到 MyIdentEvaluators 按预期为输入字符串创建,但仅为最后一个 我的身份 曾经被添加到列表中(在我的示例输入中是A3)。

    如何通过语法更改或解析器操作更改来最好地独立处理这些元素中的每一个?

    我还想到,我对这些概念的词汇表并不是它应该是什么,所以如果它看起来像我误用了一个术语,我可能是。


    根据韦恩的评论编辑:

    我试着用 op+=my_ident+ . 在这种情况下, $op 在我的行动中变成 IList (C)包含 Antlr.Runtime.Tree.CommonTree 实例。它给了我每个匹配的令牌一个条目 美元 ,所以我看到了我的三场比赛,但我没有 我的身份评估器 我真正想要的实例。我希望我能在Antlr文档中找到一个规则属性来帮助解决这个问题,但是似乎没有什么能帮助我摆脱这个问题。 伊利斯特 .


    结果…

    根据Chollida的回答,我得出了一个很好的结论:

    my_list returns [IEvaluator e]
        : { $e = new MyListEvaluator(); }
          '$'
          LPAREN
          (op=my_ident    { $e.Add($op.e); } )+
          RPAREN
        ;
    

    这个 Add 方法将为我的每个匹配项调用。

    2 回复  |  直到 14 年前
        1
  •  1
  •   chollida    14 年前

    如果我在写这篇文章,我会把匹配的个体划分成一个列表模式:

    my_list returns [IEvaluator e]
    : { $e = new MyListEvaluator(); }
      '$'
      LPAREN
      op=my_ident { $e.Add($op.e); }
      (opNext=my_ident { $e.Add($opNext.e); })*
      RPAREN
    ;
    
    
    my_ident returns [IEvaluator e]
    : IDENT { $e = new MyIdentEvaluator($IDENT.text); }
    ;
    

    这里不是使用安特尔的内置 + 我们自己做迭代。我们匹配第一个项目并将其添加到列表中,然后匹配后续项目并存储它们。

        2
  •  1
  •   JoelPM    14 年前
    my_list returns [IEvaluator e]
      : '$' LPAREN ops+=my_ident+ RPAREN { e = new MyListEvaluator(list_ops); }
      ;
    

    我在Java中做了类似的事情,必须检查生成的代码,发现ANTLR3生成一个名为“ListName Name”的变量(这里是Name=OPS),它是所有子令牌规则返回值的列表。我想在C里是一样的,尽管我可能错了。你会期望变量被称为“OPS”,但是该变量只包含最后匹配的规则值(至少在Java中)。