0

I have no idea on matching the input parenthesis with JavaScript.

Input string example:

(pen)
((pen) and orange)

it should return false if the input string is like the following:

(pen
pen)
(pen) and orange)
((pen and orange )
((pen) and orange 
)(pen and orange )(
(pen and )orange() 
1
  • how to match it with regular expression? Commented Nov 8, 2010 at 9:54

4 Answers 4

3

Regular expressions would be messy. It's much easier to go through with a simple counter.

function parenthesesBalanced(string) {
    var count = 0;

    for (var i = 0, l = string.length; i < l; i++) {
        var char = string.charAt(i);

        if (char == "(") {
            // Opening parenthesis is always OK
            count++;
        } else if (char == ")") {
            // If we're at the outer level already it's not valid
            if (count == 0) return false;
            count--;
        }
    }

    return (count == 0);
}
Sign up to request clarification or add additional context in comments.

5 Comments

This code assumes that EVERY parenthesis counts. However, it might be necessary to ignore parentheses in quotes or comments.
Quoted strings or comments are out of the scope of this function. DEN didn't indicate he was concerned about that at all, and if it turns out he does some earlier parsing would be required - whether it's done with regular expressions or character-by-character. A comment boolean and balance-tracking stack would then be the logical way of doing it (then square bracket and curly braces could also be checked easily).
thanks for the replied chris, but i found out there are some weakness. If the user input --> )orange and pen( which is not right, should return false too. It works fine in your code . Do u have any idea on it?
@DEN: to fix that just check if count is less than zero after decrementing.
@DEN: it is right, see the if (count == 0) check? That makes it valid. Try it and you'll see it returns false for ")orange and pen(".
1

replace every group of "left paren - some chars - right paren" with nothing, until there is no more groups. If the resulting string contains a parenthesis, the parens were not balanced.

balancedParens = function(str) {
    var q;   
    do {
      q = str;
      str = str.replace(/\([^()]*\)/g, '');
    } while(q != str);
    return !str.match(/[()]/);
}

    a = "foo ((and) bar and (baz) quux) and (blah)";
    b = "(dddddd()";

alert(balancedParens(a))
alert(balancedParens(b))

http://jsfiddle.net/gvGGT/

It's not possible to match a balanced string with a single regexp in javascript, because JS dialect doesn't support recursive expressions.

Comments

1

It is a known hard problem to match parens with regular expressions. While it is possible, it's not particularly efficient.

It's much faster simply to iterate through the string, maintaining a counter, incrementing it every time you hit an open paren, and decrementing it every time you hit a close paren. If the counter ever goes below zero, or the counter is not zero at the end of the string, it fails.

4 Comments

It's not even possible. Some implementations (eg. the one in .net) offer non-regular extensions to the regular expression language to allow it, but the one in JavaScript does not.
Really? I thought that regular expressions could match all CFLs, and paren matching is a classic example of a CFL.
Paren matching (to do it properly like the OP wants) is non regular for the same reason that HTML is non regular: they are recursive. I believe Perl6 regex can do it but Perl6 regex is not regexp (they even note it in the docs that it should be called regex instead of regexp or regular expression). I very much suspect that Perl6 regex may even be turing complete :-P
I had forgotten the difference between regular languages and CFLs, you are correct.
0

I made a node library call balanced to make this a bit more sane, if you wanted to just get balanced outer matches you can do this

balanced.matches({source: source, open: '(', close: ')'})

my use case was a bit more complicated, and required me to do replacements and support comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.