首页 > 解决方案 > Antlr4 基于事件的访问者 (javascript)

问题描述

我正在尝试用 antlr4 做我自己的语言。我设法创建了自己的语法并创建了自己的访问者来编译我的语言。

现在,我正在尝试为我的语言构建简单的 GUI 界面。但是,我对如何做到这一点感到很困惑,或者是否有可能。这是情况。

我的语言支持简单的函数声明。假设我的 html 页面上有简单的 textarea,它加载了我的代码构建解析器和通常的 antlr 东西。在此之后,我调用运行我的代码的访问者。

    var chars = new antlr4.InputStream(inputText);
    var lexer = new TinyLexer(chars);
    var tokens = new antlr4.CommonTokenStream(lexer);
    var parser = new TinyParser(tokens);
    parser.buildParseTrees = true;
    var tree = parser.parse();
    var visitor = new Visitor();
    visitor.visit(tree);

我的语言:

def rock()
 println("You selected ROCK")
end

rock()

这是工作并将消息打印到我的输出窗口。但是现在我添加了对我的语言的按钮的支持,这些按钮可以在点击时调用一些功能。这将创建一个简单的 html 按钮,该按钮应在单击时调用函数 rock():

Button btn1("MyButton", "rock()")

访问 newButtonCall 时我的想法是这样的

Visitor.prototype.visitNewButtonCall = function (ctx) {
    var buttonId = ctx.Identifier().getText();
    var buttonName = this.visit(ctx.exprList().expression(0));
    var buttonFunction = this.visit(ctx.exprList().expression(1));

    var button = document.createElement('button');
    button.onclick = function(){
            if(buttonFunction in this.myFunctions){
                return this.myFunctions[buttonFunction].invoke();
            }
        };
};

当然,这无法正常工作,因为访问者完成了它的工作,并且不再保留对任何内容的引用,因此 this.myFunctions 不再存在。但是我不知道如何使这项工作(除了再次调用整个访问者进程)。

有什么帮助吗?非常感谢!

标签: javascripteventsantlrantlr4visitor-pattern

解决方案


当然,这无法正常工作,因为访问者完成了它的工作,并且不再保留对任何内容的引用,因此 this.myFunctions 不再存在

这不是为什么这不起作用。函数可以从其周围范围访问对象,并且这些对象将与函数一样存在。

您的代码不起作用,因为onclick将在按钮上调用,因此this将是按钮,而不是您的访问者。您可以this在变量仍然引用访问者(即在onclick函数外部)时分配给变量,然后使用该变量而不是this

var visitor = this;
button.onclick = function(){
    if(buttonFunction in visitor.myFunctions){
        return visitor.myFunctions[buttonFunction].invoke();
    }
};

PS:关于术语的说明:您正在编写的不是编译器。编译器生成另一种语言的代码(通常是机器代码/程序集,但在 Web 的上下文中,语言也经常被编译为 JavaScript(或非 GCed 语言的 Web 程序集))。您的访问者直接执行代码,使其成为解释器。


推荐阅读