Martin Smola
Martin Smola

Reputation: 13

How to parse the most nested IF statement via Regex in PHP

I work with @if|@else|@endif statement in my HTML code and I need find most nested statement/condition (a condition that don't contain another condition) via preg_replace_callback() function.

When function resolve the condition on last level, it start again with parent IF statement as long as all conditions/IF statements will be solved.

In every iteration I need find the actual most nested conditions.

This is example of my HTML code:

  @if($i%2 == 0)

     <something html> 

        @if($i==2)

           <something html>

           @if($i == 0)

              <something html>

           @endif

        @endif

     <something html>

  @else 

     <something html>

        @if($i==2)

           <something html>

        @endif

     <something html>

  @endif

I try something like:

$pattern = '/@if\s*\(\s*(.*)\s*\)\s*((?!@if|@endif).*)\s*(?:@else\s*((?!@if|@endif).*))?\s*@endif/s';

Thank you in advance for your help.

Upvotes: 1

Views: 378

Answers (1)

lambda
lambda

Reputation: 89

Your attempt has two problems:

  1. The first capturing group matches the rest of the input: "(.)". You need to exclude the closing parens of the if-condition: "([^)])".
  2. The negative look-ahead on @if and @endif only works for the very first character. After that, it matches the rest of the input with ".". The correct nesting here is "((?!...).)".

This gives the following regex:

@if\s*\(\s*([^)]*)\s*\)\s*(((?!@if|@endif).)*)\s*(?:@else\s*(((?!@if|@endif).)*))?\s*@endif

But please note that this only works if the if-conditions do not contain expressions with parenthesis. If they can contain arbitrarily nested parenthesis, you are screwed. (You probably know this, but regex can not count an arbitrary level of nesting, you need a stack for that).

I used this to help figure out your problem: https://regex101.com/

Upvotes: 1

Related Questions