I'm trying to write regex in javascript that validates if a user has input a valid BODMAS string before evaluating

113 Views Asked by At

I'm trying to render a react input element that can either take in a number or a string with BODMAS operations like (5*3)+8 and evaluate it. I would like to first valid the BODMAS string so I'm trying to come up with a regular expression that validates that the string is valid, for example it catches something with a missing parentheses like (5*3 +8

I have two expressions so far

  const regex = /^(?:\s*\d+(?:\s*[+*/-]\s*\d+)*\s*)$/;

This one wont validate something like (5+30)*8 while the other

const regex2 = /^\(*(\d+(\.\d+)*|\((\d+(\.\d+)*|\(*(\d+(\.\d+)*|\((\d+(\.\d+)*|[\+-\/\*]))*\)*)*\)*)*[\+-\/\*]*)+\)*$/

This one returns as invalid. I'm new to regex and I think there's something I may be missing.

1

There are 1 best solutions below

1
trincot On

The best way would be to use a parser.

But if you prefer, you could iteratively simplify the input string until no more parentheses can be removed.

Below snippet is an implementation of that. The user's input is validated in real time:

function validate(expr) {
    expr = expr.replace(/\d+(\.\d+)?/g, "0")    // Simplify numbers to "0"
               .replace(/\s+/g, "")             // Remove white space
               .replace(/\B[+-]+(?=[0(])/g, "") // Remove unary operators (minus and plus)
               .replace(/[+*\/^-]/g, "-");      // Simplify binary operators to "-"
    for (let i = expr.length + 1; i > expr.length; ) {
        i = expr.length;
        expr = expr.replace(/\(0(-0)*\)/g, "0"); // Remove inner parentheses
    }
    return /^0(-0)*$/.test(expr);
}

// I/O management

const input = document.querySelector("input");
const refresh = () => input.className = validate(input.value) ? "ok" : "error";
input.oninput = refresh;
refresh();
.error { background: orange }
.ok { background: lightgreen }
Expression: <input type="text">

For parsing an expression, use the Shunting yard algorithm, possibly with some extensions to support functions and more. See for instance my implementation here.