4

I want to replace a function definition and declaration using Regex, i.e.,

replace

public abstract void myFuction(MyParam myParam);

or

@Override
public void myFuction(MyParam myParam){

}

I tried with this regex:

(@Override[\n\s\t]*)?public *(abstract)? *void
*generateProcessMethod *\(UIGenerationContext *[^)]+\)[\n\\s\t]*((\{[^{}]*?\})|;)

But the problem is if the function has any other { or } then it will not work.

Replacing [^{}] with . is not a solution as it replaces the following functions also.

acdcjunior
  • 132,397
  • 37
  • 331
  • 304
Abin Manathoor Devasia
  • 1,945
  • 2
  • 21
  • 47

3 Answers3

6

Using regular expressions, this (bracket nesting) does can be done, but only up to a fixed level of nesting.

Your current regex (changed a bit):

(@Override[\n\s\t]*)?public *(abstract)? *void *[a-z]*\([a-z]* [^)]+\)[\n\\s\t]*((\{[^\{\}]*?\})|;)

Only allows one level. More specifically, this is the part that matches it:

(\{[^\{\}]*?\})

If you wanted to match up to two levels, change the mentioned part to:

(\{([^{}]*|\{[^{}]*\})*\})

Thus:

(@Override[\n\s\t]*)?public *(abstract)? *void *[a-z]*\([a-z]* [^)]+\)[\n\\s\t]*(\{([^{}]*|\{[^{}]*\})*\}|;)

To add more levels, you have to keep editing. It will get messier and messier as you add levels.

Explanation:

  • \{ will match the first opening bracket
    • ( opens a group
      • [^{}]* matches anything other than brackets
      • | or
      • \{ if it does find an opening bracket...
        • [^{}]* ...it will match anything other than a bracket...
      • \} ...until it finds a closing bracket
    • ) closes the group
    • * the above group can happen zero or more times
  • \} matches the ending bracket

To add more levels, change the middle (second) [^{}]* part to ([^{}]*|\{[^{}]*\})*.

If you can't predict the maximum nesting level:

There are some languages that allow the nesting operator R, which allows you to nest arbitrary number of levels. If your language does not support it (Java doesn't, afaik PHP and Perl do), you'll have to either:

  • predict the maximun nesting level; OR
  • create a parser yourself.

Regular expressions, without the R operator, cannot nest an arbitrary number of levels.

That said, using the R operator would be as such:

(\{([^{}]|(?R))*\})

More info at this answer.

Community
  • 1
  • 1
acdcjunior
  • 132,397
  • 37
  • 331
  • 304
  • i cant add each level.. because i have multiple files having same function- some times the function has may opening and closing(eg.. for while loops or grouping) it depends on how the function implemented here, i can only guess function has same name and parameter and `{` `}`. – Abin Manathoor Devasia Apr 11 '13 at 05:37
  • If you can determine the maximum nesting level, you can use this solution. – Kyle Strand Apr 11 '13 at 05:37
  • There are some languages that allow the nesting operator `R`, which allows you to nest arbitrary number of levels. If your language does not support it (Java doesn't, afaik PHP and Perl do), you'll have to either predict the maximun nesting level OR create a parser yourself. Regex, without the `R` operator, **cannot** nest an arbitrary number of levels. – acdcjunior Apr 11 '13 at 05:44
1

Regex is not good at dealing with nested components. However, if you know for a fact that @Override will be indented the same as the closing brace and all of its contents are indented further, you can use this:

([\t\s]+)@Override.*?\n\1}
Explosion Pills
  • 188,624
  • 52
  • 326
  • 405
  • i cant simply add this.. i want to do the same for some other files having same definition , with change in position – Abin Manathoor Devasia Apr 11 '13 at 05:26
  • @Abin, just because you want something doesn't mean RegEx can accomplish it. I mean, it *is* pretty magical, but...there are limitations, sadly, and this is probably the biggest one. – Kyle Strand Apr 11 '13 at 05:37
0

I am afraid this is not possible using only RegExpressions.

If understand you right you need to reformat some syntax and I assume the code must still be compilable, in this case you will need to counter which increases for each { and decreases for each } so you know when the function ends. An alternative could be to go back to the first found } once you face the next declaration, but there would be a lot of exceptions to handle like when the class ends etc...

I suggest you use a Java source parses for that job, it would be able to recognize a method as a method and would spare you a lot of work, take a look at javaparser for example

BenMorel
  • 34,448
  • 50
  • 182
  • 322
CloudyMarble
  • 36,908
  • 70
  • 97
  • 130