开发者

Validating mathematical expressions in JavaScript?

I am working on a JavaScript application that needs to validate开发者_如何学Python mathematical expressions and I am not sure how to do this.

My syntax example is

(keyword1 + keyword2) * (keyword1 / (keyword1 + keyword1))

Here, keyword1 and keyword2 can be any numbers, and valid operators are standard addition, subtraction, multiplication, and division.

Does anyone have any ideas how to do this, possibly using regular expressions?


There are many ways of going about this. I suggest you read up about Context Free Grammars/Languages. This is a little simpler (although it is indeed a CFG), but knowing grammars and parsing techniques is always helpful.

I should note that the language you describe here is not regular, so no regular expression will be able to parse it (a simple use of the pumping lemma prove this). Moreover, I would recommend against using them to help in meaningful ways - they are not powerful parsing tools.

You could use parsing libraries that solve more complex grammars and implement your simple case. If you´re looking for a more direct solution, recursion is your friend:

Let´s define a valid expression as:

expression ::= literal | expression op expression | (expression)
op ::= + | - | / | * 

Where literal is a number.

Think about how tweaking the definition can change the language, in particular, think about how different implementations can solve this with different strategies: left-to-right evaluation, or the opposite, etc.


As @davin has pointed out, this is not something you can parse with a regular expression. You can, however, parse this using a context-free grammar. Recognizing that you need a CFG here is a big step, but going from a CFG to a parsing algorithm can be a bit tricky.

To parse this expression, I would suggest using a two-step approach, much like the approach you would find inside a compiler. First, you'll want to tokenize the string into a set of logical units. That is, you'd convert the string

(1 + 6) * 7

Into the list

["(", "1", "+", "6", ")", "*", "7"]

There are many ways to do this step. You could write a manual tokenizer, or use a set of regular expressions to piece apart the string. At this point you can detect lexical errors, where you report if the string has any contents that ought not be there. For example, the character "," has no business being in any of these expressions, and you can detect this here.

Once you've tokenized the string, you will want to parse the stream of tokens to verify that it is valid and, optionally, to build up an appropriate internal representation for the mathematical expression. One of the more famous (and simplest) algorithms for doing this is Dijkstra's Shunting-Yard algorithm, which you can easily write up in an hour. If you're interested in a more heavyweight class of algorithms for parsing these sorts of expressions, you should consider looking into parser generators, which are capable of handling more complex expressions. A quick search turned up this LALR(1) parser generator for JavaScript if you want to do the parsing client-side. If you want to handle parsing on the server, consider looking into the bison or ANTLR tools, which are extremely powerful parser generators.

Hope this helps!


I have to design the Dynamic Formulae creator in Angular for that i have to check whether the given expression in valid or not, before passing it to the DB.

I write this code for validating mathematical expression which can help You .

/* Code Start From Here */

validate(expression) {

    let previous = 0;
    let previous1 = 0;
    let operatorOperand = 1;

    for (let i = 0; i < expression.length; i++) {
        let c = expression[i];
        if (c == ")") {
        } else if (c == "(") {
            let j = this.indexOfFromGivenIndexInArray(expression, ")", i);

            if (j == -1) return false;

            let substring = expression.slice(i + 1, j - i);

            while (this.getcharactercount(substring, "(") != this.getcharactercount(substring, ")")) {
                if (j < expression.length - 1) j = this.indexOfFromGivenIndexInArray(expression, ")", j + 1);
                else break;
                substring = expression.slice(i + 1, j - i);
            }
            console.log(substring, "PHASE 2");
            i = j - 1;

            if (this.validate(substring) == true) {
                if (previous != 0 && previous1 != 0 && previous > previous1) {
                    previous1 = operatorOperand;
                    operatorOperand++;
                    previous = 0;
                } else if (previous != 0 && previous1 != 0 && previous <= previous1) {
                    return false;
                } else if (previous1 != 0) {
                    return false;
                } else {
                    previous1 = operatorOperand;
                    operatorOperand++;
                }
            } else {
                return false;
            }
        } else if (c == "+" || c == "-" || c == "AND" || c == "OR") {
            if (previous != 0) {
                return false;
            }
            previous = operatorOperand;
            operatorOperand++;
        } else {
            if (previous != 0 && previous1 != 0 && previous > previous1) {
                previous1 = operatorOperand;
                operatorOperand++;
                previous = 0;
            } else if (previous != 0 && previous1 != 0 && previous <= previous1) {
                return false;
            } else if (previous1 != 0) {
                return false;
            } else {
                previous1 = operatorOperand;
                operatorOperand++;
            }
        }
    }
    if (previous != 0) return false;
    return true;
}

indexOfFromGivenIndexInArray(expression, ch, index: number): number {
    console.log("eeee", expression, ch, index);
    for (let ind = index; ind < expression.length; ind++) {
        console.log(ch, "DIFF", expression[ind], "DIFF", ind);
        if (expression[ind] == ch) {
            return ind;
        }
    }
    return -1;
}

getcharactercount(exp, _c): number {
    let count = 0;
    for (let ch in exp) {
        if (ch == _c) {
            count++;
        }
    }
    return count;
}


Simple soultion is we can sent the ajax request to the server may be database with expression if it return the correct value without error my expression is valid else not valid

simple ha~

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜