Browse Source

quick update

pull/1/head
Wesley Kerfoot 11 years ago
parent
commit
8257dceac9
  1. 59
      parse.js
  2. 2
      test.jl

59
parse.js

@ -18,20 +18,22 @@ 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'' /*Checks if the next token is not followed by any of ``checks'' */
function notFollowedBy(tokens, checks) { function notFollowedBy(tokens, checks, linenum, charnum) {
if (!fst(tokens)) { if (!fst(tokens)) {
throw error.JSyntaxError(0,0,"unexpected end of source") throw error.JSyntaxError(0,0,"unexpected end of source")
} }
var nextT = fst(tokens)[0]; var nextT = fst(tokens)[0];
if (checks.some(function (x) {return x === nextT;})) if (checks.some(function (x) {
return x === nextT;
}))
return false; return false;
else else
return true; return true;
} }
//returns a function that takes a parameter and /* returns a function that takes a parameter and
//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;});
@ -65,7 +67,6 @@ function parseMany(exprType, valid, tokens, charnum, linenum) {
while (valid(snd(tokens)[0])) { while (valid(snd(tokens)[0])) {
if (!(valid(fst(tokens)[0]))) if (!(valid(fst(tokens)[0])))
break; break;
//print(valid(fst(tokens)[0]), tokens);
results.push(parse(tokens)); results.push(parse(tokens));
if (!exprType(fst(results).exprType)) if (!exprType(fst(results).exprType))
break; break;
@ -157,24 +158,33 @@ function parseDefFunction(tokens) {
return new typ.DefFunc(fname, parameters, body); return new typ.DefFunc(fname, parameters, body);
} }
function parseDef(tokens) { function parseDef(tokens, linenum, charnum) {
if (tokens.length < 2) if (tokens.length < 2)
throw error.JSyntaxError(0,0,"Unexpected end of source"); throw error.JSyntaxError(linenum,
var charnum = fst(tokens)[2]; charnum,
var linenum = fst(tokens)[3]; "Unexpected end of source");
if (fst(tokens)[0] === "left_paren") { if (fst(tokens)[0] === "left_paren") {
// It's a function definition /* It's a function definition */
tokens.pop(); tokens.pop();
return parseDefFunction(tokens); return parseDefFunction(tokens);
} }
if (notFollowedBy(tokens, ["identifier"])) { if (notFollowedBy(tokens, ["identifier"], linenum, charnum)) {
throw error.JSyntaxError(linenum, throw error.JSyntaxError(linenum,
charnum, charnum,
"def must be followed by identifier, not "+fst(tokens)[0]); "def must be followed by identifier, not "+fst(tokens)[0]);
} }
else { else {
var identifier = parse(tokens); var identifier = parse(tokens);
if (!notFollowedBy(tokens, ["def", "comma", "arrow", "right_brace", "right_square"])) { if (!fst(tokens))
throw error.JSyntaxError(linenum,
charnum,
"Unexpected end of source");
linenum = fst(tokens)[3];
charnum = fst(tokens)[2];
if (!notFollowedBy(tokens,
["def", "comma", "arrow", "right_brace", "right_square"],
linenum,
charnum)) {
throw error.JSyntaxError(linenum, throw error.JSyntaxError(linenum,
charnum, charnum,
"def " + identifier.val + " must not be followed by " + fst(tokens)[0]); "def " + identifier.val + " must not be followed by " + fst(tokens)[0]);
@ -185,9 +195,14 @@ function parseDef(tokens) {
function parseIf(tokens) { function parseIf(tokens) {
if (!notFollowedBy(tokens, ["def","comma","lambda"])) { var linenum = fst(tokens)[3];
throw error.JSyntaxError(fst(tokens)[3], var charnum = fst(tokens)[2];
fst(tokens)[2], if (!notFollowedBy(tokens,
["def","comma","lambda"],
linenum,
charnum)) {
throw error.JSyntaxError(linenum,
charnum,
"``if'' cannot be followed by "+fst(tokens)[0]) ; "``if'' cannot be followed by "+fst(tokens)[0]) ;
} }
else { else {
@ -238,7 +253,7 @@ var validArgument = tool.compose(tool.not, makeChecker(invalidArguments));
var validArgTypes = tool.compose(tool.not, makeChecker(["Definition"])); var validArgTypes = tool.compose(tool.not, makeChecker(["Definition"]));
var validOperator = makeChecker(["identifier"]); 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) {
var lhs = parse(tokens); var lhs = parse(tokens);
if (fst(tokens)) if (fst(tokens))
@ -249,7 +264,7 @@ function computeApp(tokens, charnum, linenum) {
"Unexpected end of source"); "Unexpected end of source");
} }
if (typ.OPInfo[next[1]]) { if (typ.OPInfo[next[1]]) {
//it's an infix expression /* it's an infix expression */
var result = parseInfix(tokens, 1, lhs, linenum, charnum); var result = parseInfix(tokens, 1, lhs, linenum, charnum);
if (!fst(tokens) || fst(tokens)[0] !== "right_paren") { if (!fst(tokens) || fst(tokens)[0] !== "right_paren") {
throw error.JSyntaxError(linenum, throw error.JSyntaxError(linenum,
@ -257,13 +272,12 @@ function computeApp(tokens, charnum, linenum) {
"Mismatched parentheses or missing parenthesis on right-hand side"); "Mismatched parentheses or missing parenthesis on right-hand side");
} }
else { else {
//return the result
tokens.pop(); tokens.pop();
return result; return result;
} }
} }
else { else {
//it's a prefix application /* it's a prefix application */
var parameters = parseMany(validArgTypes, validArgument, tokens, charnum, linenum); var parameters = parseMany(validArgTypes, validArgument, tokens, charnum, linenum);
if ((!fst(tokens)) || fst(tokens)[0] !== "right_paren") { if ((!fst(tokens)) || fst(tokens)[0] !== "right_paren") {
@ -272,7 +286,6 @@ function computeApp(tokens, charnum, linenum) {
"Mismatched parentheses or missing parenthesis on right-hand side"); "Mismatched parentheses or missing parenthesis on right-hand side");
} }
else { else {
//return the result
tokens.pop(); tokens.pop();
return typ.makeApp(lhs, parameters); return typ.makeApp(lhs, parameters);
} }
@ -304,7 +317,7 @@ function parseInfix(tokens, minPrec, lhs, linenum, charnum) {
var assoc = opinfo[1]; var assoc = opinfo[1];
var nextMinPrec = assoc === "Left" ? prec + 1 : prec; var nextMinPrec = assoc === "Left" ? prec + 1 : prec;
tokens.pop(); tokens.pop();
//remove the operator token /*remove the operator token*/
var rhs = parseInfix(tokens, nextMinPrec); var rhs = parseInfix(tokens, nextMinPrec);
lhs = typ.makeApp(op, [lhs, rhs]); lhs = typ.makeApp(op, [lhs, rhs]);
} }
@ -337,7 +350,7 @@ function parse(tokens) {
else if (toktype === "truelit" || toktype === "falselit") else if (toktype === "truelit" || toktype === "falselit")
return new typ.BoolT(token); return new typ.BoolT(token);
else if (toktype === "def") else if (toktype === "def")
return parseDef(tokens); return parseDef(tokens, fst(tokens)[3], fst(tokens)[2]);
else if (toktype === "ifexp") else if (toktype === "ifexp")
return parseIf(tokens); return parseIf(tokens);
else if (toktype === "left_paren") { else if (toktype === "left_paren") {

2
test.jl

@ -4,7 +4,7 @@ def (f a b)
def (add a b) def (add a b)
(a + b) (a + b)
def (catstrs strs) def (catstrs strs)
(foldr f (foldr f
(head strs) (head strs)
(tail strs)) (tail strs))

Loading…
Cancel
Save