2

I'm searching for a regex to match all C# methods in a text and the body of each found method (refrenced as "Content") should be accessible via a group.

The C# Regex above only gives the desired result if there exists exactly ONE method in the text.

Source text:

void method1(){

if(a){ exec2(); }   
else {  exec3(); }  

}

void method2(){

if(a){ exec4(); }   
else {  exec5(); }  

}

The regex:

string pattern = "(?:[^{}]|(?<Open>{)|(?<Content-Open>}))+(?(Open)(?!))";
MatchCollection methods  = Regex.Matches(source,pattern,RegexOptions.Multiline);
 foreach (Match c in methods)
 {
    string body = c.Groups["Content"].Value; // = if(a){ exec2(); }else {  exec3();}
    //Edit: get the method name
    Match mDef= Regex.Match(c.Value,"void ([\\w]+)");
    string name = mDef.Groups[1].Captures[0].Value;
 }

If only the method1 is contained in source, it works perfectly, but with additional method2 there is only one Match, and you cannot extract the individual method-body pairs any more.

How to modify the regex to match multiple methods ?

fritz
  • 427
  • 1
  • 5
  • 13
  • http://stackoverflow.com/questions/4310828/net-c-sharp-regex-for-parsing-method-property-chain-calls – Eser Aug 20 '15 at 08:33
  • What if you have comments in between that contain `{` or `}`? Or string literals containing the braces? Then, this approach will not be valid. – Wiktor Stribiżew Aug 20 '15 at 08:38
  • Can you explain what you want to capture exactly ? Content is the content of the method and Open is what ? Do you need the method definition ? – Ronan Lamour Aug 20 '15 at 08:41
  • @Lamour: See my edit – fritz Aug 20 '15 at 08:48
  • @stribizhev: let's assume there are no strings or comments – fritz Aug 20 '15 at 08:50
  • @fritz What about lambdas. How many methods are here in this example **`void method3() { Func method4 = s => s.Split(); var x = method4("a b c"); }`** – Eser Aug 20 '15 at 08:56
  • @fritz And also this **`public override string ToString() => "test";`** – Eser Aug 20 '15 at 08:57
  • @Eser He's asking for help with a specific problem with his specific use case. Do you have to complicate things with other perceived problems? – Rawling Aug 20 '15 at 08:58
  • I have [a sample regex](http://regexstorm.net/tester?p=(%3f%3cmethod_name%3e%5cw%2b)%5cs*%5c(.*%3f%5c)%5cs*(%3f%3cmethod_body%3e%5c%7b(%3f%3e%5b%5e%7b%7d%5d%2b%7c(%3f%3cnumber%3e%5c%7b)%7c%7d(%3f%3c-number%3e))*(%3f(number)(%3f!))%7d)&i=void+method1()%0d%0a%7b%0d%0a%0d%0aif(a)%7b+exec2()%3b+%7d+++%0d%0aelse+%7b++exec3()%3b+%7d++%0d%0a%0d%0a%7d%0d%0a%0d%0avoid+method2(string+a)%7b%0d%0a%0d%0aif(a)%7b+exec4()%3b+%7d+++%0d%0aelse+%7b++exec5()%3b+%7d++%0d%0a%0d%0a%7d&o=m) that will match basic examples as yours. No idea if it is any good anyway. – Wiktor Stribiżew Aug 20 '15 at 08:58
  • 1
    @stribizhev: Great! You can put this as answer. Indeed I'm not searching for gerneral solution or parser to find all kind of methods, I know what constructs may occur in my text. – fritz Aug 20 '15 at 09:04

1 Answers1

3

Assuming you only want to match basic code like those samples in your question, you can use

(?<method_name>\w+)\s*\((?s:.*?)\)\s*(?<method_body>\{(?>[^{}]+|\{(?<n>)|}(?<-n>))*(?(n)(?!))})

See demo

enter image description here

To access the values you need, use .Groups["method_name"].Value and .Groups["method_body"].Value.

Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
  • I shortened the balanced construct name a bit to reduce the pattern size. I also made sure to capture several lines in the method signature - if any - by means of the internal singleline modifier `(?s:)`. If my answer is helpful, please consider also upvoting it. – Wiktor Stribiżew Aug 20 '15 at 09:12