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

Parsing 如何对规则中可以匹配多个项的每个项执行ANTLR解析器操作?,parsing,antlr,grammar,Parsing,Antlr,Grammar,我正在尝试编写一个与列表匹配的ANTLR解析器规则,我想编写一个解析器操作,可以独立处理列表中的每个项目 这些规则的输入示例如下: $(A1 A2 A3) 我希望生成一个evaluator,其中包含三个MyIdentityEvaluator对象的列表——A1、A2和A3各一个 下面是我的一段语法: my_list returns [IEvaluator e] : { $e = new MyListEvaluator(); } '$' LPAREN o

我正在尝试编写一个与列表匹配的ANTLR解析器规则,我想编写一个解析器操作,可以独立处理列表中的每个项目

这些规则的输入示例如下:

$(A1 A2 A3)
我希望生成一个evaluator,其中包含三个
MyIdentityEvaluator
对象的列表——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)

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

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


根据韦恩的评论编辑:

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


结果

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

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

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的内置
+
,而是自己进行迭代。我们匹配第一个项目并将其添加到列表中,然后匹配后续项目并存储它们

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

我在Java中做了类似的事情,必须检查生成的代码,以发现ANTLR3生成了一个名为“list_NAME”(在本例中NAME=ops)的变量,该变量是所有子令牌规则返回值的列表。我想C#也是一样,尽管我可能错了。您可能希望该变量仅被称为“ops”,但该变量将只包含最后匹配的规则值(至少在Java中)。

这还不足以回答您的问题,$op是否不包含所有三个标记?或者其他一些事情,比如你想为每个令牌做一些特定的事情?要将所有三个代币转换成$op,我认为您需要op+=my_ident+(等号前面的另一个加号)。我需要更多的信息来回答另一个问题。我的问题是我真的不知道“$op”到底是什么。我能做到这一点,一定程度上要感谢你在这个问题和其他问题上的帮助!我订购了特伦斯·帕尔的书。:)是的,我只想对每个令牌执行相同的操作——在本例中,将令牌添加到列表中。我将编辑我的问题,以反映您提出的“op+”建议的结果。好的,那么来自该规则的my_ident和返回值加上$op都按预期工作(此时需要)。现在获取my_列表中的$e以返回正确的对象。它应该只返回$op的列表吗?我认为您希望在开始时修改my_list规则-my_list返回[IEEvaluator e]@init{$e=new MyListeEvaluator();}:“$”。。。此外,您可能需要更改my_ident或my_列表中的返回标签/变量;它们都是e可能会有点混乱。接下来是MyListEvaluator与MyIdentitEvaluator(我不知道C)。