最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

regex for nested parenthesis in javascript - Stack Overflow

programmeradmin3浏览0评论

I'm coding a calculator in Javascript.

I want to translate : [expression1]^[expression2] into : Math.pow([expression1], [expression2])

When I have simple expressions like 5^-3 it's quite easy to do with a regex, but when it es with more plex expressions like :

(-5*(6+3)-5)^((2*2)-2)+(4*5)

I don't see how to deal with it with regex because of the nested parenthesis...

Any advice? Thanks.

I'm coding a calculator in Javascript.

I want to translate : [expression1]^[expression2] into : Math.pow([expression1], [expression2])

When I have simple expressions like 5^-3 it's quite easy to do with a regex, but when it es with more plex expressions like :

(-5*(6+3)-5)^((2*2)-2)+(4*5)

I don't see how to deal with it with regex because of the nested parenthesis...

Any advice? Thanks.

Share Improve this question asked Sep 3, 2012 at 15:17 MatthewMatthew 8679 silver badges21 bronze badges 5
  • it would be also possible to have something like (2^3)^(4^5) ? – Fabrizio Calderan Commented Sep 3, 2012 at 15:19
  • 5 Regex does bee very difficult to manage once you start trying to deal with nestable elements. For things like this, a parser is usually a better solution. A quick google brought up this one: jsfromhell./classes/math-parser (but I haven't tried it, and others may exist) – SDC Commented Sep 3, 2012 at 15:21
  • @FabrizioCalderan : Yep, and it bees even harder – Matthew Commented Sep 3, 2012 at 15:38
  • @SDC: Thank you, I'm gonna check on this side – Matthew Commented Sep 3, 2012 at 15:39
  • Have a look at this answer: stackoverflow./a/4414453/1548853 – Firas Dib Commented Sep 3, 2012 at 16:21
Add a ment  | 

2 Answers 2

Reset to default 3

Use regex pattern:

/((?:(?=[^()]*\d)\d*(?:\.\d*)?)|(?:\((?:(?:[^()]+)|(?:[^()]*\([^()]*\)[^()]*)+)\)))\^((?:(?=[^()]*\d)\-?\d*(?:\.\d*)?)|(?:\((?:(?:[^()]+)|(?:[^()]*\([^()]*\)[^()]*)+)\)))/

Check this fiddle.


Explanation:

[Step 1] :: Regex patter contains two almost same sub-patterns linked with ^ sign between

((?:(?=[^()]*\d)\d*(?:\.\d*)?)|(?:\((?:(?:[^()]+)|(?:[^()]*\([^()]*\)[^()]*)+)\)))
\^
((?:(?=[^()]*\d)\-?\d*(?:\.\d*)?)|(?:\((?:(?:[^()]+)|(?:[^()]*\([^()]*\)[^()]*)+)\)))

The only difference is that second one (behind ^) allows negative number as a simple parameter (\-?)

[Step 2] :: Sub-pattern from Step 1 has two alternatives:

(?:(?=[^()]*\d)\-?\d*(?:\.\d*)?)
|
(?:\((?:(?:[^()]+)|(?:[^()]*\([^()]*\)[^()]*)+)\))

[Step 3] :: First alternative is a number - for example: 1234 or 12.34 or 1234. or .1234

(?=[^()]*\d)
\-?\d*
(?:\.\d*)?

[Step 4] :: Second alternative is a nested parenthesis formula

\(
(?:(?:[^()]+)|(?:[^()]*\([^()]*\)[^()]*)+)
\)

[Step 5] :: which might be simple or plex (with other parenthesis inside)

(?:[^()]+)
|
(?:[^()]*\([^()]*\)[^()]*)+

[Step 6] :: and if is plex and have some other parenthesis inside, we ensure there are nested

[^()]*
\(
[^()]*
\)
[^()]*

browser javascript, as it is now. does not support recursive regular expressions.

my solution for this was to match a prefix with regular expressions. then to search for its parenthesis using a tokenizer approach. then if the parenthesis are balanced then return the chunk that is inside the parenthesis.

// replace_tokenizer_paranthesis by shimon doodkin
// this function is searching for a regexp prefix
// then searching for a chunk inside balanced parantheseis
//
// s="s( s(gdfgs)fasd)" - searched string
// prefix=/s\(/   - searched regex for prefix
// onmatch: - replace callback function, arguments:
//  a= prefix,
//  b= inside data,
//  c = closing paranthesis
//  to return same , return  [a,b+c]
//
// example:
// replace_tokenizer_paranthesis(s,prefix,function (a,b,c){ return [ "CONVERT(",b+",DATE)"  ] }) // return [ newprefix , all rest ]

function replace_tokenizer_paranthesis(s,prefix,onmatch) 
{
 var m,start=0;
 var input;
 while(m=(input=s.substr(start)).match(prefix))
 {
    var offset_at_end=m.index+m[0].length;


    var counter = 1;

    var skip_until="";
    var i = offset_at_end;
    for(; i < input.length; i++)
    {
        //var pc = i-1>=0?input[i-1]:"";
        var c = input[i];
        if( counter===0 )
        {
            break;
        }

        //else if(c===skip_until&& pc!=='\\') //maybe backslash queoted
        else if(c===skip_until)
        {
            skip_until='';
        }
        else if(c==='"')
        {
            skip_until='"';
        }
        else if(c==="'")
        {
            skip_until="'";
        }

        else if(c==='(')
        {
            counter++;
        }
        else if(c===')')
        {
            counter--;
        }
    }
    if( counter===0 )
    {
            var result=onmatch(m[0], input.substring(offset_at_end,i-1),")")
            s=s.substring(0,start+m.index)+result[0]+result[1]+s.substr(start+i);
            start+=result[0].length;
    }
    else
      start+=offset_at_end;
 }
 return s
}
发布评论

评论列表(0)

  1. 暂无评论