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 个东西:
- 在基本访问者原型中实现
visitExpr
。
- 调用时自动检测正确的选择
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);
}
};
我正在使用带有 Java脚本目标的 antlr4 (4.5.3),并尝试实现访问者。
按照 antlr4 书的计算器示例(伟大的书顺便说一句),我正在尝试创建一个类似的语法:
...
expr: expr op=('*'|'/') expr # MulDiv
| expr op=('+'|'-') expr # AddSub
| INT # int
| '(' expr ')' # parens
;
...
问题:为标记的替代方法(例如 visitMulDiv)创建了访问者方法,但是缺少 2 个东西:
- 在基本访问者原型中实现
visitExpr
。 - 调用时自动检测正确的选择
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);
}
};