UNPKG

@qualifyze/airtable-formulator

Version:
90 lines 3.84 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.reduceOperations = exports.isOperationNode = void 0; const primitives_1 = require("./primitives"); const expression_1 = require("./expression"); const utils_1 = require("./utils"); const node_reducer_1 = require("./node-reducer"); function isOperationNodeMember(node) { return (0, expression_1.isExpressionNode)(node) || (0, primitives_1.isOperator)(node) || (0, primitives_1.isSpace)(node); } function isOperationNode(node) { const { operator, left, right } = node; return ((0, primitives_1.isGroupNode)(node) && node.members.every(isOperationNodeMember) && node.type === "operation" && (0, primitives_1.isNode)(operator) && (0, primitives_1.isOperator)(operator) && (0, primitives_1.isNode)(left) && (0, expression_1.isExpressionNode)(left) && (0, primitives_1.isNode)(right) && (0, expression_1.isExpressionNode)(right)); } exports.isOperationNode = isOperationNode; function createOperation(nodes) { const operation = (0, primitives_1.createGroup)("operation", nodes); const [left, operator, right, invalid] = (0, primitives_1.filterMeaningfulNodes)(nodes); if (!left || !(0, expression_1.isExpressionNode)(left)) { throw new Error((0, primitives_1.createNodeErrorMessage)(operation, `expected left operand to be an expression type, but got ${left.type}`)); } if (!operator || !(0, primitives_1.isOperator)(operator)) { throw new Error((0, primitives_1.createNodeErrorMessage)(operation, `expected an operator, but got ${operator.type}`)); } if (!right || !(0, expression_1.isExpressionNode)(right)) { throw new Error((0, primitives_1.createNodeErrorMessage)(operation, `expected right operand to be an expression type, but got ${right.type}`)); } if (invalid) { throw new Error((0, primitives_1.createNodeErrorMessage)(operation, `expected only left operand, operator, and right operand, but got an extra ${invalid.type}`)); } return { ...operation, left, operator, right, }; } // XXX I could not find any reliable sources on airtable operator precedence, // so I am assuming that it will be similar to javascript's operator precedence. const operatorPrecedence = [ "&", "*", "/", "+", "-", "<", "<=", ">", ">=", "=", "!=", ]; exports.reduceOperations = (0, node_reducer_1.eagerlyRepeat)(([...nodes]) => { const meaningfulNodes = (0, primitives_1.filterMeaningfulNodes)(nodes); const operatorNodes = meaningfulNodes.filter(primitives_1.isOperator); // Sort operators by precedence operatorNodes.sort((a, b) => { const aIndex = operatorPrecedence.indexOf(a.value); const bIndex = operatorPrecedence.indexOf(b.value); return aIndex - bIndex; }); const replacement = operatorNodes .map((operator) => { const operatorIndex = meaningfulNodes.indexOf(operator); const left = meaningfulNodes[operatorIndex - 1]; const right = meaningfulNodes[operatorIndex + 1]; return { left, operator, right }; }) .find(({ left, right }) => left && (0, expression_1.isExpressionNode)(left) && right && (0, expression_1.isExpressionNode)(right)); if (replacement) { const { left, right } = replacement; const leftIndex = nodes.indexOf(left); const rightIndex = nodes.indexOf(right); const members = nodes.slice(leftIndex, rightIndex + 1); if ((0, utils_1.checkArray)(members, isOperationNodeMember)) { const operation = createOperation(members); nodes.splice(leftIndex, members.length, operation); } } return nodes; }); //# sourceMappingURL=operation.js.map