import antlr4 from 'antlr4';
import TinyPLListener from './TinyPLListener.js'
class MyVisitor extends TinyPLListener {
constructor(output) {
super();
this.output = output;
this.scopes = [{}];
this.level = 0;
}
enterStatements(ctx) {
this.scopes.push({});
}
exitStatements(ctx) {
this.scopes.pop();
}
enterVariableDeclaration(ctx) {
if (this.level > 0) return;
this.scopes[this.scopes.length - 1][ctx.Identifier().getText()] = null;
}
enterAssignment(ctx) {
if (this.level > 0) return;
var value = null;
if (ctx.Number() == null) {
var variableName = ctx.Identifier(1).getText();
// get the current value of the variable by searching from inner to outer scope
for (let i = this.scopes.length - 1; i >= 0; i--) {
if (variableName in this.scopes[i]) {
value = this.scopes[i][variableName];
break;
}
}
} else {
value = ctx.Number().getText();
}
// update the value of the variable by searching from inner to outer scope
var variableName = ctx.Identifier(0).getText();
for (let i = this.scopes.length - 1; i >= 0; i--) {
if (variableName in this.scopes[i]) {
this.scopes[i][variableName] = value;
break;
}
}
}
enterFunctionDeclaration(ctx) {
this.level += 1;
this.scopes[this.scopes.length - 1][ctx.Identifier(0).getText()] = ctx.statements();
}
exitFunctionDeclaration(ctx) {
this.level -= 1;
}
enterCall(ctx) {
if (this.level > 0) return;
if (ctx.PrintKeyword() != null) {
// print function is called
var variableName = ctx.Identifier(0).getText();
// search for the variables in the scopes, starting with the most recent one (inner)
this.output.push(this.findSomethingInStack(variableName));
console.log(this.output);
} else {
// any other function call
var functionName = ctx.Identifier(0).getText();
var statements = this.findSomethingInStack(functionName);
// use the antlr4 parser to walk the statements
antlr4.tree.ParseTreeWalker.DEFAULT.walk(this, statements);
}
}
findSomethingInStack(identifier) {
for (let i = this.scopes.length - 1; i >= 0; i--) {
if (identifier in this.scopes[i]) {
return this.scopes[i][identifier];
}
}
}
}
export default class Milestone1 {
constructor(tree) {
this.tree = tree;
}
run() {
var output = [];
var treeVisitor = new MyVisitor(output);
antlr4.tree.ParseTreeWalker.DEFAULT.walk(treeVisitor, this.tree);
return output;
}
}