【发布时间】:2012-08-23 00:28:17
【问题描述】:
我已经知道这个问题的解决方法,但我想真正使用这种方法,至少有一个原因——它应该可以工作。
这条规则取自 Terence Parr 的“The Definitive ANTLR Reference”(本书适用于 ANTLR3):
expr : (INT -> INT) ('+' i=INT -> ^('+' $expr $i) )*;
如果INT后面没有+,则结果将为INT(单节点),如果是--将构建子树,第一个INT(称为$expr)作为左分支。
我想建立类似的规则,但使用自定义操作:
mult_expr : (pow_expr -> pow_expr )
(op=MUL exr=pow_expr
-> { new BinExpr($op,$mult_expr.tree,$exr.tree) })*;
ANTLR 接受这样的规则,但是当我使用输入(例如)“5 * 3”运行解析器时,它会给我一个错误“line 1:1 missing EOF at '*'5”。
问题:如何在自定义重写操作中使用反向引用?
【问题讨论】:
-
@Bart Kiers,不要在解析器语法中使用自定义操作,而是依赖默认的 AST。然后编写树语法,并将整个 AST 重写为自定义的。我希望非常避免这种情况,因为它使我的工作加倍,而且我看到的这种变通方法越多,我就越怀疑 ANTLR 的能力(它应该可以节省我的工作;-D)。跨度>
-
不确定这是否可能...但是,可以选择创建自己的
CommonTreeAdaptor吗? (见:stackoverflow.com/questions/7635729/extend-antlr3-asts) -
@Bart Kiers,我看不出适配器如何改变这里的东西(顺便说一句。当你引入自定义 AST 时,你也必须引入自定义适配器,我做到了)。
-
您已经拥有自己的适配器了吗?那你为什么不在
create(Token)方法中创建你自己的节点类的实例,让你的规则是:mult_expr : pow_expr (MUL^ pow_expr)*? -
是的,我就是这个意思。如果是一元
-,只需将U_SUB放入您的tokens { ... }块并执行:unary_expr : SUB atom -> ^(U_SUB atom) | atom;。那么在适配器的create(...)方法中出现的任何SUB都将是二进制-和U_SUB一元-。
标签: parsing rewrite antlr abstract-syntax-tree backreference