Skip to content

Instantly share code, notes, and snippets.

@SauloSilva
Last active August 29, 2015 14:10
Show Gist options
  • Save SauloSilva/7bef8ec6e6f9abd9529a to your computer and use it in GitHub Desktop.
Save SauloSilva/7bef8ec6e6f9abd9529a to your computer and use it in GitHub Desktop.
egg.js mini language
function parseExpression(program) {
program = skipSpace(program);
var match, expr;
if (match = /^"([^"]*)"/.exec(program))
expr = {type: "value", value: match[1]};
else if (match = /^\d+\b/.exec(program))
expr = {type: "value", value: Number(match[0])};
else if (match = /^[^\s(),"]+/.exec(program))
expr = {type: "word", name: match[0]};
else
throw new SyntaxError("Unexpected syntax: " + program);
return parseApply(expr, program.slice(match[0].length));
}
/*
--------------------------------
--------------------------------
--------------------------------
Inicio do exercício 3 - Comentários do livro eloquent javascript
--------------------------------
--------------------------------
--------------------------------
*/
function skipSpace(string) {
var first = string.search(/\S/);
var commentRegex = /\#.*\n/gi; // add var comment regex
if (first == -1) return "";
return string.slice(first).replace(commentRegex, '') // change here
}
/*
--------------------------------
--------------------------------
--------------------------------
Final do exercício 3 - Comentários do livro eloquent javascript
--------------------------------
--------------------------------
--------------------------------
*/
function parseApply(expr, program) {
program = skipSpace(program);
if (program[0] != "(")
return {expr: expr, rest: program};
program = skipSpace(program.slice(1));
expr = {type: "apply", operator: expr, args: []};
while (program[0] != ")") {
var arg = parseExpression(program);
expr.args.push(arg.expr);
program = skipSpace(arg.rest);
if (program[0] == ",")
program = skipSpace(program.slice(1));
else if (program[0] != ")")
throw new SyntaxError("Expected ',' or ')'");
}
return parseApply(expr, program.slice(1));
}
function parse(program) {
var result = parseExpression(program);
if (skipSpace(result.rest).length > 0)
throw new SyntaxError("Unexpected text after program");
return result.expr;
}
function evaluate(expr, env) {
switch(expr.type) {
case "value":
return expr.value;
case "word":
if (expr.name in env)
return env[expr.name];
else
throw new ReferenceError("Undefined variable: " +
expr.name);
case "apply":
if (expr.operator.type == "word" &&
expr.operator.name in specialForms)
return specialForms[expr.operator.name](expr.args,
env);
var op = evaluate(expr.operator, env);
if (typeof op != "function")
throw new TypeError("Applying a non-function.");
return op.apply(null, expr.args.map(function(arg) {
return evaluate(arg, env);
}));
}
}
var specialForms = Object.create(null);
specialForms["if"] = function(args, env) {
if (args.length != 3)
throw new SyntaxError("Bad number of args to if");
if (evaluate(args[0], env) !== false)
return evaluate(args[1], env);
else
return evaluate(args[2], env);
};
specialForms["while"] = function(args, env) {
if (args.length != 2)
throw new SyntaxError("Bad number of args to while");
while (evaluate(args[0], env) !== false)
evaluate(args[1], env);
// Since undefined does not exist in Egg, we return false,
// for lack of a meaningful result.
return false;
};
specialForms["do"] = function(args, env) {
var value = false;
args.forEach(function(arg) {
value = evaluate(arg, env);
});
return value;
};
specialForms["define"] = function(args, env) {
if (args.length != 2 || args[0].type != "word")
throw new SyntaxError("Bad use of define");
var value = evaluate(args[1], env);
env[args[0].name] = value;
return value;
};
specialForms["fun"] = function(args, env) {
if (!args.length)
throw new SyntaxError("Functions need a body");
function name(expr) {
if (expr.type != "word")
throw new SyntaxError("Arg names must be words");
return expr.name;
}
var argNames = args.slice(0, args.length - 1).map(name);
var body = args[args.length - 1];
return function() {
if (arguments.length != argNames.length)
throw new TypeError("Wrong number of arguments");
var localEnv = Object.create(env);
for (var i = 0; i < arguments.length; i++)
localEnv[argNames[i]] = arguments[i];
return evaluate(body, localEnv);
};
};
/*
--------------------------------
--------------------------------
--------------------------------
Inicio do exercício 4 - Corrigindo o escopo do livro eloquent javascript
--------------------------------
--------------------------------
--------------------------------
*/
specialForms["set"] = function(args, env) {
var prototypes = Object.getPrototypeOf(env);
do {
if (Object.hasOwnProperty.call(prototypes, args[0].name)) {
prototypes[args[0].name] = env.val
break;
} else {
throw('Some kind of ReferenceError')
}
prototypes = Object.getPrototypeOf(prototypes);
} while(prototypes != null)
};
/*
--------------------------------
--------------------------------
--------------------------------
Inicio do exercício 4 - Corrigindo o escopo do livro eloquent javascript
--------------------------------
--------------------------------
--------------------------------
*/
var topEnv = Object.create(null);
topEnv["true"] = true;
topEnv["false"] = false;
["+", "-", "*", "/", "==", "<", ">"].forEach(function(op) {
topEnv[op] = new Function("a, b", "return a " + op + " b;");
});
topEnv["print"] = function(value) {
console.log(value);
return value;
};
/*
--------------------------------
--------------------------------
--------------------------------
Inicio exercício 1 - Array do livro eloquent javascript
--------------------------------
--------------------------------
--------------------------------
*/
topEnv["array"] = function() {
return Array.prototype.slice.call(arguments);
}
topEnv["length"] = function(array) {
return array instanceof Array ? array.length : 0;
}
topEnv["element"] = function(array, element) {
return array[element];
};
/*
--------------------------------
--------------------------------
--------------------------------
Final do exercício 1 - Array do livro eloquent javascript
--------------------------------
--------------------------------
--------------------------------
*/
function run() {
var env = Object.create(topEnv);
var program = Array.prototype.slice
.call(arguments, 0).join("\n");
return evaluate(parse(program), env);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment