refactor: add op_precedence to express & with desugar_ops

This commit is contained in:
Felix Roos 2025-10-07 22:59:50 +02:00
parent f33db5f07f
commit 3a7d50924d
No known key found for this signature in database

View file

@ -21,14 +21,14 @@ export class MondoParser {
close_curly: /^\}/, close_curly: /^\}/,
number: /^-?[0-9]*\.?[0-9]+/, // before pipe! number: /^-?[0-9]*\.?[0-9]+/, // before pipe!
// TODO: better error handling when "-" is used as rest, e.g "s [- bd]" // TODO: better error handling when "-" is used as rest, e.g "s [- bd]"
op: /^[*/:!@%?+-]|^\.{2}/, // * / : ! @ % ? .. op: /^[*\/:!@%?+\-&]|^\.{2}/, // * / : ! @ % ? ..
and: /^&/,
// dollar: /^\$/, // dollar: /^\$/,
pipe: /^#/, pipe: /^#/,
stack: /^[,$]/, stack: /^[,$]/,
or: /^[|]/, or: /^[|]/,
plain: /^[a-zA-Z0-9-~_^#]+/, plain: /^[a-zA-Z0-9-~_^#]+/,
}; };
op_precedence = [['*', '/', ':', '!', '@', '%', '?', '+', '-', '..'], ['&']];
// matches next token // matches next token
next_token(code, offset = 0) { next_token(code, offset = 0) {
for (let type in this.token_types) { for (let type in this.token_types) {
@ -151,30 +151,9 @@ export class MondoParser {
} }
return children; return children;
} }
desugar_ands(children) { desugar_ops(children, types) {
while (true) { while (true) {
let opIndex = children.findIndex((child) => child.type === 'and'); let opIndex = children.findIndex((child) => child.type === 'op' && types.includes(child.value));
if (opIndex === -1) break;
if (opIndex === children.length - 1) {
throw new Error(`cannot use & as last child.`);
}
if (opIndex === 0) {
throw new Error(`cannot use & as first child.`);
}
// convert infix to prefix notation
const op = { type: 'plain', value: children[opIndex].value };
const left = children[opIndex - 1];
const right = children[opIndex + 1];
const call = { type: 'list', children: [op, right, left] };
// insert call while keeping other siblings
children = [...children.slice(0, opIndex - 1), call, ...children.slice(opIndex + 2)];
children = this.unwrap_children(children);
}
return children;
}
desugar_ops(children) {
while (true) {
let opIndex = children.findIndex((child) => child.type === 'op');
if (opIndex === -1) break; if (opIndex === -1) break;
const op = { type: 'plain', value: children[opIndex].value }; const op = { type: 'plain', value: children[opIndex].value };
if (opIndex === children.length - 1) { if (opIndex === children.length - 1) {
@ -285,9 +264,10 @@ export class MondoParser {
// the type we've removed before splitting needs to be added back // the type we've removed before splitting needs to be added back
children = [{ type: 'plain', value: type }, ...children]; children = [{ type: 'plain', value: type }, ...children];
} }
children = this.desugar_ops(children); // for each precendence group, call desugar_ops once
children = this.desugar_ands(children); this.op_precedence.forEach((ops) => {
// children = this.desugar_pipes(children, (children) => this.desugar_dollars(children)); children = this.desugar_ops(children, ops);
});
children = this.desugar_pipes(children); children = this.desugar_pipes(children);
return children; return children;
}), }),