0
votes

I am trying to do my own language with antlr4. I manged to create my own grammar and make my own Visitor which compiles my language.

Now, I am trying to build simple GUI interface for my language. However I am quite confused with idea how to do it, or if it is even possible. Here is the situation.

My language support easy function declarations. Lets say I have simple textarea on my html page which loads my code build parser and usual antlr stuff. After this i call visitor which run my code.

    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);

My language:

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

rock()

This is working and print message to my output windows. However now I added support for buttons in my language which can call some function on click. This will create simple html button which should call function rock() on click:

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

My idea was something like this when visiting 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();
            }
        };
};

Of course, this cant work cause visitor finished its job and it is no more keeping reference about anything so this.myFunctions doesnt exist anymore. However I have no clever idea how to make this work (Except calling whole visitor process again).

Any help? Thanks a lot!

1

1 Answers

1
votes

Of course, this cant work cause visitor finished its job and it is no more keeping reference about anything so this.myFunctions doesnt exist anymore

That's not why this doesn't work. Functions can access objects from their surrounding scope and those objects will live as long as the function.

Your code doesn't work because onclick will be called on the button, so this will be the button, not your visitor. You can assign this to a variable while it still refers to the visitor (i.e. outside the onclick function) and then use that variable instead of this:

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

PS: A note on terminology: What you're writing is not a compiler. A compiler generates code in another language (often that's machine code/assembly, but in the context of the web, languages are also often compiled to JavaScript (or web assembly for non GCed languages)). Your visitor executes the code directly, making it an interpreter.