You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
83 lines
2.0 KiB
JavaScript
83 lines
2.0 KiB
JavaScript
'use strict';
|
|
|
|
const util = require("util");
|
|
|
|
module.exports = function findOperatorSequences(tree, operatorMap) {
|
|
let current = tree;
|
|
let currentIndex = 0;
|
|
let currentSequence;
|
|
|
|
let operators = [];
|
|
let operands = [];
|
|
let operatorSequences = [];
|
|
let operatorSequenceMap = {};
|
|
|
|
function storeCurrentOperatorSequence() {
|
|
operatorSequences.push(currentSequence);
|
|
|
|
if (operatorSequenceMap[currentSequence.precedence] == null) {
|
|
operatorSequenceMap[currentSequence.precedence] = [];
|
|
}
|
|
|
|
operatorSequenceMap[currentSequence.precedence].push(currentSequence);
|
|
}
|
|
|
|
while (current != null) {
|
|
operators.push(current.operator);
|
|
|
|
if (current.left != null) {
|
|
operands.push(current.left);
|
|
} else {
|
|
/* Unary prefix operator */
|
|
operands.push(null);
|
|
}
|
|
|
|
if (operatorMap[current.operator] == null) {
|
|
throw new Error(`Encountered unknown '${current.operator}' operator`);
|
|
}
|
|
|
|
let associativity = operatorMap[current.operator].associativity;
|
|
let precedence = operatorMap[current.operator].precedence;
|
|
|
|
if (currentSequence != null && precedence === currentSequence.precedence) {
|
|
/* Next operator in the same sequence. */
|
|
currentSequence.length += 1;
|
|
} else {
|
|
if (currentSequence != null) {
|
|
/* We were previously working on a different operator. */
|
|
storeCurrentOperatorSequence();
|
|
}
|
|
|
|
currentSequence = {
|
|
precedence: precedence,
|
|
associativity: associativity,
|
|
length: 1,
|
|
firstIndex: currentIndex
|
|
}
|
|
}
|
|
|
|
if (current.right == null) {
|
|
throw new Error("An error occurred; encountered a `null` right operand, but this should never happen");
|
|
} else {
|
|
if (current.right.type === "operatorExpression") {
|
|
current = current.right;
|
|
currentIndex += 1;
|
|
} else {
|
|
/* Store the very last operand. */
|
|
operands.push(current.right);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Store the very last sequence we were still working on. */
|
|
storeCurrentOperatorSequence();
|
|
|
|
return {
|
|
operators,
|
|
operands,
|
|
operatorSequences,
|
|
operatorSequenceMap
|
|
}
|
|
};
|