Reputation: 1619
I have a function which can take a string, interpret it as a calculation and return the result of the calculation, examples for valid calculations are:
3(log(e+pi^(22/3)))
44+3*(pi+2)/root(7)
the function is quite heavy so I would like to only run it if the String actually is a calculation. Before I added functions like log and root, pi and e and implicit multiplycation i used the following regex:
/^((-?([0-9]+?\.)?[0-9]+?)\s?([+\-*\/%^]|(\*\*))\s?)+?(-?([0-9]+?\.)?[0-9]+?)$/
which doesn't work anymore. At this point I am not even sure if a regex would make sense performance wise. I expect about 0.1% of strings to match (being a valid calculation).
Do you have any ideas on how to create a well performing regular expression (the function itself determines weather its a valid calculation itself, but it takes a long time, so no 100% accuracy needed) or a function which validates the calculation?
Upvotes: 0
Views: 987
Reputation: 1619
I have written a function which verifies the calculation, here is the code:
const isValidCalc = (calc) => {
contains = {
br: false,
num: false,
let: false,
op: false,
}
let prev;
let level = 0;
return ![...calc.replace(/\*\*/g, "^").replace(/ /g, "").replace(/e/g, Math.E).replace(/pi/g, Math.PI)].some(el => {
if (el === "(") {
prev = "open";
level++;
return false;
};
if (el === ")") {
if (level-- === 0 || prev === "letter") return true;
prev = "close";
contains.br = true;
return false;
}
if (_.is.Operation(el)) {
if (prev === "operator" || prev === "letter") return true;
prev = "operator";
contains.op = true;
return false;
}
if (_.is.Numeric(el) || el === ".") {
if (prev === "close" || prev === "letter") return true;
prev = "numeric"
contains.num = true;
return false;
}
if (_.is.Letter(el)) {
prev = "letter"
contains.let = true;
return false;
}
return true;
}) && level === 0 && contains.num && (!contains.let || contains.br) && (contains.let || contains.op);
};
Upvotes: 0
Reputation: 176
The question you are asking is in essence Regular Expression AND String Parsing. IMHO, your string calculation can be built as a syntax tree. It would be easier to build a parser for it than to create a rather complicated regex.
Upvotes: 1