mirror of
https://github.com/ANL-CEEESA/RELOG.git
synced 2025-12-06 15:48:51 -06:00
Parse and evaluate expressions
This commit is contained in:
14
relog-web/package-lock.json
generated
14
relog-web/package-lock.json
generated
@@ -16,6 +16,7 @@
|
|||||||
"d3-array": "^2.12.1",
|
"d3-array": "^2.12.1",
|
||||||
"dagre": "^0.8.5",
|
"dagre": "^0.8.5",
|
||||||
"idb": "^6.1.5",
|
"idb": "^6.1.5",
|
||||||
|
"jsep": "^1.3.8",
|
||||||
"leaflet": "^1.8.0",
|
"leaflet": "^1.8.0",
|
||||||
"react": "^17.0.2",
|
"react": "^17.0.2",
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^17.0.2",
|
||||||
@@ -11201,6 +11202,14 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/jsep": {
|
||||||
|
"version": "1.3.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/jsep/-/jsep-1.3.8.tgz",
|
||||||
|
"integrity": "sha512-qofGylTGgYj9gZFsHuyWAN4jr35eJ66qJCK4eKDnldohuUoQFbU3iZn2zjvEbd9wOAhP9Wx5DsAAduTyE1PSWQ==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10.16.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/jsesc": {
|
"node_modules/jsesc": {
|
||||||
"version": "2.5.2",
|
"version": "2.5.2",
|
||||||
"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
|
"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
|
||||||
@@ -25021,6 +25030,11 @@
|
|||||||
"xml-name-validator": "^3.0.0"
|
"xml-name-validator": "^3.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"jsep": {
|
||||||
|
"version": "1.3.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/jsep/-/jsep-1.3.8.tgz",
|
||||||
|
"integrity": "sha512-qofGylTGgYj9gZFsHuyWAN4jr35eJ66qJCK4eKDnldohuUoQFbU3iZn2zjvEbd9wOAhP9Wx5DsAAduTyE1PSWQ=="
|
||||||
|
},
|
||||||
"jsesc": {
|
"jsesc": {
|
||||||
"version": "2.5.2",
|
"version": "2.5.2",
|
||||||
"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
|
"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
"d3-array": "^2.12.1",
|
"d3-array": "^2.12.1",
|
||||||
"dagre": "^0.8.5",
|
"dagre": "^0.8.5",
|
||||||
"idb": "^6.1.5",
|
"idb": "^6.1.5",
|
||||||
|
"jsep": "^1.3.8",
|
||||||
"leaflet": "^1.8.0",
|
"leaflet": "^1.8.0",
|
||||||
"react": "^17.0.2",
|
"react": "^17.0.2",
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^17.0.2",
|
||||||
|
|||||||
50
relog-web/src/casebuilder/expr.js
Normal file
50
relog-web/src/casebuilder/expr.js
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
import { Jsep } from "jsep";
|
||||||
|
import { exportValue } from "./export";
|
||||||
|
|
||||||
|
export const evaluateExpr = (expr, data) => {
|
||||||
|
const node = Jsep.parse(expr);
|
||||||
|
return evaluateNode(node, data);
|
||||||
|
};
|
||||||
|
|
||||||
|
const evaluateNode = (node, data) => {
|
||||||
|
if (node.type == "BinaryExpression") {
|
||||||
|
return evaluateBinaryExprNode(node, data);
|
||||||
|
} else if (node.type == "UnaryExpression") {
|
||||||
|
return evaluateUnaryExprNode(node, data);
|
||||||
|
} else if (node.type == "Literal") {
|
||||||
|
return node.value;
|
||||||
|
} else if (node.type == "Identifier") {
|
||||||
|
return data[node.name];
|
||||||
|
} else {
|
||||||
|
throw `Unknown type: ${node.type}`;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const evaluateBinaryExprNode = (node, data) => {
|
||||||
|
const leftVal = evaluateNode(node.left, data);
|
||||||
|
const rightVal = evaluateNode(node.right, data);
|
||||||
|
if (node.operator == "+") {
|
||||||
|
return leftVal + rightVal;
|
||||||
|
} else if (node.operator == "*") {
|
||||||
|
return leftVal * rightVal;
|
||||||
|
} else if (node.operator == "/") {
|
||||||
|
return leftVal / rightVal;
|
||||||
|
} else if (node.operator == "-") {
|
||||||
|
return leftVal - rightVal;
|
||||||
|
} else if (node.operator == "^") {
|
||||||
|
return Math.pow(leftVal, rightVal);
|
||||||
|
} else {
|
||||||
|
throw `Unknown operator: ${node.operator}`;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const evaluateUnaryExprNode = (node, data) => {
|
||||||
|
const arg = evaluateNode(node.argument, data);
|
||||||
|
if (node.operator == "+") {
|
||||||
|
return arg;
|
||||||
|
} else if (node.operator == "-") {
|
||||||
|
return -arg;
|
||||||
|
} else {
|
||||||
|
throw `Unknown operator: ${node.operator}`;
|
||||||
|
}
|
||||||
|
};
|
||||||
19
relog-web/src/casebuilder/expr.test.js
Normal file
19
relog-web/src/casebuilder/expr.test.js
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
import { evaluateExpr } from "./expr";
|
||||||
|
|
||||||
|
test("parse expression", () => {
|
||||||
|
// Basic expressions
|
||||||
|
expect(evaluateExpr("1 + 1")).toEqual(2);
|
||||||
|
expect(evaluateExpr("2 * 5")).toEqual(10);
|
||||||
|
expect(evaluateExpr("2 * (3 + 5)")).toEqual(16);
|
||||||
|
expect(evaluateExpr("14 / 2")).toEqual(7);
|
||||||
|
expect(evaluateExpr("10 - 3")).toEqual(7);
|
||||||
|
expect(evaluateExpr("-10")).toEqual(-10);
|
||||||
|
expect(evaluateExpr("+10")).toEqual(10);
|
||||||
|
expect(evaluateExpr("2^3")).toEqual(8);
|
||||||
|
expect(evaluateExpr("2^(3 + 1)")).toEqual(16);
|
||||||
|
|
||||||
|
// With data
|
||||||
|
expect(evaluateExpr("x + 1", { x: 10 })).toEqual(11);
|
||||||
|
expect(evaluateExpr("2 ^ (3 + x)", { x: 1 })).toEqual(16);
|
||||||
|
expect(evaluateExpr("x + y", { x: 1, y: 2 })).toEqual(3);
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user