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

我正在尝试编写一个匹配事物列表的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按照我的输入字符串的预期创建,但只有最后一个my_ident被添加到列表中(在我的示例输入中为A3).

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

在我看来,我对这些概念的词汇不是它应该是的,所以如果它看起来像是在滥用一个术语,我可能就是这样.

编辑回应Wayne的评论:

我尝试使用op = my_ident.在这种情况下,我的操作中的$op成为包含Antlr.Runtime.Tree.CommonTree实例的IList(在C#中).它确实在$op中为每个匹配的令牌提供了一个条目,所以我看到了我的三个匹配,但是我没有我真正想要的MyIdentEvaluator实例.我希望我能在ANTLR文档中找到一个可能对此有帮助的规则属性,但似乎没有任何东西可以帮助我摆脱这个IList.

结果…

根据chollida的回答,我最终得到了这个效果很好:

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

为my_ident的每个匹配调用Add方法.

最佳答案 如果我写这篇文章,我会将个别匹配分成列表模式:

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

这里不是使用Antlr内置的,而是自己进行迭代.我们匹配第一个项目并将其添加到列表中,然后我们匹配连续项目并存储它们.

点赞