Antlr4 Javascript 目标 - 访客问题和标记替代

Antlr4 Javascript target - issue with Visitor and labeled alternative

我正在使用带有 Java脚本目标的 antlr4 (4.5.3),并尝试实现访问者。

按照 antlr4 书的计算器示例(伟大的书顺便说一句),我正在尝试创建一个类似的语法:

...
expr:   expr op=(​'*'​|​'/'​) expr      # MulDiv
    |   expr op=(​'+'​|​'-'​) expr      # AddSub
    |   INT                         # int
    |   ​'('​ expr ​')'​                # parens
    ;
...

问题:为标记的替代方法(例如 visitMulDiv)创建了访问者方法,但是缺少 2 个东西:

  1. 在基本访问者原型中实现 visitExpr
  2. 调用时自动检测正确的选择 this.visit(ctx.expr()) - 意味着访问正确的 visitX 方法。

书中Java中的访问者是这样实现的。

我已经通过实现 visitExpr() 和修改上下文 c'tor 名称(类似于 here)来解决这个问题,但我觉得 JS 应该可以免费工作,就像 Java 版本。

这是一个错误还是我遗漏了什么?

我认为这是一个错误。在运行时源代码中,最新的javascript运行时(4.5.2)中的ParseTreeVisitor.visit与python2版本(4.5.3)有点不同。在 python2 版本中,ParseTreeVisitor.visit 利用 RuleContext.accept 方法来触发不同的访问者事件。我假设 Antlr4 的开发人员忘记更新 javascript 运行时。

有快速解决方法。

antlr4/tree/Tree.js

ParseTreeVisitor.prototype.visit = function(ctx) {
    // if (Utils.isArray(ctx)) {
    //  var self = this;
    //  return ctx.map(function(child) { return visitAtom(self, child)});
    // } else {
    //  return visitAtom(this, ctx);
    // }
    return ctx.accept(this)
};

有一个更好的方法,不修改库函数。

ValidatorVisitor.prototype.visitExpr = function(ctx) {
    return ctx.accept(this);
}

我相信这个问题已经在 antlr 4.7 中得到修复:

ParseTreeVisitor.prototype.visit = function(ctx) {
    if (Array.isArray(ctx)) {
        return ctx.map(function(child) {
            return child.accept(this);
        }, this);
    } else {
        return ctx.accept(this);
    }
};