3 years ago, I wrote this post: http://regexlib.com/REDetails.aspx?regexp_id=1135.
It contained a .Net regular expression that would match the highest level of matching braces, something that is needed more often than not when parsing languages. It will also return null if no matching braces are found. Finally, as an added bonus, it will ignore braces that are escaped with a backslash.
Soon after I posted it, someone commented on it being impossible, because Finite Automatas can’t count. I didn’t want to fight it (and I didn’t know better), so I simply made a wrong statement that would divert the discussion. I simply knew that it worked back then. I’m wiser now, and I know the answer.
FAs are used to parse regular languages and as such, they can’t count. That’s absolutely true. That means that you can’t keep track of what you’ve seen by using a FA. So, if you need to match a symmetrical phrase (aabbccbbaa), you can’t. That’s what Push-down automatas are used for.
Problem is, .Net regular expressions don’t work as a regular language. When you start using backtracking and lookahead, you’re automatically out of the regular language domain. And then, Finite Automatas can’t be used anymore.
So, if you need to count, you can always use a backtrack. You can use them to search for a palindrome (http://aspn.activestate.com/ASPN/Cookbook/Rx/Recipe/326097) and you can use them to search for matching braces.
As an added bonus, here’s how you do different braces with the regex:
Curly ({}): (?<!\\)\{(\\\{|\\\}|[^\{\}]|(?<!\\)\{.*(?<!\\)\})*(?<!\\)\}
Parenthesis (()): (?<!\\)\((\\\(|\\\)|[^\(\)]|(?<!\\)\(.*(?<!\\)\))*(?<!\\)\)
Square ([]): (?<!\\)\[(\\\[|\\\]|[^\[\]]|(?<!\\)\[.*(?<!\\)\])*(?<!\\)\]
Chevrons (<>): (?<!\\)\<(\\\<|\\\>|[^\<\>]|(?<!\\)\<.*(?<!\\)\>)*(?<!\\)\>
Hope you find it useful!