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

问题描述:

我正在尝试编写一个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)。

如何通过语法更改或解析器操作更改独立地对待每个元素?

我还想到,我对这些概念的词汇量并不是它应该是的,所以如果看起来我滥用了一个词,我可能是。


编辑回应韦恩的评论:

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


结果...

基于chollida的答案,我结束了这个效果很好:

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

Add方法被调用的my_ident的每场比赛。这里

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的内置的+我们迭代自己的:

+0

对于我来说,回答你的问题还不够,是否$ op不包含所有三个标记?还是其他的东西,比如你想为每个标记做一些特定的事情?为了将所有三个令牌放入$ op中,我认为您需要op + = my_ident +(等号前面的另一个加号)。我需要更多信息来回答另一个问题。 – WayneH 2010-02-02 00:06:35

+0

我的问题是我真的不知道“$ op”究竟是什么。我到了那里,部分归功于你对这个和其他问题的帮助!我订购了Terence Parr书。 :)是的,我只是想能够对每个令牌做同样的事情 - 在这种情况下,将令牌添加到列表中。我将编辑我的问题以反映您提出的“op +”建议的结果。 – 2010-02-02 05:45:36

+0

好吧,所以来自该规则的my_ident和返回值加上$ op都按预期工作(此时通缉)。现在获取my_list中的$ e以返回正确的对象。它应该只返回$ op的列表吗?我想一个你想修改my_list规则在开始时是 - my_list返回[IEvaluator e] @init {$ e = new MyListEvaluator(); } :'$'... 另外,您可能希望更改my_ident或my_list中的返回标签/变量;他们两个都可能会有点混乱。 接下来是MyListEvaluator vs MyIdentEvaluator(我不知道C#)。 – WayneH 2010-02-02 13:34:04

如果我在写这个我会分裂出单独匹配到一个列表模式。我们匹配第一个项目并将其添加到列表中,然后匹配连续的项目并存储它们。

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

我做在Java中类似的事情,不得不检查生成的代码,发现ANTLR3生成一个变量称为“LIST_NAME”(其中在这种情况下,NAME = OPS),这是所有的子列表 - 语言规则返回值。我想在C#中它是一样的,虽然我可能是错的。你会希望这个变量被称为“ops”,但该变量将只包含最后匹配的规则值(至少在Java中)。