refactor: add op_precedence to express & with desugar_ops
This commit is contained in:
parent
f33db5f07f
commit
3a7d50924d
1 changed files with 8 additions and 28 deletions
|
|
@ -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;
|
||||||
}),
|
}),
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue