在ANTLR4(javascript目标)中使用访问者的正确方法



我在理解如何在ANTLR4,Javascript目标中正确使用访问者时遇到了麻烦。

我准备了一个非常基本的语法,它接受INT + INTINT - INT操作。

grammar PlusMinus;
INT    : [0-9]+;
WS     : [ tr]+ -> skip;
PLUS  : '+';
MINUS : '-';
input : plusOrMinus
    ;
plusOrMinus
    : numberLeft PLUS numberRight # Plus
    | numberLeft MINUS numberRight # Minus
    ;
numberLeft : INT;
numberRight : INT;

从这个语法中,ANTLR将生成一个具有这三个功能的访问者,visitInputvisitPlusvisitMinus。我从visitInput开始,通过执行此operation = ctx.plusOrMinus()来获取操作ctx。

这就是我卡住的地方,我怎么知道operation类型是正负?换句话说,我在哪里传递ctx.plusOrMinux()visitPlus()visitMinus()

我设法创建了一个确实有效的访问者,但它非常丑陋,我在这里发布它,因为也许它有助于更好地理解我的问题。第 20-29 行是问题所在。

首先...加号和减号是词法分析器规则。 您不访问令牌(词法分析器规则的结果)。

看起来你希望它像一个侦听器一样工作(你设置了当树步行者到达该节点时被调用的函数。 可以在进入或退出节点时调用节点(取决于您是在处理节点的子节点之前还是之后获取节点)。 访问者希望您处理自己的树导航,这有时很有用,但听众在适合目的的地方更干净。 使用嵌套时,您可能希望在处理子节点后进行侦听,因此您需要在侦听器上实现 exitPlusOrMins() 函数。 我建议在此函数内的调试器中停止代码,以查看可用的对象(在 ctx 对象中)。

(您还需要重新考虑您的 numberLeft 和 numberRIght 解析器规则。 更像是:

plusOrMinus: lexpr=INT (op=PLUS | op=MINUS) rexpr=INT;

会给你一个非常接近的等价物,你目前所拥有的。你所拥有的将与像 ANTLR 这样的递归下降解析器一起使用(就这个例子而言),但你正朝着错误的方向前进,使它们成为不同的解析规则。 具体来说,通过使它们成为两个替代解析规则,您赋予 PLUS 的优先级高于减号,并且 PLUS 和 MINUS 在评估顺序上应具有相同的优先级。 因此,它们需要是相同的解析规则。当您在解析器规则中放置这样的替代项时,您也建立了优先级,因此请注意这些规则的顺序。

但是,为了获得比添加或减去整数更进一步,您需要lexpr和rexpr实际上本身就是表达式(您应该阅读ANTLR书中的表达式解析;它涵盖了非常好)。

使用该规则,您的 exitPlusOrMinus 可以解析 lexpr 和 rexpr 的 int 值,然后评估运算的值以确定是加法还是减法。

最新更新