Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Antlr4 Javascript Visitor

I'm currently trying to develope a JavaScript Compiler with the help of an Antlr4 Visitor. I've got this already implemented with Java but cannot figure out how to do this in JavaScript. Probably somebody can answer me a few questions?

1: In Java there is a Visitor.visit function. If im right this isn't possibile with Javascript. Is there a work around for this?

2: My Javascript Visitor got all the generated visiting functions but when I use console.log(ctx) the context is undefined. Any idea why?

Extract from the SimpleVisitor.js:

// Visit a parse tree produced by SimpleParser#parse.
SimpleVisitor.prototype.visitParse = function(ctx) {
        console.log(ctx);
};

Main js file:

var antlr4 = require('lib/antlr4/index');
var SimpleLexer = require('antlr4/SimpleLexer');
var SimpleParser = require('antlr4/SimpleParser');
var SimpleVisitor = require('antlr4/SimpleVisitor');    

var input = "double hallo = 1;";
var chars = new antlr4.InputStream(input);
var lexer = new SimpleLexer.SimpleLexer(chars);
var tokens = new antlr4.CommonTokenStream(lexer);
var parser = new SimpleParser.SimpleParser(tokens);
var visitor = new SimpleVisitor.SimpleVisitor();
parser.buildParseTrees = true;
var tree = parser.parse();

visitor.visitParse();

This is probably enough to start with ...

Bruno

Edit:

Probably the context is undefined because I call the function without arguments but where do I get the "starting"-context?

Edit2:

So I think I get the idea how this should work out. One Question remaining how do I determine which rule to call next inside each visitor function?

like image 787
Bruno Avatar asked Feb 16 '16 14:02

Bruno


1 Answers

The basic idea behind the visitor is that you have to handle all the logic by yourself. To do this I generated the visitor using antlr. My own visitor overrides all functions that I need to implement my logic.

  1. create lexer, tokens, ...

    var antlr4 = require('antlr4/index');
    var SimpleJavaLexer = require('generated/GrammarLexer');
    var SimpleJavaParser = require('generated/GrammarParser');
    var SimpleJavaVisitor = require('generated/GrammarVisitor');
    var Visitor = require('./Visitor');
    
    var input = "TestInput";
    var chars = new antlr4.InputStream(input);
    var lexer = new GrammarLexer.GrammarLexer(chars);
    var tokens = new antlr4.CommonTokenStream(lexer);
    var parser = new GrammarParser.GrammarParser(tokens);
    var visitor = new Visitor.Visitor();
    parser.buildParseTrees = true;
    var tree = parser.parse();
    
  2. and call your entry function

    visitor.visitTest(tree);
    
  3. inside your new visitor you need to implement your new logic to determine which function to call next (the right context as argument is important)

    var GrammarVisitor =     require('generated/GrammarVisitor').GrammarVisitor;
    
    function Visitor () {
      SimpleJavaVisitor.call(this);
      return this;
    };
    
    Visitor.prototype = Object.create(GrammarVisitor.prototype);
    Visitor.prototype.constructor = Visitor;
    Visitor.prototype.visitTest = function(ctx) {
        // implement logic to determine which function to visit
        // then call next function and with the right context
        this.visitBlock(ctx.block());
    };
    

I hope you can understand my basic idea. If anybody got any questions just comment.

like image 185
Bruno Avatar answered Nov 10 '22 09:11

Bruno