1
0
mirror of https://github.com/Baidicoot/rpncalc-v4 synced 2024-06-18 11:09:57 +00:00

fixed random throws + non-backtracing stream

This commit is contained in:
Aidan K. Ewart 2020-05-20 00:11:31 +01:00
parent e29e83789c
commit ccff5a14a3

View File

@ -65,7 +65,7 @@ const attempt = (parser) => (stream) => {
const or = (a, b) => (stream) => { const or = (a, b) => (stream) => {
let aout = a(stream); let aout = a(stream);
if (aout.parsed === null) { if (aout.parsed === null) {
return b(stream); return b(aout.stream);
} else { } else {
return aout; return aout;
} }
@ -74,15 +74,15 @@ const or = (a, b) => (stream) => {
/* (parser) */ /* (parser) */
const parens = (parser) => (stream) => { const parens = (parser) => (stream) => {
let a = parseSyntax("(", stream); let a = parseSyntax("(", stream);
if (a === null) { if (a.parsed === null) {
return {parsed:null, stream:stream}; return {parsed:null, stream:a.stream};
} }
let dat = parser(stream); let dat = parser(a.stream);
a = parseSyntax(")", stream); a = parseSyntax(")", dat.stream);
if (a === null) { if (a.parsed === null) {
throw 'mismatched parens!'; throw 'mismatched parens!';
} }
return dat; return {parsed:dat.parsed, stream:a.stream};
} }
/* [parser] */ /* [parser] */
@ -90,6 +90,7 @@ const many = (parser) => (stream) => {
let parsed = []; let parsed = [];
for (let i = parser(stream); i.parsed !== null; i = parser(stream)) { for (let i = parser(stream); i.parsed !== null; i = parser(stream)) {
parsed.push(i.parsed); parsed.push(i.parsed);
stream = i.stream;
} }
return {parsed:parsed, stream:stream}; return {parsed:parsed, stream:stream};
} }
@ -160,30 +161,31 @@ const parseSyntax = (syntax, stream) => {
const parseName = (stream) => { const parseName = (stream) => {
let id = parseIdent(stream); let id = parseIdent(stream);
if (id.parsed === null) { if (id.parsed === null) {
return {parsed:null, stream:stream}; return {parsed:null, stream:id.stream};
} }
let syn = parseSyntax(";", stream); let syn = parseSyntax(";", id.stream);
if (syn.parsed === null) { if (syn.parsed === null) {
throw 'could not parse name!' throw 'could not parse name!'
} }
return {parsed:id.parsed.val, stream:stream}; return {parsed:id.parsed.val, stream:syn.stream};
} }
/* takes in stream, outputs parsed item or null - FAILABLE */ /* takes in stream, outputs parsed item or null - FAILABLE */
const parseLambda = (stream) => { const parseLambda = (stream) => {
let name = attempt(parseName)(stream).parsed; let name = attempt(parseName)(stream);
if (name === null) { if (name.parsed === null) {
name = ""; name.parsed = "";
} }
let args = many(parseIdent)(stream).parsed; let args = many(parseIdent)(name.stream);
if (parseSyntax("->", stream).parsed === null) { let syn = parseSyntax("->", args.stream);
if (syn.parsed === null) {
throw 'no lambda body found!'; throw 'no lambda body found!';
} }
let body = parseExprs(stream).parsed; // .parsed should never be null, but anyway... let body = parseExprs(syn.stream); // .parsed should never be null, but anyway...
if (body === null) { if (body.parsed === null) {
throw 'no lambda body found!'; throw 'no lambda body found!';
} }
return {parsed:{type:"func", name:name, args:args, body:body}, stream:stream}; return {parsed:{type:"func", name:name.parsed, args:args.parsed, body:body.parsed}, stream:body.stream};
} }
/* takes in stream, outputs parsed item or null */ /* takes in stream, outputs parsed item or null */