我无法理解如何在ANTLR4,Javascript目标中正确使用访问者。
我准备了一个非常基本的语法,它接受INT + INT
或INT - INT
次操作。
grammar PlusMinus;
INT : [0-9]+;
WS : [ \t\r]+ -> skip;
PLUS : '+';
MINUS : '-';
input : plusOrMinus
;
plusOrMinus
: numberLeft PLUS numberRight # Plus
| numberLeft MINUS numberRight # Minus
;
numberLeft : INT;
numberRight : INT;
根据这一语法,ANTLR将生成一个具有以下三个功能的访问者:visitInput
,visitPlus
和visitMinus
。我从visitInput
开始,我可以通过执行operation = ctx.plusOrMinus()
来获取操作ctx。
这就是我被卡住的地方,我怎么知道operation
的类型是加号还是减号?换句话说,我在哪里将ctx.plusOrMinux()
传递给visitPlus()
或visitMinus()
?
我成功创建了一个可以工作的访问者,但它非常难看,I am posting it here因为这可能有助于更好地理解我的问题。第20-29行就是问题所在。
答案 0 :(得分:1)
首先...... PLUS和MINUS是词法规则。您不访问令牌(词法分析器规则的结果)。
看起来你期望它像监听器一样工作(你设置你的函数,当树步行者到达那个节点时被调用。你可以在进入或退出节点时被调用(取决于是否你希望在你处理它的孩子之前或之后得到节点。访问者希望你处理你自己的树导航,这有时是有用的,但听众在适合目的的地方更干净。有了嵌套,你可能想要在处理子节点之后监听,所以你需要在你的监听器上实现一个exitPlusOrMins()函数。我建议你在这个函数里面的调试器中停止你的代码,看看你可以使用的对象(在ctx对象中)。
(您还需要重新考虑您的numberLeft和numberRIght解析器规则。更像是:
plusOrMinus:lexpr = INT(op = PLUS | op = MINUS)rexpr = INT;
会给你一个非常接近的东西,相当于你到目前为止。你所拥有的将使用像ANTLR这样的递归下降解析器(就这个例子而言),但是你朝着错误的方向前进,使它们成为不同的解析规则。)
为了比增加或减去整数更进一步,你需要lexpr和rexpr实际上是表达式本身(你应该阅读ANTLR书中的表达式解析;它的覆盖非常好)。
使用该规则,exitPlusOrMinus可以解析lexpr和rexpr的int值,然后计算op的值以确定是添加还是减去。