var add = function (a, b) { return a + b } var sub = function (a, b) { return a - b } var mul = function (a, b) { return a * b } var div = function (a, b) { return a / b } var eq = function (a, b) { return a === b } var le = function (a, b) { return a < b } var ge = function (a, b) { return a > b } var leq = function (a, b) { return a <= b } var geq = function (a, b) { return a >= b } var print = function (x) { console.log(x) } var stuck = function (msg) { throw {type:'stuck', msg:msg} } var to_string = function (x) { return String(x) } var parse = function (source) { var ast = require('esprima').parse(source).body[0].expression; // Esprima does it's little thing. To be handled by auto generated code we need to // reshape the tree structure to match the labels and expected content. function transform (tree) { if (tree === undefined) { } else { // Javascript style instructions are well handled with no additional creation. switch (tree.operator) { case '+': tree.type = "Add"; tree.operator = undefined; break; case '-': tree.type = "Sub"; tree.operator = undefined; break; case "*": tree.type = "Mul"; tree.operator = undefined; break; case "/": tree.type = "Div"; tree.operator = undefined; break; default: break; } if (tree.type === "Literal") { tree.type = "Const"; } // tree.left and tree.right from parser interpretation if (tree.left !== undefined) tree.left = transform(tree.left); if (tree.right !== undefined) tree.right = transform(tree.right); // Esprima sees these standalone type instructions as Identifiers if (tree.type === "Identifier") { switch (tree.name) { case "Emp": tree.type = "Emp"; break; default: console.log("Unknown ident"); break; } } // Esprima generates a function type structure that needs reshaping to the // automatically generated structure, respecting label names! if (tree.type === "CallExpression") { switch (tree.callee.name) { case "Push": tree.type = "Push"; tree.value = transform(tree.arguments[0]); tree.stack = transform(tree.arguments[1]); break; case "Pop": tree.type = "Pop"; tree.stack = transform(tree.arguments[0]); break; default: console.log("Unknown callexpr"); break; } } return tree; } } return transform(ast); }