2

I have Javascript files containing functions of the form:

function xyz(a,b,c,...){
....
}

I want to change them to the following form for the sake of Typescript migration:

private xyz(a,b,c,...){
....
}

I could use "function(.*)\(.*\)" but if there are nested functions, I need to leave them unchanged.

What would be the proper C# RegEx for this?

Wai Ha Lee
  • 8,598
  • 83
  • 57
  • 92
John L.
  • 1,825
  • 5
  • 18
  • 45
  • 2
    I assume you've read https://stackoverflow.com/questions/133601/can-regular-expressions-be-used-to-match-nested-patterns already... if not - good stating point... Probably https://stackoverflow.com/questions/19596502/regex-nested-parentheses can even be used as duplicate. – Alexei Levenkov Feb 24 '19 at 22:55

3 Answers3

0

Match: function (.+{.*(.*{(?2)}.*)*.*?}) with the multiline parameter on

Then replace with: private \1

This RegEx matches the function entirely, including any nested functions/if statements etc, so you can replace only the outermost one.

Explanation

function                Matches function keyword
         (              Starts capture group
          .+            Matches function name and parameters
            {           Opens function
             .*         Matches any code in function
               (        Starts new capture group (2) for catching internal curly braces
                .*      Matches any code in function
                  {     Matches opening curly brace
                   (?2) Matches capture group (2), to match any code and curly braces inside
                  }     Matches closing curly brace
                .*      Matches any code
              )*        Closes capture group (2) and allows it to be repeated
           .*?          Matches any code, until next curly brace
          }             Matches closing curly brace
         )              Closes capture group

Note that the recursion ((?2)) is not supported in .net by default, so you'll have to use another RegEx-Engine for C#, such as PCRE for .Net.

If you don't want to use another engine, you can replace the (?2) with (.*{(?2)}.*)* recursively as deep as you want, as to match nested if loops etc., and finally replace the (?2) with .*. The result should look something like this: function (.+{.*(.*{(.*{(.*{(.*{(.*{(.*{(.*)}.*)*}.*)*}.*)*}.*)*}.*)*}.*)*.*?})

blenderfreaky
  • 738
  • 7
  • 26
  • Could you please provide the expression that I can try on http://regexstorm.net/tester? – John L. Feb 25 '19 at 00:19
  • I'm quite sure you are missing both types of strings that can be used inside TypeScript/JavaScript code - `'}'` and `"}"` in your regex similar to the other answer https://stackoverflow.com/a/54857054/477420... Also this one have some chance to built complete parser :) – Alexei Levenkov Feb 25 '19 at 00:30
  • I tried function (.+{.*(.*{(.*{(.*{(.*{(.*{(.*{(.*)}.*)*}.*)*}.*)*}.*)*}.*)*}.*)*.*}) but it takes the following functions too, until the last "}" character it sees. – John L. Feb 25 '19 at 00:59
  • Didn't think about that. Try this: function (.+{.*(.*{(.*{(.*{(.*{(.*{(.*{(.*)}.*)*}.*)*}.*)*}.*)*}.*)*}.*)*.*?}) – blenderfreaky Feb 25 '19 at 02:23
-1

It may be as simple as matching:

/^function/gm

Provided your top-level functions have no indentation (demo). Or if they are indented to, say, one tab or 4 spaces you could use:

/^\tfunction/gm    or    /^    function/gm

This uses the start of line anchor (^).

Callum Watkins
  • 2,844
  • 4
  • 29
  • 49
-2

This would work for you

 var src = @"function xyz(a,b,c,...){
   function abc(){
   }
 }";  
 var pattern = @"\s*function\s*(?=\w+\(\w+|,\)\s*\{.+?})";

var result = Regex.Replace(src, pattern, "private ", RegexOptions.Multiline);
result.Dump();

Check This

PS: you need to enable MultiLine option

Derviş Kayımbaşıoğlu
  • 28,492
  • 4
  • 50
  • 72