X-Git-Url: http://lambda.jimpryor.net/git/gitweb.cgi?p=lambda.git;a=blobdiff_plain;f=code%2Fparse.js;h=dfa06400ddbf530691b7e3389e13be994d587e58;hp=fe079dc5439ece6e9b3cf5f1c7199ed573c90ff3;hb=516417f5f9ac78553dd1788e263878ff6016f21d;hpb=42859c95fe5548d1fc3c3f5b03980b13a35ebf35 diff --git a/code/parse.js b/code/parse.js index fe079dc5..dfa06400 100644 --- a/code/parse.js +++ b/code/parse.js @@ -1,8 +1,17 @@ // Parser for lambda with let written in Simplified JavaScript -// by Jim Pryor 2010-09-22 -// Stripped down from Top Down Operator Precedence : parse.js -// http://javascript.crockford.com/tdop/index.html -// Douglas Crockford 2010-06-26 +// by Jim Pryor 2010-09-22 +// Stripped down from Top Down Operator Precedence : parse.js +// http://javascript.crockford.com/tdop/index.html +// Douglas Crockford 2010-06-26 + +/*jslint onevar: false + */ + +/* members create, error, message, name, prototype, stringify, toSource, + toString, write +*/ + +/*global make_var, make_app, make_lam, Lambda_var */ var make_parse = function () { var symbol_table = {}; @@ -24,12 +33,12 @@ var make_parse = function () { v = t.value; a = t.type; if (a === "name") { - o = symbol_table[v]; - if (o && typeof o !== 'function' ) { - a = "keyword"; - } else { - o = symbol_table["(name)"]; - } + o = symbol_table[v]; + if (o && typeof o !== 'function') { + a = "keyword"; + } else { + o = symbol_table["(name)"]; + } } else if (a === "number") { o = symbol_table["(literal)"]; a = "literal"; @@ -38,7 +47,7 @@ var make_parse = function () { if (!o) { t.error("Unknown operator."); } - a = "keyword"; + a = "keyword"; } else { t.error("Unexpected token."); } @@ -53,7 +62,7 @@ var make_parse = function () { var original_symbol = { handler: function () { this.error("Undefined."); - }, + } }; var symbol = function (id) { @@ -80,171 +89,171 @@ var make_parse = function () { return this; }; - var var_table = {}; - var name_table = {}; - - var name_handler = function () { - var n = name_table[this.value]; - if (!n) { - n = make_var(this.value); - var_table[this.value] = n; - n = new Lambda_var(n); - name_table[this.value] = n; - } - if (this.first) { - return make_app(this.first.handler(), n); - } else { - return n; - } - }; + var var_table = {}; + var name_table = {}; - var branch_handler = function () { - var n = this.second.handler(); - if (this.first) { - return make_app(this.first.handler(), n); - } else { - return n; - } - }; + var name_handler = function () { + var n = name_table[this.value]; + if (!n) { + n = make_var(this.value); + var_table[this.value] = n; + n = new Lambda_var(n); + name_table[this.value] = n; + } + if (this.first) { + return make_app(this.first.handler(), n); + } else { + return n; + } + }; - var lambda_handler = function () { - var body = this.second.handler(); - var n, v; - while (this.first.length) { - n = this.first.pop().value; - v = var_table[n]; - if (!v) { - v = make_var(n); - var_table[n] = v; - name_table[n] = new Lambda_var(v); - } - body = make_lam(v, body); - } - return body; - }; + var branch_handler = function () { + var n = this.second.handler(); + if (this.first) { + return make_app(this.first.handler(), n); + } else { + return n; + } + }; + + var lambda_handler = function () { + var body = this.second.handler(); + var n, v; + while (this.first.length) { + n = this.first.pop().value; + v = var_table[n]; + if (!v) { + v = make_var(n); + var_table[n] = v; + name_table[n] = new Lambda_var(v); + } + body = make_lam(v, body); + } + return body; + }; symbol("(end)"); - symbol("(name)").handler = name_handler; + symbol("(name)").handler = name_handler; symbol("(literal)").handler = itself; - symbol("let").handler = lambda_handler; - symbol("=").handler = branch_handler; - symbol("in"); - symbol(")").handler = branch_handler; - symbol("("); - symbol("\\").handler = lambda_handler; - symbol("lambda").handler = lambda_handler; - symbol("."); - - var expression = function (in_let) { - var t, n; - if (token.id === "\\" || token.id === "lambda") { - token.value = "lambda"; - t = token; - advance(); - n = token; - if (n.arity !== "name") { - n.error("Expected a variable name."); - } - advance(); - if (token.id === "(") { - t.first = [n]; - advance(); - t.second = expression(false); - advance(")"); - return t; - } else { - t.first = []; - while (token.arity === "name") { - t.first.push(n); - n = token; - advance(); - } - if (token.id === ".") { - t.first.push(n); - advance(); - t.second = expression(in_let); - } else if (t.first.length === 1) { - t.second = n; - } else { - t.first.push(n); - t.error("Can't parse lambda abstract."); - } - return t; - }; - } else { - n = null; - while (token.id === "(") { - advance(); - t = expression(false); - token.first = n; - token.second = t; - n = token; - advance(")"); - if (in_let && token.id === "let" || token.id === "(end)" || token.id === ")") { - return n; - } - } - if (token.arity != "name") { - token.error("Expected a variable name."); - } - token.first = n; - n = token; - advance(); - while (true) { - if (in_let && token.id === "in" || token.id === "(end)" || token.id === ")") { - return n; - } else if (token.id === "(") { - advance(); - t = expression(false); - token.first = n; - token.second = t; - n = token; - advance(")"); - } else { - if (token.arity != "name") { - token.error("Expected a variable name."); - } - token.first = n; - n = token; - advance(); - } - } - } - } + symbol("let").handler = lambda_handler; + symbol("=").handler = branch_handler; + symbol("in"); + symbol(")").handler = branch_handler; + symbol("("); + symbol("\\").handler = lambda_handler; + symbol("lambda").handler = lambda_handler; + symbol("."); + + var expression = function (in_let) { + var t, n; + if (token.id === "\\" || token.id === "lambda") { + token.value = "lambda"; + t = token; + advance(); + n = token; + if (n.arity !== "name") { + n.error("Expected a variable name."); + } + advance(); + if (token.id === "(") { + t.first = [n]; + advance(); + t.second = expression(false); + advance(")"); + return t; + } else { + t.first = []; + while (token.arity === "name") { + t.first.push(n); + n = token; + advance(); + } + if (token.id === ".") { + t.first.push(n); + advance(); + t.second = expression(in_let); + } else if (t.first.length === 1) { + t.second = n; + } else { + t.first.push(n); + t.error("Can't parse lambda abstract."); + } + return t; + } + } else { + n = null; + while (token.id === "(") { + advance(); + t = expression(false); + token.first = n; + token.second = t; + n = token; + advance(")"); + if (in_let && token.id === "let" || token.id === "(end)" || token.id === ")") { + return n; + } + } + if (token.arity !== "name") { + token.error("Expected a variable name."); + } + token.first = n; + n = token; + advance(); + while (true) { + if (in_let && token.id === "in" || token.id === "(end)" || token.id === ")") { + return n; + } else if (token.id === "(") { + advance(); + t = expression(false); + token.first = n; + token.second = t; + n = token; + advance(")"); + } else { + if (token.arity !== "name") { + token.error("Expected a variable name."); + } + token.first = n; + n = token; + advance(); + } + } + } + }; return function (source) { - tokens = source.tokens(); + tokens = source.tokens(); token_nr = 0; advance(); - - // let n = c in b - // (\n. b) c - - var t = null, eq, c, base = {}; - var target = base; - - while (token.id == "let") { - t = token; - advance(); - if (token.arity !== "name") { - token.error("Expected a variable name."); - } - t.first = [token]; - advance(); - eq = token; // token.id === "=" - advance("="); - c = expression(true); - c.first = eq; - eq.second = t; - target.second = c; - target = t; - advance("in"); - } - - target.second = expression(false); + + // let n = c in b + // (\n. b) c + + var t = null, eq, c, base = {}; + var target = base; + + while (token.id === "let") { + t = token; + advance(); + if (token.arity !== "name") { + token.error("Expected a variable name."); + } + t.first = [token]; + advance(); + eq = token; // token.id === "=" + advance("="); + c = expression(true); + c.first = eq; + eq.second = t; + target.second = c; + target = t; + advance("in"); + } + + target.second = expression(false); advance("(end)"); - return base.second; + return base.second; }; };