2

I'm trying to parse mathematical expressions with nested brackets:

(1 * (2 - 3)) + 4

I want to get every expression in brackets, like this:

  • (1 * (2 - 3))
  • (2 - 3)

Using this expression: (.*?\))(?=($|[^(]+)) I'm getting this result:

(1 * (2 - 3)

)

And using this expression: \(.*?\) I'm getting this result:

(1 * (2 - 3) 

But nothing works correctly. How can I loop an expression inside?

Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563

2 Answers2

2

You can use

(?=(\((?>[^()]+|(?<c>)\(|(?<-c>)\))*(?(c)(?!))\)))

See the regex demo. Details:

  • (?= - a positive lookahead:
    • (\((?>[^()]+|(?<c>)\(|(?<-c>)\))*(?(c)(?!))\))) - Group 1:
      • \( - a ( char
      • (?>[^()]+|(?<c>)\(|(?<-c>)\))* - zero or more repetitions of any one or more chars other than ( and ), or a ( char (with a value pushed onto Group "c" stack), or a ) char (with a value popped from the Group "c" stack)
      • (?(c)(?!)) - if Group "c" stack is not empty, fail and backtrack
      • \) - a ) char.

See the C# demo:

var text = "(1 * (2 - 3)) + 4";
var pattern = @"(?=(\((?>[^()]+|(?<c>)\(|(?<-c>)\))*(?(c)(?!))\)))";
var results = Regex.Matches(text, pattern)
    .Cast<Match>()
    .Select(m => m.Groups[1].Value)
    .ToList();
Console.WriteLine(String.Join(", ", results));
// => (1 * (2 - 3)), (2 - 3)
Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
-1

The usual way would be to use a recursive regular expression but unfortunately this capability is not supported by C#'s Regex. Alternatively, you can manually parse the string (and there is C# code provided in this PAQ to do that).

gordy
  • 9,360
  • 1
  • 31
  • 43
  • Please don't link to existing answers like this. If this question is a duplicate of the other, then mark it as so. – Enigmativity Apr 19 '21 at 21:10
  • @Enigmativity is there a community guideline for this? it's not a duplicate question since they asked specifically how to do this via regex but the answer is probably relevant - I thought linking would be better than copying and pasting the answer here since the context is probably also useful – gordy Apr 19 '21 at 21:14
  • Unless you have something substantive in your answer (i.e. it can stand alone) then it should be a comment. Does "C#'s Regex doesn't support recursive expressions, I suggest parsing this manually" answer this question? – Enigmativity Apr 19 '21 at 21:17
  • https://meta.stackoverflow.com/questions/265552/when-to-flag-an-answer-as-not-an-answer – Enigmativity Apr 19 '21 at 21:19