You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
72 lines
2.6 KiB
72 lines
2.6 KiB
4 months ago
|
const { ConditionExpressionGroup, ConditionExpression, LOGICAL } = require("./expression");
|
||
|
const { operatorMap } = require("./operators");
|
||
|
|
||
|
/**
|
||
|
* @param {ConditionExpression} expression Expression to evaluate
|
||
|
* @param {object} context Context to evaluate against; These are values for variables in the expression
|
||
|
* @returns {boolean} Whether the expression evaluates true or false
|
||
|
* @throws {Error}
|
||
|
*/
|
||
|
function evaluateExpression(expression, context) {
|
||
|
/**
|
||
|
* @type {import("./operators").ConditionOperator|null}
|
||
|
*/
|
||
|
const operator = operatorMap.get(expression.operator) || null;
|
||
|
if (operator === null) {
|
||
|
throw new Error("Unexpected expression operator ID '" + expression.operator + "'. Expected one of [" + operatorMap.keys().join(",") + "]");
|
||
|
}
|
||
|
|
||
|
if (!Object.prototype.hasOwnProperty.call(context, expression.variable)) {
|
||
|
throw new Error("Variable missing in context: " + expression.variable);
|
||
|
}
|
||
|
|
||
|
return operator.test(context[expression.variable], expression.value);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param {ConditionExpressionGroup} group Group of expressions to evaluate
|
||
|
* @param {object} context Context to evaluate against; These are values for variables in the expression
|
||
|
* @returns {boolean} Whether the group evaluates true or false
|
||
|
* @throws {Error}
|
||
|
*/
|
||
|
function evaluateExpressionGroup(group, context) {
|
||
|
if (!group.children.length) {
|
||
|
throw new Error("ConditionExpressionGroup must contain at least one child.");
|
||
|
}
|
||
|
|
||
|
let result = null;
|
||
|
|
||
|
for (const child of group.children) {
|
||
|
let childResult;
|
||
|
|
||
|
if (child instanceof ConditionExpression) {
|
||
|
childResult = evaluateExpression(child, context);
|
||
|
} else if (child instanceof ConditionExpressionGroup) {
|
||
|
childResult = evaluateExpressionGroup(child, context);
|
||
|
} else {
|
||
|
throw new Error("Invalid child type in ConditionExpressionGroup. Expected ConditionExpression or ConditionExpressionGroup");
|
||
|
}
|
||
|
|
||
|
if (result === null) {
|
||
|
result = childResult; // Initialize result with the first child's result
|
||
|
} else if (child.andOr === LOGICAL.OR) {
|
||
|
result = result || childResult;
|
||
|
} else if (child.andOr === LOGICAL.AND) {
|
||
|
result = result && childResult;
|
||
|
} else {
|
||
|
throw new Error("Invalid logical operator in child of ConditionExpressionGroup. Expected 'and' or 'or'. Got '" + group.andOr + "'");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (result === null) {
|
||
|
throw new Error("ConditionExpressionGroup did not result in a boolean.");
|
||
|
}
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
module.exports = {
|
||
|
evaluateExpression,
|
||
|
evaluateExpressionGroup,
|
||
|
};
|