3

Possible Duplicate:
Safe evaluation of arithmetic expressions in Javascript

I am trying to build a online calculator as part of the website I have been working on.

I have + - * / ( ) AVG MIN MAX sine cos etc as the operations. There are buttons for numbers, operators and functions. I just appending a string with whatever button is pressed.

I have to build a basic syntax checker on the UI side. The server will actually perform the operations and store them and display. I do not want to spend too much time writing the client side code but the idea is to validate to see it mathematically makes sense.

Here is my plan:

I will just try an eval() of the string generated and catch the error. If the error is synatxError, then it means that the string is syntactically wrong. If it is any other type of error, I am okay with it.

So I did this at the beginning of the script:

Error.prototype.dummy_attribute = "notSyntaxError"
SyntaxError.prototype.dummy_attribute = "SyntaxError"

The above method does not work for me well because if there is string link 2() I get a type error. Now I have to write a code that checks for empty brackets and brackets preceded by no operators, or brackets followed by no operators

Or Is there an alternative method I can use to check the syntax of the string I have to see if it mathematically makes sense.

Community
  • 1
  • 1
Ranjith Ramachandra
  • 10,399
  • 14
  • 59
  • 96
  • `eval()` should have been named `evil()`. You will find many sources suggesting you **do not use it**. Have you tried parsing with a regex? – Jivings Oct 18 '12 at 13:15
  • Actually I have thought about it. But regex has such a steep learning curve and I am working on a deadline. Regex will probably remain a skill I have always wanted but I never have. I have also thought about risk with eval, but I think it can not cause much harm since I am generating that string when a click happens and I am careful with the function names etc. Is my approach so bad? – Ranjith Ramachandra Oct 18 '12 at 13:20
  • 2
    @Jivings Writing a regular expression for that is nearly impossible. Good luck matching opening and closing parens. And eval() is not always evil. – epascarello Oct 18 '12 at 13:20
  • On a side note: How the hell do they write lexical parsers for a programming laguage? I am dying to implement this simple thing. – Ranjith Ramachandra Oct 18 '12 at 13:22
  • What is an example queation look like using AVG, MAX, MIN, etc? – epascarello Oct 18 '12 at 13:23
  • @epascarello Sounds pretty evil in this scenario. Agreed about regex, I probably should have said parser. – Jivings Oct 18 '12 at 13:23
  • `AVG ( 2008 , 2000 ) / 100 + sine(10) + MAX(10,20)` @epascarello But I have to think about cases like people leaving brackets open, or doing something like `MAX()25()` Sometimes it makes sense: For exapmle 2(2) should give 4 but 2() should be invalid – Ranjith Ramachandra Oct 18 '12 at 13:25
  • 2
    @Jivings how is it evil? It is evil to the person who is using the page. Only way it would cause harm is if people can share unvalidated equations with each other via a link. Who cares if the user breaks their own page. – epascarello Oct 18 '12 at 13:25
  • @epascarello The thing is I do not want to evaluate it on client side. And there are a whole lot of functions like standard deviation etc which take comma separated values. And the requirement I have is to check syntax of it. – Ranjith Ramachandra Oct 18 '12 at 13:31
  • @epascarello You're making an assumption. And that is not the only evil. It also makes debugging notoriously difficult. As we are seeing here. – Jivings Oct 18 '12 at 13:32
  • Guys, somebody has voted to close this question :( – Ranjith Ramachandra Oct 18 '12 at 13:35
  • @RanjithR I assume it was because of the possible duplicate. – Jivings Oct 18 '12 at 13:37
  • :) thats cool. BTW how can I build a parser. Can you give me some links where I can learn – Ranjith Ramachandra Oct 18 '12 at 13:42
  • Try a Google search for "javascript parser generator". – Alex D Oct 18 '12 at 13:44
  • Wow. I did not know this PEG.js sort of thing existed. – Ranjith Ramachandra Oct 18 '12 at 13:51

1 Answers1

1

It is possible with eval. I know some die hard eval haters will downvote this. The only way this is bad is you let people supply links to your page with an equation in the query string. That will open you up to an XSS attack. If you use it only on the current page for validation, than the person will be just screwing up their own page, no risk to other people.

Basic idea:

function avg () {
    var len = arguments.length;
    if(len===0) {
        throw "no arguments suppulied for AVG";   
    }
    var arr = Array.prototype.slice.call(arguments, 0);   
    var total = 0;
    for (var i=0; i<len; i++) {
        total += arr[i];
    }
    return total/len;
}
function sine (num) {
    return Math.sin(num);
}

function max () {

    var len = arguments.length;
    if(len===0) {
        throw "no arguments suppulied for MAX";      
    }   
    var arr = Array.prototype.slice.call(arguments, 0);
    return Math.max.apply(null, arr);

}


function isValidEqn (eqn) {
    try{
        eval("var x = " + eqn.toLowerCase());
        return !isNaN(x);
    } catch(e) {
        //console.error(e);
        return false;
    }
}



var eqn1 = "AVG ( 2008 , 2000 )";
var eqn2 = "AVG ( 2008 , 2000 ) / 100 + sine(10)";
var eqn3 = "AVG ( 2008 , 2000 ) / 100 + sine(10) + MAX(10,20)";

console.log("sadjhsahd", isValidEqn("sadjhsahd") );
console.log(eqn1, isValidEqn(eqn1) );
console.log(eqn2, isValidEqn(eqn2) );
console.log(eqn3, isValidEqn(eqn3) );
epascarello
  • 204,599
  • 20
  • 195
  • 236
  • I like this idea though. I won't have any query strings and the only way to generate this is from the UI. I guess I will write dummy functions for all functions to check for arguments. – Ranjith Ramachandra Oct 18 '12 at 13:49