Browse Source

misc style improvements, improve error reporting line/char info

pull/18/head
nisstyre56 11 years ago
parent
commit
a8e3afd946
  1. 1
      example.jl
  2. 163
      parse.js

1
example.jl

@ -82,6 +82,7 @@ def r def
def main def main
let { let {
(f a) -> a
unary = (print (testUnary 6)) unary = (print (testUnary 6))
splitted = def { splitted = def {
xs = (fst (splitxs [12,3,4,56])) xs = (fst (splitxs [12,3,4,56]))

163
parse.js

@ -192,8 +192,8 @@ function parseDefFunction(tokens, linenum, charnum) {
var body; var body;
if (fname.exprType !== "Name") { if (fname.exprType !== "Name") {
throw error.JSyntaxError(fst(tokens)[3], throw error.JSyntaxError(linenum,
fst(tokens)[2], charnum,
"Expected an identifier in function definition"); "Expected an identifier in function definition");
} }
if (fst(tokens)[0] === "right_paren") { if (fst(tokens)[0] === "right_paren") {
@ -204,17 +204,17 @@ function parseDefFunction(tokens, linenum, charnum) {
validName, validName,
validFormPar, validFormPar,
tokens, tokens,
fst(tokens)[2], charnum,
fst(tokens)[3]); linenum);
} }
if (!tokens || (fst(tokens)[0]) !== "right_paren") { if (!tokens || (fst(tokens)[0]) !== "right_paren") {
throw error.JSyntaxError(fst(tokens)[3], throw error.JSyntaxError(linenum,
fst(tokens)[2], charnum,
"Formal parameters must be followed by )"); "Formal parameters must be followed by )");
} }
tokens.pop(); tokens.pop();
body = parse(tokens); body = parse(tokens);
result = addSrcPos(new typ.DefFunc(fname, parameters, body), tokens, linenum, charnum); result = addSrcPos(new typ.DefFunc(fname, parameters, body), tokens, body.linenum, body.charnum);
return result; return result;
} }
@ -235,32 +235,32 @@ function parseLetForm(tokens, linenum, charnum) {
validLet, validLet,
letEnd, letEnd,
tokens, tokens,
linenum, charnum,
charnum); linenum);
if (fst(tokens) && fst(tokens)[0] !== "right_brace") { if (fst(tokens) && fst(tokens)[0] !== "right_brace") {
throw error.JSyntaxError(fst(tokens)[2], throw error.JSyntaxError(fst(tokens)[2],
fst(tokens)[3], fst(tokens)[3],
"let/def form must have a closing }"); "let/def form must have a closing }");
} }
if (!fst(tokens)) { if (!fst(tokens)) {
throw error.JSyntaxError(linenum, throw error.JSyntaxError(_.last(pairs).linenum,
charnum, _.last(pairs).charnum,
"Unexpected end of source"); "Unexpected end of source");
} }
tokens.pop(); tokens.pop();
if (tokens.length <= 0) { if (tokens.length <= 0) {
throw error.JSyntaxError(fst(tokens)[3], throw error.JSyntaxError(_.last(pairs).linenum,
fst(tokens)[2], _.last(pairs).charnum,
"let/def form must have a body"); "let/def form must have a body");
} }
body = parse(tokens); body = parse(tokens);
if (body.exprType === "Definition" || if (body.exprType === "Definition" ||
body.exprType === "FunctionDefinition") { body.exprType === "FunctionDefinition") {
throw error.JSyntaxError(fst(tokens)[3], throw error.JSyntaxError(body.linenum,
fst(tokens)[2], body.charnum,
"Body of a let/def expression cannot be a definition"); "Body of a let/def expression cannot be a definition");
} }
result = addSrcPos(new typ.LetExp(pairs, body), tokens, linenum, charnum); result = addSrcPos(new typ.LetExp(pairs, body), tokens, body.linenum, body.charnum);
return result; return result;
} }
@ -284,12 +284,12 @@ function parseLetFunction(tokens, linenum, charnum) {
validName, validName,
validFormPar, validFormPar,
tokens, tokens,
fst(tokens)[2], charnum,
fst(tokens)[3]); linenum);
} }
if ((fst(tokens)[0]) !== "right_paren") { if ((fst(tokens)[0]) !== "right_paren") {
throw error.JSyntaxError(fst(tokens)[3], throw error.JSyntaxError(linenum,
fst(tokens)[2], charnum,
"Formal parameters must be followed by )"); "Formal parameters must be followed by )");
} }
tokens.pop(); tokens.pop();
@ -300,7 +300,7 @@ function parseLetFunction(tokens, linenum, charnum) {
} }
tokens.pop(); tokens.pop();
body = parse(tokens); body = parse(tokens);
result = addSrcPos(new typ.DefFunc(fname, parameters, body), tokens, linenum, charnum); result = addSrcPos(new typ.DefFunc(fname, parameters, body), tokens, body.linenum, body.charnum);
return result; return result;
} }
@ -310,46 +310,49 @@ function parseLetBinding(tokens, linenum, charnum) {
var bound; var bound;
if (name.exprType != "Name") { if (name.exprType != "Name") {
throw error.JSyntaxError(linenum, throw error.JSyntaxError(name.linenum,
charnum, name.charnum,
"Expected an identifier in let/def binding"); "Expected an identifier in let/def binding");
} }
if (!fst(tokens) || fst(tokens)[1] !== "=") { if (!fst(tokens) || fst(tokens)[1] !== "=") {
throw error.JSyntaxError(linenum, throw error.JSyntaxError(name.linenum,
charnum, name.charnum,
"An identifier in a let/def binding must be followed by ``=''"); "An identifier in a let/def binding must be followed by ``=''");
} }
tokens.pop(); tokens.pop();
if (!notFollowedBy(tokens, if (!notFollowedBy(tokens,
["comma", "arrow", "right_brace", "right_square"], ["comma", "arrow", "right_brace", "right_square"],
linenum, name.linenum,
charnum)) { name.charnum)) {
throw error.JSyntaxError(linenum, throw error.JSyntaxError(name.linenum,
charnum, name.charnum,
"The binding of " + identifier.val + " must not be followed by " + fst(tokens)[0]); "The binding of " + identifier.val + " must not be followed by " + fst(tokens)[0]);
} }
bound = parse(tokens); bound = parse(tokens);
if (bound.exprType === "Definition" || if (bound.exprType === "Definition" ||
bound.exprType === "FunctionDefinition") { bound.exprType === "FunctionDefinition") {
throw error.JSyntaxError(linenum, throw error.JSyntaxError(bound.linenum,
charnum, bound.charnum,
"A definition cannot be the value of a binding"); "A definition cannot be the value of a binding");
} }
result = addSrcPos(new typ.Def(name, bound), tokens, linenum, charnum); result = addSrcPos(new typ.Def(name, bound), tokens, bound.linenum, bound.charnum);
return result; return result;
} }
function parseLetItem(tokens) { function parseLetItem(tokens) {
var linenum = fst(tokens)[3];
var charnum = fst(tokens)[2];
if (fst(tokens) && fst(tokens)[0] === "left_paren") { if (fst(tokens) && fst(tokens)[0] === "left_paren") {
tokens.pop(); tokens.pop();
return parseLetFunction(tokens, return parseLetFunction(tokens,
fst(tokens)[3], linenum,
fst(tokens)[2]); charnum);
} }
else { else {
return parseLetBinding(tokens, return parseLetBinding(tokens,
fst(tokens)[3], linenum,
fst(tokens)[2]); charnum);
} }
} }
@ -371,8 +374,8 @@ function parseDataType(tokens, linenum, charnum) {
charnum, charnum,
linenum); linenum);
if (!tokens || (fst(tokens)[0]) !== "right_paren") { if (!tokens || (fst(tokens)[0]) !== "right_paren") {
throw error.JSyntaxError(fst(tokens)[3], throw error.JSyntaxError(_.last(parameters).linenum,
fst(tokens)[2], _.last(parameters).charnum,
"Data type parameters must be followed by )"); "Data type parameters must be followed by )");
} }
tokens.pop(); tokens.pop();
@ -414,8 +417,8 @@ function parseDefType(tokens, linenum, charnum) {
else { else {
lhs = parse(tokens, linenum, charnum); lhs = parse(tokens, linenum, charnum);
if (!tokens) { if (!tokens) {
throw error.JSyntaxError(linenum, throw error.JSyntaxError(lhs.linenum,
charnum, lhs.charnum,
"Unexpected end of source"); "Unexpected end of source");
} }
if (lhs.exprType !== "TypeOperator") { if (lhs.exprType !== "TypeOperator") {
@ -431,7 +434,7 @@ function parseDefType(tokens, linenum, charnum) {
rhs.charnum, rhs.charnum,
"was expecting an application or type operator on the right-hand side of a type definition"); "was expecting an application or type operator on the right-hand side of a type definition");
} }
result = addSrcPos(new typ.DefType(lhs, rhs), tokens, linenum, charnum); result = addSrcPos(new typ.DefType(lhs, rhs), tokens, rhs.linenum, rhs.charnum);
return result; return result;
} }
} }
@ -475,24 +478,22 @@ function parseDef(tokens, linenum, charnum) {
else { else {
identifier = parse(tokens); identifier = parse(tokens);
if (!fst(tokens)) if (!fst(tokens))
throw error.JSyntaxError(linenum, throw error.JSyntaxError(identifier.linenum,
charnum, identifier.charnum,
"Unexpected end of source"); "Unexpected end of source");
linenum = fst(tokens)[3];
charnum = fst(tokens)[2];
if (!notFollowedBy(tokens, if (!notFollowedBy(tokens,
["comma", "arrow", "right_brace", "right_square"], ["comma", "arrow", "right_brace", "right_square"],
linenum, identifier.linenum,
charnum)) { identifier.charnum)) {
throw error.JSyntaxError(linenum, throw error.JSyntaxError(identifier.linenum,
charnum, identifier.charnum,
"def " + identifier.val + " must not be followed by " + fst(tokens)[0]); "def " + identifier.val + " must not be followed by " + fst(tokens)[0]);
} }
bound = parse(tokens); bound = parse(tokens);
if (bound.exprType === "Definition" || if (bound.exprType === "Definition" ||
bound.exprType === "FunctionDefinition") { bound.exprType === "FunctionDefinition") {
throw error.JSyntaxError(linenum, throw error.JSyntaxError(bound.linenum,
charnum, bound.charnum,
"A definition cannot be the value of a binding"); "A definition cannot be the value of a binding");
} }
result = addSrcPos(new typ.Def(identifier, bound), tokens, bound.linenum, bound.charnum); result = addSrcPos(new typ.Def(identifier, bound), tokens, bound.linenum, bound.charnum);
@ -503,6 +504,7 @@ function parseDef(tokens, linenum, charnum) {
function parseDefOp(tokens, linenum, charnum) { function parseDefOp(tokens, linenum, charnum) {
var result; var result;
var names; var names;
var pattern;
if (fst(tokens)[0] !== "integer" || if (fst(tokens)[0] !== "integer" ||
fst(tokens)[1] < 1) { fst(tokens)[1] < 1) {
@ -532,7 +534,7 @@ function parseDefOp(tokens, linenum, charnum) {
charnum, charnum,
"defop must be surrounded by exactly 3 identifiers"); "defop must be surrounded by exactly 3 identifiers");
} }
var pattern = tokens.slice(tokens.length-3, pattern = tokens.slice(tokens.length-3,
tokens.length); tokens.length);
tokens.pop(); tokens.pop(); tokens.pop(); tokens.pop(); tokens.pop(); tokens.pop();
if (fst(tokens)[0] !== "right_paren") { if (fst(tokens)[0] !== "right_paren") {
@ -554,17 +556,19 @@ function parseDefOp(tokens, linenum, charnum) {
names.slice(1,3), names.slice(1,3),
parse(tokens)), parse(tokens)),
tokens, tokens,
linenum, _.last(names).linenum,
charnum); _.last(names).charnum);
return result; return result;
} }
function parseIf(tokens) { function parseIf(tokens, linenum, charnum) {
var linenum = fst(tokens)[3];
var charnum = fst(tokens)[2];
var result; var result;
var ifC;
var thenC;
var elseC;
if (!notFollowedBy(tokens, if (!notFollowedBy(tokens,
["def","comma","lambda"], ["def","comma","lambda"],
linenum, linenum,
@ -574,32 +578,32 @@ function parseIf(tokens) {
"``if'' cannot be followed by "+fst(tokens)[0]) ; "``if'' cannot be followed by "+fst(tokens)[0]) ;
} }
else { else {
var ifC = parse(tokens); ifC = parse(tokens);
if (!fst(tokens) || fst(tokens)[0] !== "thenexp") { if (!fst(tokens) || fst(tokens)[0] !== "thenexp") {
throw error.JSyntaxError(fst(tokens)[3], throw error.JSyntaxError(ifC.linenum,
fst(tokens)[2], ifC.charnum,
"if ``exp'' must be folowed by ``then'' exp, not "+snd(tokens)[0]); "if ``exp'' must be folowed by ``then'' exp, not "+snd(tokens)[0]);
} }
else { else {
tokens.pop(); tokens.pop();
var thenC = parse(tokens); thenC = parse(tokens);
if (fst(tokens) && fst(tokens)[0] === "elsexp") { if (fst(tokens) && fst(tokens)[0] === "elsexp") {
tokens.pop(); tokens.pop();
if (_.size(tokens) < 1) { if (_.size(tokens) < 1) {
throw error.JSyntaxError(linenum, throw error.JSyntaxError(thenC.linenum,
charnum, thenC.charnum,
"Unexpected end of source"); "Unexpected end of source");
} }
else { else {
var elseC = parse(tokens); elseC = parse(tokens);
result = addSrcPos(new typ.If(ifC, thenC, elseC), tokens, elseC.linenum, elseC.charnum); result = addSrcPos(new typ.If(ifC, thenC, elseC), tokens, elseC.linenum, elseC.charnum);
return result; return result;
} }
} }
else { else {
throw error.JSyntaxError(linenum, throw error.JSyntaxError(thenC.linenum,
charnum, thenC.charnum,
"If expression must include an else variant"); "If expression must include an else variant");
} }
} }
@ -613,9 +617,7 @@ function validFormPar(tok) {
tok[1] !== "->"; tok[1] !== "->";
} }
function parseLambda(tokens) { function parseLambda(tokens, linenum, charnum) {
var linenum = fst(tokens)[2];
var charnum = fst(tokens)[3];
var result; var result;
var parameters = parseMany(parse, var parameters = parseMany(parse,
validName, validName,
@ -624,8 +626,8 @@ function parseLambda(tokens) {
charnum, charnum,
linenum); linenum);
if (fst(tokens)[1] !== "->") { if (fst(tokens)[1] !== "->") {
throw error.JSyntaxError(fst(tokens)[3], throw error.JSyntaxError(_.last(parameters).linenum,
fst(tokens)[2], _.last(parameters).charnum,
"arrow must follow parameters in lambda, not "+fst(tokens)[0]); "arrow must follow parameters in lambda, not "+fst(tokens)[0]);
} }
tokens.pop(); tokens.pop();
@ -643,20 +645,22 @@ function computeApp(tokens, charnum, linenum) {
var lhs = parse(tokens); var lhs = parse(tokens);
var next; var next;
var result; var result;
var parameters;
if (fst(tokens)) { if (fst(tokens)) {
next = fst(tokens); next = fst(tokens);
} }
else { else {
throw error.JSyntaxError(linenum, throw error.JSyntaxError(lhs.linenum,
charnum, lhs.charnum,
"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 */
result = parseInfix(tokens, 1, lhs, linenum, charnum); result = parseInfix(tokens, 1, lhs, lhs.linenum, lhs.charnum);
if (!fst(tokens) || fst(tokens)[0] !== "right_paren") { if (!fst(tokens) || fst(tokens)[0] !== "right_paren") {
throw error.JSyntaxError(fst(tokens)[3], throw error.JSyntaxError(lhs.linenum,
fst(tokens)[2], lhs.charnum,
"Mismatched parentheses or missing parenthesis on right-hand side"); "Mismatched parentheses or missing parenthesis on right-hand side");
} }
else { else {
@ -666,7 +670,6 @@ function computeApp(tokens, charnum, linenum) {
} }
else { else {
/* it's a prefix application */ /* it's a prefix application */
var parameters;
if (fst(tokens)[0] !== "right_paren") { if (fst(tokens)[0] !== "right_paren") {
parameters = parseMany(parse, parameters = parseMany(parse,
validArgTypes, validArgTypes,
@ -744,7 +747,7 @@ function parse(tokens) {
return parseList(tokens, linenum, charnum); return parseList(tokens, linenum, charnum);
} }
else if (toktype === "lambda") { else if (toktype === "lambda") {
return parseLambda(tokens); return parseLambda(tokens, linenum, charnum);
} }
else if (toktype === "integer") { else if (toktype === "integer") {
result = addSrcPos(new typ.IntT(token), tokens, linenum, charnum); result = addSrcPos(new typ.IntT(token), tokens, linenum, charnum);
@ -777,12 +780,12 @@ function parse(tokens) {
return parseDefOp(tokens, linenum, charnum); return parseDefOp(tokens, linenum, charnum);
} }
else if (toktype === "ifexp") { else if (toktype === "ifexp") {
return parseIf(tokens); return parseIf(tokens, linenum, charnum);
} }
else if (toktype === "left_paren") { else if (toktype === "left_paren") {
if (fst(tokens)[0] === "lambda") { if (fst(tokens)[0] === "lambda") {
tokens.pop(); tokens.pop();
var parsed = parseLambda(tokens); var parsed = parseLambda(tokens, linenum, charnum);
tokens.pop(); tokens.pop();
return parsed; return parsed;
} }

Loading…
Cancel
Save