class PrintStmt extends Node {
constructor(loc, value) {
super(NodeType.PRINT_STMT, loc);
this.value = value;
}
}
NodeType.PRINT_STMT = "printStmt";
class Parser {
parseProg() {
// ...
while (true) {
// ...
if (tok.type === TokenType.NUMBER) stmt = this.parseExprStmt();
if (tok.type === TokenType.PRINT) stmt = this.parsePrintStmt();
node.body.push(stmt);
}
// ...
}
parsePrintStmt() {
const node = new PrintStmt();
let tok = this.lexer.next();
node.loc.start = tok.loc.start;
node.value = this.parseExpr();
node.loc.end = this.lexer.getPos();
return node;
}
}
class Visitor {
visitPrintStmt(node) {}
visitStmt(node) {
switch (node.type) {
case NodeType.EXPR_STMT:
return this.visitExprStmt(node);
case NodeType.SAY_HI:
return this.visitSayHi(node);
case NodeType.PRINT_STMT:
return this.visitPrintStmt(node);
}
}
}
class InterpretVisitor extends Visitor {
visitProg(node) {
node.body.forEach(stmt => this.visitStmt(stmt));
}
visitBinaryExpr(node) {
const left = this.visitExpr(node.left);
const op = node.op.type;
const right = this.visitExpr(node.right);
switch (op) {
case "+":
return left + right;
case "-":
return left - right;
case "*":
return left * right;
case "/":
return left / right;
case "**":
return left ** right;
}
}
visitPrintStmt(node) {
console.log(this.visitExpr(node.value));
}
visitNumLiteral(node) {
return parseInt(node.value);
}
}
const code = `print 1 + 2 ** 3 * 5`;
const src = new Source(code);
const lexer = new Lexer(src);
const parser = new Parser(lexer);
const ast = parser.parseProg();
const visitor = new InterpretVisitor();
visitor.visitProg(ast);