'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 } };