我正在尝试编写一个匹配事物列表的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
变为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
;
my_ident的每次匹配都会调用Add
方法。
答案 0 :(得分:1)
如果我写这篇文章,我会将个别匹配分成列表模式:
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的内置+
,而是自己进行迭代。我们匹配第一个项目并将其添加到列表中,然后我们匹配连续项目并存储它们。
答案 1 :(得分:1)
my_list returns [IEvaluator e]
: '$' LPAREN ops+=my_ident+ RPAREN { e = new MyListEvaluator(list_ops); }
;
我在Java中做了类似的事情,不得不检查生成的代码,发现ANTLR3生成一个名为“list_NAME”的变量(在这种情况下NAME = ops),这是所有子令牌规则返回的列表值。我想它在C#中是一样的,虽然我可能是错的。您可能希望变量只被称为“ops”,但该变量将只包含最后匹配的规则值(至少在Java中)。