I was writing antlr4 parser, using target language JavaScript, and I need to use visitor to get custom output from my tree (one array, every tree level on other array level). But I get some troubles with returning values from visit functions, when I try to return value from every visit function I get result wrapped in array (I don't need this). I tried to debug my code, but I can't truely see a code part in antlr4 library when this array is created (probably when accept function return a value, accept called inside visitChildren method). I have default operations that work as a chain until value match with concrete operation (expression -> relation -> add -> mult -> etc.).
visitor.js:
visitFormula(ctx) {
let result = [];
for (let i = 1; i < ctx.getChildCount() - 1; i++) {
let part = this.visit(ctx.getChild(i));
result.push(part);
}
console.log("formula " + JSON.stringify(result));
return result;
}
// Visit a parse tree produced by MyGrammarParser#expo.
visitExpo(ctx) {
let result = this.visitChildren(ctx);
console.log("expo " + JSON.stringify(result));
return result;
}
// Visit a parse tree produced by MyGrammarParser#unary.ex
visitUnary(ctx) {
let result = this.visitChildren(ctx);
console.log("unary " + JSON.stringify(result));
return result;
}
// Visit a parse tree produced by MyGrammarParser#mult.
visitMult(ctx) {
let result = this.visitChildren(ctx);
console.log("mult " + JSON.stringify(result));
return result;
}
// Visit a parse tree produced by MyGrammarParser#add.
visitAdd(ctx) {
let result = this.visitChildren(ctx);
console.log("add " + JSON.stringify(result));
return result;
}
visitTerm(ctx) {
if (this.isTerminalNode(ctx)) {
console.log("term " + JSON.stringify(ctx.getText()));
return ctx.getText();
}
let result = this.visitChildren(ctx);
console.log("term " + JSON.stringify(result));
return result;
}
visitFunction(ctx) {
let result = [ctx.FUNCTION_NAME().getText()];
const expressionList = ctx.expression();
for (let i = 0; i < expressionList.length; i++) {
console.log("FUNC ARGS", expressionList[i].getText());
let part = this.visit(expressionList[i]);
result.push(part);
}
console.log("function " + JSON.stringify(result));
return result;
}
parser.g4:
formula : ST expression EOF;
expo: unary (CARRET unary)*;
unary : (ADD | negation)* term;
negation : SUB;
mult : expo ((MUL | DIV) expo)*;
add : mult ((ADD | SUB) mult)*;
relation
: add (RELATION_SYMBOL add)*
;
expression
: relation ((AND | OR) relation)*
;
function
: FUNCTION_NAME OPEN_ROUND_BRACKET (expression (COMMA expression)*)? CLOSE_ROUND_BRACKET
;
term : function | INTEGER | DECIMAL | PERCENT | reference | OPEN_ROUND_BRACKET expression CLOSE_ROUND_BRACKET;
index.js:
const formula = "=IF($I$11=D169,1,0)";
var chars = new InputStream(formula, true);
var lexer = new MyGrammarLexer(chars);
var tokens = new CommonTokenStream(lexer);
var parser = new MyGrammarParser(tokens);
const tree = parser.formula();
const visitor = new GrammarParserVisitor(); // FormulaWalker
let res = visitor.visitFormula(tree);
console.log(JSON.stringify(res));
I can show part of the result (when visting this input's =IF($I$11=D169,1,0) third parameter), that i get from console.log in visit functions:
term "0"
unary ["0"]
expo [["0"]]
mult [[["0"]]]
add [[[["0"]]]]
relation [[[[["0"]]]]]
But I need just to return string without wrapping it in arrays. Why I get this problem and how can I fix it?
Here's a start for a visitor in JavaScript. I simplified your grammar a little bit (yes, know this is not correct, but this is just a demo):
A visitor might look like this:
which can be tested with the following
main.js:My
package.jsonlooks like this:If you now run this file with
npm run start, you will see this on your console: