1

I need to run an important check over multiple PHP files with the following regex:

\$this\->(m_\w+)(?!(.|\v)*private \$\1)

But my IDE (Sublime Text 2) says that it runs out of stack space while trying to match the regex. It works fine with very small files though, but none of the files I need to check is small enough. So how the regex can be optimized to let it work on text of any length?

Desmond Hume
  • 8,037
  • 14
  • 65
  • 112
  • What's that pattern - `(.|\v)` - for? `\v` is `.`, after all. – raina77ow Dec 18 '13 at 10:55
  • One possible option is to make `+` quantifier (in `\w+`) possessive (with `+` modifier, or with `?>` operator, whatever Sublime supports. – raina77ow Dec 18 '13 at 10:57
  • @raina77ow `\v` matches a newline of any form, `.` doesn't match newlines by default, so `(.|\v)` matches any character including newlines – Desmond Hume Dec 18 '13 at 10:58
  • Erm.. ain't that `/s` modifier's purpose? Or, if that's not supported, character class - `[\s\S]`, for example? I'm asking, because it's rather strange seeing alternation doing class's work - and because I considered `\v` to be a perlish feature. But if that's working, no problem: engine should optimize this anyway. – raina77ow Dec 18 '13 at 10:59
  • @raina77ow there's no `/s` modifier in Sublime and `[\s\S]` feels bit more weird than `(.|\v)` to me, at least now, maybe gonna employ it in the future, thanks – Desmond Hume Dec 18 '13 at 11:03
  • @raina77ow was trying `?>` around the capture and adding a `\b` after `\w+`, neither worked.. – Desmond Hume Dec 18 '13 at 11:12
  • Define 'neither worked'. Have you changed `(.|\v)` to `[\s\S]` as well? It's not about 'feeling' actually: it's about capturing group as well. – raina77ow Dec 18 '13 at 11:16
  • ok, there are some small things you could fix: `(?s)\$this->(m_\w+)(?!.*?private\s*\$\1)`. `(?s)` will set the `s` modifier to match newlines with `.`, I made the lookahead ungreedy by using `*?` – HamZa Dec 18 '13 at 11:19
  • 1
    `(.|\v)` may feel less weird than `[\s\S]`, but it's the `(.|v)` that's killing your performance. See [Javascript regex hangs (using v8)](http://stackoverflow.com/questions/2407870/javascript-regex-hangs-using-v8) for the explanation. – Alan Moore Dec 18 '13 at 12:40

1 Answers1

4

You can increase your pattern speed using this:

\$this->(m_\w++)(?!(?>[^p]++|\Bp++|p(?!rivate \$\1\b))++private \$\1\b)
Casimir et Hippolyte
  • 88,009
  • 5
  • 94
  • 125
  • The first edition was producing false matches but the current is awesome, wow, thank you so much! – Desmond Hume Dec 18 '13 at 11:48
  • This is simply awesome!! It took me little while to grasp the suggested changes. Truly amazing... sad can't do more than +1 – anubhava Dec 18 '13 at 12:13