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:
parent
83e6cb247a
commit
678dc200b2
@ -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 !!)");
|
||||
|
1
main.js
1
main.js
@ -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";
|
||||
|
32
parse.mjs
32
parse.mjs
@ -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);
|
Loading…
Reference in New Issue
Block a user