0

I have a simple template system and a regular expression catch some specials tags like if conditions. now I need an if condition inside an if condition and my current expression breaks on the first if-endtag.

I tried (?R) and some other but either I don't get any HTML tags inside the brackets or they break on the first /#if

{{{#if(.*?)}}}(.*?){{{\/#if}}}

and my HTML code

{{{#if:header:!=:}}}
    <div class="header">
        <h1>
                {{{header}}}
                {{{#if:header_bar:!=:}}}
                    <div class="headbuttons">
                        {{{header_bar}}}
                    </div>
                {{{/#if}}}
            </h1>
        </div>
    {{{/#if}}}

expected ist one return from #if:header:!=:}}} to the second /#if

can someone help me please to get this work?

Sayed Mohd Ali
  • 2,004
  • 3
  • 8
  • 25
  • This does not look like PHP code. Are you using a template engine or another framework? Laravel, maybe? – tshimkus Feb 12 '19 at 10:18
  • 3
    You're probably better off learning a more flexible mechanism, like a Lexer+Parser pipeline, as regexes are not really suited for detecting this kind of complex nesting. It might be possible, but it's going to get buggy and hard to manage pretty soon. – IMSoP Feb 12 '19 at 10:19
  • @tshimkus I think the text in the question is sample input for testing the regex against. – IMSoP Feb 12 '19 at 10:20
  • correct this is a snippet which shows the context and working. there is no framework. so there is no "simple" way to get the if syntax recursive? but is this not the same thing as try to catch some nested div from a string? –  Feb 12 '19 at 10:33
  • 1
    perhaps this answer to an other question could help you : https://stackoverflow.com/a/35271017/3992945 but as stated by @IMSoP using a regex is probably not the best way to handle this kind of structures. Also you can have a look at existing template engines (such as twig or smarty) to see haw they handle this – ᴄʀᴏᴢᴇᴛ Feb 12 '19 at 10:34

1 Answers1

0

I tried (?R) …

(?R) works; instead of the simple if-body (.*?) we can use an alternation with the recursive pattern .*?(?R).*? on one side and the simple pattern .*? on the other side: (.*?(?R).*?|.*?). Sample:

preg_match('/{{{#if(.*?)}}}(.*?(?R).*?|.*?){{{\/#if}}}/s', '
{{{#if:header:!=:}}}
    <div class="header">
        <h1>
                {{{header}}}
                {{{#if:header_bar:!=:}}}
                    <div class="headbuttons">
                        {{{header_bar}}}
                    </div>
                {{{/#if}}}
            </h1>
        </div>
    {{{/#if}}}', $matches);
echo $matches[0], "\n";

Output:

{{{#if:header:!=:}}}
    <div class="header">
        <h1>
                {{{header}}}
                {{{#if:header_bar:!=:}}}
                    <div class="headbuttons">
                        {{{header_bar}}}
                    </div>
                {{{/#if}}}
            </h1>
        </div>
    {{{/#if}}}
Armali
  • 14,228
  • 13
  • 47
  • 141