1
0
mirror of https://github.com/Baidicoot/rpncalc-v4 synced 2024-12-12 11:10:26 +00:00

improved parser to allow constants

This commit is contained in:
Aidan K. Ewart 2020-05-31 00:40:37 +01:00
parent 83e6cb247a
commit 678dc200b2
3 changed files with 33 additions and 9 deletions

View File

@ -70,6 +70,14 @@ const len = (_, args) => {
return [{type:"int", val:args[0].length}];
}
const coerce = (_, args) => {
if (args[0].type === "type") {
return [{type:args[0].val, val:args[1].val}];
} else {
throw 'typeerror'
}
}
addDefn("+", ["int", "int"], add);
addDefn("-", ["int", "int"], sub);
addDefn("/", ["int", "int"], div);
@ -84,6 +92,7 @@ addDefn("snd", ["pair"], snd);
addDefn("arr", ["int"], arr);
addDefn("!!", ["int", "array"], index);
addDefn("len", ["array"], len);
addDefn("coerce", 2, coerce);
//addRPNDefn("unit", "(-> 0 arr)");
//addRPNDefn("mono", "(-> 1 arr)");
//addRPNDefn("unwrap", "(-> 0 !!)");

View File

@ -44,6 +44,7 @@ submit.onclick = (event) => {
outbox.innerHTML = "incorrect syntax somewhere";
return;
}
console.log(ast.parsed);
let out = execRPN({}, ast.parsed);
if (!out) {
outbox.innerHTML = "failed to execute";

View File

@ -172,10 +172,21 @@ const parsePush = (stream) => {
return {parsed:{type:"push", elem:id.parsed}, stream:id.stream};
}
const parseDefn = (stream) => {
let name = parseName(stream);
if (name.parsed === null) {
return {parsed:null, stream:name.stream};
}
let expr = parseExpr(stream);
if (expr.parsed === null) {
return {parsed:null, stream:expr.stream};
}
return {parsed:{type:"defn", ident:name.parsed, defn:expr.parsed}, stream:expr.stream}
}
/* takes in stream, outputs parsed item or null - FAILABLE */
const parseLambda = (stream) => {
let name = attempt(parseName)(stream);
let args = many(parseIdent)(name.stream);
let args = many(parseIdent)(stream);
let syn = parseSyntax("->")(args.stream);
if (syn.parsed === null) {
throw 'no lambda body found!';
@ -184,16 +195,19 @@ const parseLambda = (stream) => {
if (body.parsed === null) {
throw 'no lambda body found!';
}
let func = {type:"func", args:args.parsed.map(x => x.val), body:body.parsed};
if (name.parsed === null) {
return {parsed:func, stream:body.stream};
} else {
return {parsed:{type:"defn", ident:name.parsed, defn:func}, stream:body.stream};
}
return {parsed:{type:"func", args:args.parsed.map(x => x.val), body:body.parsed}, stream:body.stream};
}
/* takes in stream, outputs parsed item or null */
const parseExpr = or(parseType, or(parseIdent, or(parseInteger, or(parsePush, attempt(parens(parseLambda))))));
const parseExpr = or(
attempt(parens(parseDefn)), or(
attempt(parens(parseLambda)), or(
attempt(parseLambda), or(
parseType, or(
parseIdent, or(
parseInteger,
parsePush
))))));
/* takes in stream, outputs parsed items */
export const parseExprs = many(parseExpr);