Marcus Parsons
Marcus Parsons

Reputation: 1803

Get exact match in string using regex and javascript

I'm trying to get an exact match from a given string, and then manipulate that string. I have a rather large calculator program that you can see here: http://www.marcusparsons.com/projects/calculator. There's nothing on the main pages just yet, and the original code is quite long.

The goal has been to implement a feature into the calculator where Math doesn't have to be prefixed to Math objects/methods. It's worked great up until I added a function that allows a user to use the "acosh()" method (and experimental methods) regardless of whether it's implemented in their browser or not (ehem...IE). The problem I run into is that the algorithm I have now wants to replace "acosh" with aMath.cosh()" because it sees "cos" inside of "acosh".

So, when I pass it the string "acosh(1)+cos(pi/3)" it turns into "aMath.cosh(1)+cos(Math.PI/3)".

Edit: The string above should be "acosh(1)+Math.cos(Math.PI/3)".

I'm a newbie at Regular Expressions, and I'm thinking that is where my problem is.

Here's the example code: http://jsfiddle.net/mparson8/2ej5n3u4/4/

var $mathKeywords = ["E", "LN2", "LN10", "LOG2E", "LOG10E", "PI", "SQRT1_2", "SQRT2", "abs", "acos", "asin", "asinh", "atan", "atan2", "atanh", "cbrt", "ceil", "clz32", "cos", "exp", "expm1", "floor", "fround", "hypot", "imul", "log1p", "log10", "log2", "max", "min", "pow", "random", "round", "sin", "sinh", "sqrt", "tan", "tanh", "trunc"];

var $resultVal = "acosh(1)+cos(PI/3)".toLowerCase();
try {
//Iterate over each Math object/method
$.each($mathKeywords, function (i, val) {
    //Convert val within array to a lower case form
    var $lowerKey = val.toLowerCase();
    //The regex pattern I came up with
    var pattern = new RegExp("(^|\\W)" + $lowerKey + "($|\\W)");
    //See if pattern gives a match within $resultVal
    var $location = $resultVal.match(pattern);
    //Math keyword is found
    if ($location != null) {
        //replace the lowercase version of the math keyword with its properly cased version prepended 
        //with Math. i.e. cos becomes Math.cos and pi becomes Math.PI
        $resultVal = $resultVal.replace($lowerKey, "Math." + val);
    }
});
//Set the result element's value to an evaluation of $resultVal
//A better implementation of the eval exists within the calc program
alert($resultVal);
alert(eval($resultVal));
} catch (err) {
alert("Error: Cannot process expression due to " + err + ".");
}

I appreciate any and all help! :)

Upvotes: 2

Views: 2731

Answers (1)

Halcyon
Halcyon

Reputation: 57703

If you want to continue on the path of regular expressions, this seems to work:

var $mathKeywords = ["E", "LN2", "LN10", "LOG2E", "LOG10E", "PI", "SQRT1_2", "SQRT2", "abs", "acos", "asin", "asinh", "atan", "atan2", "atanh", "cbrt", "ceil", "clz32", "cos", "exp", "expm1", "floor", "fround", "hypot", "imul", "log1p", "log10", "log2", "max", "min", "pow", "random", "round", "sin", "sinh", "sqrt", "tan", "tanh", "trunc"];

var $resultVal = "acosh(1)+cos(PI/3)".toLowerCase();
try {
    //Iterate over each Math object/method
    $.each($mathKeywords, function (i, val) {
        //Convert val within array to a lower case form
        var $lowerKey = val.toLowerCase();
        var pattern = new RegExp("\\b" + $lowerKey + "\\b", "g");
        //See if pattern gives a match within $resultVal
        var $location = $resultVal.match(pattern);
        //Math keyword is found
        if ($location != null) {
            //replace the lowercase version of the math keyword with its properly cased version prepended 
            //with Math. i.e. cos becomes Math.cos and pi becomes Math.PI
            $resultVal = $resultVal.replace(pattern, "Math." + val);
        }
    });
    //Set the result element's value to an evaluation of $resultVal
    //A better implementation of the eval exists within the calc program
    console.log($resultVal);
    console.log(eval($resultVal));
} catch (err) {
    alert("Error: Cannot process expression due to " + err + ".");
}

Output:

acosh(1)+Math.cos(Math.PI/3)

(actually its Error: Cannot process expression due to ReferenceError: acosh is not defined. but you get the point)


Changes:

  • Use \b as a word boundary
  • Use pattern (with word boundary) in replacement
  • Use g flag to replace all occurrences.

Upvotes: 5

Related Questions