如何为可匹配多个项目的规则中的每个项目执行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的内置的+
我们迭代自己的:
如果我在写这个我会分裂出单独匹配到一个列表模式。我们匹配第一个项目并将其添加到列表中,然后匹配连续的项目并存储它们。
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 +(等号前面的另一个加号)。我需要更多信息来回答另一个问题。 – WayneH 2010-02-02 00:06:35
我的问题是我真的不知道“$ op”究竟是什么。我到了那里,部分归功于你对这个和其他问题的帮助!我订购了Terence Parr书。 :)是的,我只是想能够对每个令牌做同样的事情 - 在这种情况下,将令牌添加到列表中。我将编辑我的问题以反映您提出的“op +”建议的结果。 – 2010-02-02 05:45:36
好吧,所以来自该规则的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