Browse Source

Merge pull request #5 from oftn/master

refactor parseMany function to accept general functions rather than stri...
pull/21/head
Wesley Kerfoot 11 years ago
parent
commit
40287e4d7a
  1. 4
      closure_conversion.js
  2. 81
      parse.js

4
closure_conversion.js

@ -151,8 +151,8 @@ function test(src) {
console.log(JSON.stringify(closure_convert_all(ast), null, 4)); console.log(JSON.stringify(closure_convert_all(ast), null, 4));
} }
//console.log(test(pprint.pprint(parser.parse(pprint.pprint(parser.parse("if something then if a then if b then c else d else rtrrt else some_other_thing")[0]))[0]))); console.log(pprint.pprint(parser.parse(pprint.pprint(parser.parse("if something then if a then if b then c else d else rtrrt else some_other_thing")[0]))[0]));
//console.log(pprint.pprint(parser.parse("def main (print let { a = def {f = (lambda a b -> (a+b))} f} (a 2 3))")[0])); console.log(pprint.pprint(parser.parse("def main (print let { a = def {f = (lambda a b -> (a+b))} f} (a 2 3))")[0]));
module.export = { module.export = {
test : test, test : test,
closureConvert : closure_convert_all closureConvert : closure_convert_all

81
parse.js

@ -36,10 +36,22 @@ function notFollowedBy(tokens, checks, linenum, charnum) {
checks if it is in the array ``props''*/ checks if it is in the array ``props''*/
function makeChecker(props) { function makeChecker(props) {
return function(x) { return function(x) {
return x && props.some(function (y) {return y === x;}); return x && props.some(function (y) {return y(x);});
}; };
} }
function tokTypeCheck(name) {
return function(tok) {
return tok[0] === name;
};
}
function formTypeCheck(stxtype) {
return function(stx) {
return stx.exprType === stxtype;
};
}
/*Tries to parse until the prediction ``valid'' fails or the wrong type is parsed /*Tries to parse until the prediction ``valid'' fails or the wrong type is parsed
Collects the results into an array and returns it*/ Collects the results into an array and returns it*/
function parseMany(parse, exprType, valid, tokens, charnum, linenum) { function parseMany(parse, exprType, valid, tokens, charnum, linenum) {
@ -52,7 +64,7 @@ function parseMany(parse, exprType, valid, tokens, charnum, linenum) {
var results = []; var results = [];
var parsed; var parsed;
if (valid(fst(tokens)[0])) { if (valid(fst(tokens))) {
parsed = parse(tokens); parsed = parse(tokens);
} }
else { else {
@ -63,9 +75,9 @@ function parseMany(parse, exprType, valid, tokens, charnum, linenum) {
results.push(parsed); results.push(parsed);
//make sure there are at least 2 tokens to parse //make sure there are at least 2 tokens to parse
if (tokens.length > 1 && fst(tokens) && valid(fst(tokens)[0])) { if (tokens.length > 1 && fst(tokens) && valid(fst(tokens))) {
while (valid(snd(tokens)[0])) { while (valid(snd(tokens))) {
if (!(valid(fst(tokens)[0]))) if (!(valid(fst(tokens))))
break; break;
results.push(parse(tokens)); results.push(parse(tokens));
if (!exprType(fst(results).exprType)) if (!exprType(fst(results).exprType))
@ -83,7 +95,7 @@ function parseMany(parse, exprType, valid, tokens, charnum, linenum) {
throw error.JSyntaxError(linenum, throw error.JSyntaxError(linenum,
charnum, charnum,
"unexpected end of source"); "unexpected end of source");
if (valid(fst(tokens)[0])) if (valid(fst(tokens)))
results.push(parse(tokens)); results.push(parse(tokens));
return results; return results;
} }
@ -149,11 +161,11 @@ function parseDefFunction(tokens) {
} }
else { else {
parameters = parseMany(parse, parameters = parseMany(parse,
validName, validName,
validFormPar, validFormPar,
tokens, tokens,
fst(tokens)[2], fst(tokens)[2],
fst(tokens)[3]); fst(tokens)[3]);
} }
if ((fst(tokens)[0]) !== "right_paren") { if ((fst(tokens)[0]) !== "right_paren") {
throw error.JSyntaxError(fst(tokens)[3], throw error.JSyntaxError(fst(tokens)[3],
@ -165,8 +177,8 @@ function parseDefFunction(tokens) {
return new typ.DefFunc(fname, parameters, body); return new typ.DefFunc(fname, parameters, body);
} }
validLet = makeChecker(["Definition", "FunctionDefinition"]); validLet = makeChecker(["Definition", "FunctionDefinition"].map(formTypeCheck));
letEnd = _.compose($.not, makeChecker(["right_brace"])); letEnd = _.compose($.not, makeChecker(["right_brace"].map(tokTypeCheck)));
function parseLetForm(tokens, linenum, charnum) { function parseLetForm(tokens, linenum, charnum) {
if (!fst(tokens)) { if (!fst(tokens)) {
@ -223,11 +235,11 @@ function parseLetFunction(tokens, linenum, charnum) {
} }
else { else {
parameters = parseMany(parse, parameters = parseMany(parse,
validName, validName,
validFormPar, validFormPar,
tokens, tokens,
fst(tokens)[2], fst(tokens)[2],
fst(tokens)[3]); fst(tokens)[3]);
} }
if ((fst(tokens)[0]) !== "right_paren") { if ((fst(tokens)[0]) !== "right_paren") {
throw error.JSyntaxError(fst(tokens)[3], throw error.JSyntaxError(fst(tokens)[3],
@ -235,7 +247,7 @@ function parseLetFunction(tokens, linenum, charnum) {
"Formal parameters must be followed by )"); "Formal parameters must be followed by )");
} }
tokens.pop(); tokens.pop();
if (fst(tokens)[0] !== "arrow") { if (fst(tokens)[1] !== "->") {
throw error.JSyntaxError(fst(tokens)[3], throw error.JSyntaxError(fst(tokens)[3],
fst(tokens)[2], fst(tokens)[2],
"Function parameters in let/def form must be followed by ->"); "Function parameters in let/def form must be followed by ->");
@ -430,19 +442,23 @@ function parseIf(tokens) {
} }
} }
var validName = makeChecker(["Name"].map(formTypeCheck));
var validFormPar = makeChecker(["identifier"]); function validFormPar(tok) {
var validName = makeChecker(["Name"]); return tok[0] === "identifier" &&
tok[1] !== "->";
}
function parseLambda(tokens) { function parseLambda(tokens) {
var linenum = fst(tokens)[2];
var charnum = fst(tokens)[3];
var parameters = parseMany(parse, var parameters = parseMany(parse,
validName, validName,
validFormPar, validFormPar,
tokens, tokens,
fst(tokens)[2], charnum,
fst(tokens)[3]); linenum);
if (fst(tokens)[1] !== "->") {
if (fst(tokens)[0] !== "arrow") {
throw error.JSyntaxError(fst(tokens)[3], throw error.JSyntaxError(fst(tokens)[3],
fst(tokens)[2], fst(tokens)[2],
"arrow must follow parameters in lambda, not "+fst(tokens)[0]); "arrow must follow parameters in lambda, not "+fst(tokens)[0]);
@ -452,10 +468,9 @@ function parseLambda(tokens) {
return new typ.FuncT(parameters, body); return new typ.FuncT(parameters, body);
} }
var invalidArguments = ["def", "comma", "right_paren", "right_square", "right_brace", "left_brace", "right_brace"]; var invalidArguments = ["def", "comma", "right_paren", "right_square", "right_brace", "left_brace", "right_brace"].map(tokTypeCheck);
var validArgument = _.compose($.not, makeChecker(invalidArguments)); var validArgument = _.compose($.not, makeChecker(invalidArguments));
var validArgTypes = _.compose($.not, makeChecker(["Definition"])); var validArgTypes = _.compose($.not, makeChecker(["Definition"].map(formTypeCheck)));
var validOperator = makeChecker(["identifier"]);
/* Parses function application (either infix or prefix) */ /* Parses function application (either infix or prefix) */
function computeApp(tokens, charnum, linenum) { function computeApp(tokens, charnum, linenum) {
@ -488,11 +503,11 @@ function computeApp(tokens, charnum, linenum) {
var parameters; var parameters;
if (fst(tokens)[0] !== "right_paren") { if (fst(tokens)[0] !== "right_paren") {
parameters = parseMany(parse, parameters = parseMany(parse,
validArgTypes, validArgTypes,
validArgument, validArgument,
tokens, tokens,
charnum, charnum,
linenum); linenum);
} }
else { else {
parameters = []; parameters = [];

Loading…
Cancel
Save