Browse Source

defuck tabs in files

pull/8/head
nisstyre56 11 years ago
parent
commit
db2933031d
  1. 270
      parse.js
  2. 144
      representation.js

270
parse.js

@ -11,33 +11,33 @@ var error = require("./errors.js");
var print = console.log;
function fst(ts) {
return ts[ts.length-1];
return ts[ts.length-1];
}
function snd(ts) {
return ts[ts.length-2];
return ts[ts.length-2];
}
/*Checks if the next token is not followed by any of ``checks'' */
function notFollowedBy(tokens, checks, linenum, charnum) {
if (!fst(tokens)) {
if (!fst(tokens)) {
throw error.JSyntaxError(0,0,"unexpected end of source");
}
var nextT = fst(tokens)[0];
if (checks.some(function (x) {
if (checks.some(function (x) {
return x === nextT;
}))
return false;
else
return true;
return false;
else
return true;
}
/* returns a function that takes a parameter and
checks if it is in the array ``props''*/
function makeChecker(props) {
return function(x) {
return x && props.some(function (y) {return y(x);});
};
return function(x) {
return x && props.some(function (y) {return y(x);});
};
}
function tokTypeCheck(name) {
@ -61,43 +61,43 @@ function parseMany(parse, exprType, valid, tokens, charnum, linenum) {
"Unexpected end of source");
}
var current = fst(tokens)[0];
var results = [];
var parsed;
if (valid(fst(tokens))) {
parsed = parse(tokens);
}
else {
throw error.JSyntaxError(linenum,
var results = [];
var parsed;
if (valid(fst(tokens))) {
parsed = parse(tokens);
}
else {
throw error.JSyntaxError(linenum,
charnum,
"Unexpected token: ``"+fst(tokens)[0]+"''");
}
}
results.push(parsed);
//make sure there are at least 2 tokens to parse
if (tokens.length > 1 && fst(tokens) && valid(fst(tokens))) {
while (valid(snd(tokens))) {
if (!(valid(fst(tokens))))
//make sure there are at least 2 tokens to parse
if (tokens.length > 1 && fst(tokens) && valid(fst(tokens))) {
while (valid(snd(tokens))) {
if (!(valid(fst(tokens))))
break;
results.push(parse(tokens));
if (!exprType(fst(results).exprType))
break;
if (fst(tokens))
if (!exprType(fst(results).exprType))
break;
if (fst(tokens))
current = fst(tokens)[0];
else
throw error.JSyntaxError(charnum, linenum, "Unexpected end of source");
if (tokens.length <= 1)
break;
}
}
//do the same validity check as before and in the loop
if (tokens.length <= 1)
break;
}
}
//do the same validity check as before and in the loop
if (!fst(tokens))
throw error.JSyntaxError(linenum,
charnum,
"unexpected end of source");
if (valid(fst(tokens)))
results.push(parse(tokens));
return results;
if (valid(fst(tokens)))
results.push(parse(tokens));
return results;
}
@ -149,7 +149,7 @@ function parseList(tokens) {
function parseDefFunction(tokens) {
var fname = parse(tokens);
var fname = parse(tokens);
var parameters;
if (fname.exprType != "Name") {
throw error.JSyntaxError(fst(tokens)[3],
@ -285,7 +285,7 @@ function parseLetBinding(tokens, linenum, charnum) {
charnum,
"A definition cannot be the value of a binding");
}
return new typ.Def(name, bound);
return new typ.Def(name, bound);
}
function parseLetItem(tokens) {
@ -321,12 +321,12 @@ function parseDef(tokens, linenum, charnum) {
fst(tokens)[2]);
}
if (notFollowedBy(tokens, ["identifier"], linenum, charnum)) {
throw error.JSyntaxError(linenum,
if (notFollowedBy(tokens, ["identifier"], linenum, charnum)) {
throw error.JSyntaxError(linenum,
charnum,
"def must be followed by identifier, not "+fst(tokens)[0]);
}
else {
}
else {
var identifier = parse(tokens);
if (!fst(tokens))
throw error.JSyntaxError(linenum,
@ -349,8 +349,8 @@ function parseDef(tokens, linenum, charnum) {
charnum,
"A definition cannot be the value of a binding");
}
return new typ.Def(identifier, bound);
}
return new typ.Def(identifier, bound);
}
}
function parseDefOp(tokens, linenum, charnum) {
@ -402,35 +402,35 @@ function parseDefOp(tokens, linenum, charnum) {
function parseIf(tokens) {
var linenum = fst(tokens)[3];
var charnum = fst(tokens)[2];
if (!notFollowedBy(tokens,
if (!notFollowedBy(tokens,
["def","comma","lambda"],
linenum,
charnum)) {
throw error.JSyntaxError(linenum,
throw error.JSyntaxError(linenum,
charnum,
"``if'' cannot be followed by "+fst(tokens)[0]) ;
}
else {
var ifC = parse(tokens);
if (!fst(tokens) || fst(tokens)[0] !== "thenexp") {
throw error.JSyntaxError(fst(tokens)[3],
}
else {
var ifC = parse(tokens);
if (!fst(tokens) || fst(tokens)[0] !== "thenexp") {
throw error.JSyntaxError(fst(tokens)[3],
fst(tokens)[2],
"if ``exp'' must be folowed by ``then'' exp, not "+snd(tokens)[0]);
}
else {
tokens.pop();
var thenC = parse(tokens);
else {
tokens.pop();
var thenC = parse(tokens);
if (fst(tokens) && fst(tokens)[0] === "elsexp") {
tokens.pop();
if (fst(tokens) && fst(tokens)[0] === "elsexp") {
tokens.pop();
if (_.size(tokens) < 1) {
throw error.JSyntaxError(linenum,
charnum,
"Unexpected end of source");
}
else {
var elseC = parse(tokens);
return new typ.If(ifC, thenC, elseC);
var elseC = parse(tokens);
return new typ.If(ifC, thenC, elseC);
}
}
else {
@ -452,20 +452,20 @@ function validFormPar(tok) {
function parseLambda(tokens) {
var linenum = fst(tokens)[2];
var charnum = fst(tokens)[3];
var parameters = parseMany(parse,
var parameters = parseMany(parse,
validName,
validFormPar,
tokens,
charnum,
linenum);
if (fst(tokens)[1] !== "->") {
throw error.JSyntaxError(fst(tokens)[3],
if (fst(tokens)[1] !== "->") {
throw error.JSyntaxError(fst(tokens)[3],
fst(tokens)[2],
"arrow must follow parameters in lambda, not "+fst(tokens)[0]);
}
tokens.pop();
var body = parse(tokens);
return new typ.FuncT(parameters, body);
}
tokens.pop();
var body = parse(tokens);
return new typ.FuncT(parameters, body);
}
var invalidArguments = ["def", "comma", "right_paren", "right_square", "right_brace", "left_brace", "right_brace"].map(tokTypeCheck);
@ -477,31 +477,31 @@ function computeApp(tokens, charnum, linenum) {
var lhs = parse(tokens);
var next;
var result;
if (fst(tokens)) {
next = fst(tokens);
if (fst(tokens)) {
next = fst(tokens);
}
else {
throw error.JSyntaxError(linenum,
else {
throw error.JSyntaxError(linenum,
charnum,
"Unexpected end of source");
}
if (typ.OPInfo[next[1]]) {
/* it's an infix expression */
result = parseInfix(tokens, 1, lhs, linenum, charnum);
if (!fst(tokens) || fst(tokens)[0] !== "right_paren") {
throw error.JSyntaxError(linenum,
}
if (typ.OPInfo[next[1]]) {
/* it's an infix expression */
result = parseInfix(tokens, 1, lhs, linenum, charnum);
if (!fst(tokens) || fst(tokens)[0] !== "right_paren") {
throw error.JSyntaxError(linenum,
charnum,
"Mismatched parentheses or missing parenthesis on right-hand side");
}
else {
}
else {
tokens.pop();
return result;
}
}
else {
/* it's a prefix application */
return result;
}
}
else {
/* it's a prefix application */
var parameters;
if (fst(tokens)[0] !== "right_paren") {
if (fst(tokens)[0] !== "right_paren") {
parameters = parseMany(parse,
validArgTypes,
validArgument,
@ -512,16 +512,16 @@ function computeApp(tokens, charnum, linenum) {
else {
parameters = [];
}
if ((!fst(tokens)) || fst(tokens)[0] !== "right_paren") {
throw error.JSyntaxError(linenum,
if ((!fst(tokens)) || fst(tokens)[0] !== "right_paren") {
throw error.JSyntaxError(linenum,
charnum,
"Mismatched parentheses or missing parenthesis on right-hand side");
}
else {
}
else {
tokens.pop();
return typ.makeApp(lhs, parameters);
}
}
return typ.makeApp(lhs, parameters);
}
}
}
/*Parses infix expressions by precedence climbing
@ -529,81 +529,81 @@ function computeApp(tokens, charnum, linenum) {
http://eli.thegreenplace.net/2012/08/02/parsing-expressions-by-precedence-climbing/
*/
function parseInfix(tokens, minPrec, lhs, linenum, charnum) {
if (!lhs) {
lhs = parse(tokens);
}
while (true) {
var cur = fst(tokens);
if (!cur) {
throw error.JSyntaxError(linenum,
if (!lhs) {
lhs = parse(tokens);
}
while (true) {
var cur = fst(tokens);
if (!cur) {
throw error.JSyntaxError(linenum,
charnum,
"Unexpected end of source");
}
var opinfo = typ.OPInfo[cur[1]];
if (!opinfo || opinfo[0] < minPrec)
break;
var op = new typ.Name(cur[1]);
var prec = opinfo[0];
var assoc = opinfo[1];
var nextMinPrec = assoc === "Left" ? prec + 1 : prec;
tokens.pop();
/*remove the operator token*/
var rhs = parseInfix(tokens, nextMinPrec);
lhs = typ.makeApp(op, [lhs, rhs]);
}
return lhs;
}
var opinfo = typ.OPInfo[cur[1]];
if (!opinfo || opinfo[0] < minPrec)
break;
var op = new typ.Name(cur[1]);
var prec = opinfo[0];
var assoc = opinfo[1];
var nextMinPrec = assoc === "Left" ? prec + 1 : prec;
tokens.pop();
/*remove the operator token*/
var rhs = parseInfix(tokens, nextMinPrec);
lhs = typ.makeApp(op, [lhs, rhs]);
}
return lhs;
}
function parse(tokens) {
var charnum = fst(tokens)[2];
var linenum = fst(tokens)[3];
var toktype;
if (fst(tokens)) {
toktype = fst(tokens)[0];
if (fst(tokens)) {
toktype = fst(tokens)[0];
}
else {
process.exit(code=1);
}
var token = fst(tokens)[1];
tokens.pop();
if (toktype === "stringlit") {
return new typ.StrT(token);
else {
process.exit(code=1);
}
var token = fst(tokens)[1];
tokens.pop();
if (toktype === "stringlit") {
return new typ.StrT(token);
}
else if (toktype === "left_square") {
return parseList(tokens);
}
else if (toktype === "lambda") {
return parseLambda(tokens);
else if (toktype === "lambda") {
return parseLambda(tokens);
}
else if (toktype === "integer") {
return new typ.IntT(token);
else if (toktype === "integer") {
return new typ.IntT(token);
}
else if (toktype === "float") {
return new typ.FloatT(token);
else if (toktype === "float") {
return new typ.FloatT(token);
}
else if (toktype === "identifier") {
else if (toktype === "identifier") {
return new typ.Name(token);
}
else if (toktype === "constructor") {
return new typ.TypeOp(token);
}
else if (toktype === "truelit" || toktype === "falselit") {
return new typ.BoolT(token);
else if (toktype === "truelit" || toktype === "falselit") {
return new typ.BoolT(token);
}
else if (toktype === "def" ||
else if (toktype === "def" ||
toktype === "let") {
return parseDef(tokens, fst(tokens)[3], fst(tokens)[2]);
return parseDef(tokens, fst(tokens)[3], fst(tokens)[2]);
}
else if (toktype === "defop") {
return parseDefOp(tokens, fst(tokens)[3], fst(tokens)[2]);
}
else if (toktype === "ifexp") {
return parseIf(tokens);
else if (toktype === "ifexp") {
return parseIf(tokens);
}
else if (toktype === "left_paren") {
if (fst(tokens)[0] === "lambda") {
else if (toktype === "left_paren") {
if (fst(tokens)[0] === "lambda") {
tokens.pop();
var parsed = parseLambda(tokens);
tokens.pop();

144
representation.js

@ -2,26 +2,26 @@ var errors = require("./errors.js");
var _ = require("underscore");
var Expression = {
display :
function() {
return this.exprType + " " + this.val;
},
type :
function () {
return this.exprType;
}
display :
function() {
return this.exprType + " " + this.val;
},
type :
function () {
return this.exprType;
}
};
var TypeExpression = {
unify :
function (t) {
if (this.expr === t.expr) {
return t.expr;
}
else {
console.log("Could not unify " + this.expr + " with " + t.expr);
}
},
function (t) {
if (this.expr === t.expr) {
return t.expr;
}
else {
console.log("Could not unify " + this.expr + " with " + t.expr);
}
},
isTypeExpr : true
};
@ -62,46 +62,46 @@ function UnaryOp(op, v) {
UnaryOp.prototype = Expression;
function IntT(v) {
this.exprType = "Integer";
this.val = parseInt(v, 10);
return this;
this.exprType = "Integer";
this.val = parseInt(v, 10);
return this;
}
IntT.prototype = Expression;
function FloatT(v) {
this.exprType = "Float";
this.val = parseFloat(v, 10);
return this;
this.exprType = "Float";
this.val = parseFloat(v, 10);
return this;
}
FloatT.prototype = Expression;
function StrT(v) {
this.exprType = "String";
this.val = v;
return this;
this.exprType = "String";
this.val = v;
return this;
}
StrT.prototype = Expression;
function BoolT(b) {
if (b === "true") {
this.val = true;
}
else {
this.val = false;
}
this.exprType = "Bool";
return this;
if (b === "true") {
this.val = true;
}
else {
this.val = false;
}
this.exprType = "Bool";
return this;
}
BoolT.prototype = Expression;
function ListT(xs) {
this.xs = xs;
this.val = xs;
this.exprType = "List";
return this;
this.xs = xs;
this.val = xs;
this.exprType = "List";
return this;
}
function Nil() {
@ -113,47 +113,47 @@ Nil.prototype = Expression;
ListT.prototype = Expression;
function FuncT(p, body) {
this.p = p;
this.body = body;
this.val = [p, body];
this.exprType = "Function";
return this;
this.p = p;
this.body = body;
this.val = [p, body];
this.exprType = "Function";
return this;
}
FuncT.prototype = Expression;
//Wrapper for function objects
function OpT(operator) {
this.op = operator;
this.val = this.op;
this.exprType = "Function";
return this;
this.op = operator;
this.val = this.op;
this.exprType = "Function";
return this;
}
OpT.prototype = Expression;
// Applications separate from other types
function App(func, p) {
this.func = func;
this.exprType = "Application";
if (p)
this.p = p;
return this;
this.func = func;
this.exprType = "Application";
if (p)
this.p = p;
return this;
}
// Names are not types
function Name(identifier) {
this.ident = identifier;
this.val = this.ident;
this.exprType = "Name";
return this;
this.ident = identifier;
this.val = this.ident;
this.exprType = "Name";
return this;
}
function Def(ident, exp) {
this.ident = ident;
this.val = exp;
this.exprType = "Definition";
return this;
this.ident = ident;
this.val = exp;
this.exprType = "Definition";
return this;
}
function DefFunc(ident, params, body) {
@ -166,11 +166,11 @@ function DefFunc(ident, params, body) {
}
function If(condition, thenexp, elseexp) {
this.condition = condition;
this.thenexp = thenexp;
this.elseexp = elseexp;
this.exprType = "If";
return this;
this.condition = condition;
this.thenexp = thenexp;
this.elseexp = elseexp;
this.exprType = "If";
return this;
}
function TypeVar(name) {
@ -221,14 +221,14 @@ TypeApp.prototype = TypeExpression;
//Applies the function ``name'' to the list of parameters
function makeApp(name, parameters) {
if (parameters) {
return parameters.slice(1).reduce(function(f, ident) {
return new App(f, ident);
}, new App(name, parameters[0]));
}
else {
return new App(name);
}
if (parameters) {
return parameters.slice(1).reduce(function(f, ident) {
return new App(f, ident);
}, new App(name, parameters[0]));
}
else {
return new App(name);
}
}
function makeGensym() {

Loading…
Cancel
Save