Создание обработчика шаблонов в PHP (проблема с отрицательным взглядом вперед) - PullRequest
0 голосов
/ 15 августа 2011

Я разрабатываю небольшой обработчик шаблонов на PHP, например, smarty, гораздо более простой Я использовал умный раньше, но это было слишком крепким для меня. Я думал, что я готов с моим, но действительно раздражающая ошибка обнаружилась. Моя концепция проста. Я использую preg_split для разделения шаблонных команд и HTML-кода, обработки и взрыва. команда {foreach} работает очень хорошо, поэтому я не буду об этом упоминать, ошибка появляется в предложении {if}. "{If} часть" регулярного выражения:

{if\s+[a-zA-Z0-9\{'\}\=\s\/$\!\=]{1,}\s*}

Проблема в том, что мне нужно разрешить фигурные скобки из-за подстановки переменных, и это заставляет регулярное выражение не останавливаться в конце "{if **}". Я пытался смотреть в будущее с негативным прогнозом и отвергать прогноз с позитивным прогнозом, чтобы исключить "{если", чтобы избежать проблемы, но мне не повезло.

Пример для шаблона:

{if '{$a}' = 'a'}
    blabla
    {if 'c' = 'c'}
        blabla
    {/if}
{/if}
valami más
{if 'b' != 'b'}
    blabla
{/if}
{if '{$c}' = '{$c}'}
    blabla
{/if}

Ожидаемый результат:

{if '{$a}' = 'a'}
{if 'c' = 'c'}
{if 'b' != 'b'}
{if '{$c}' = '{$c}'}

Может ли кто-нибудь помочь, пожалуйста?

1 Ответ

1 голос
/ 15 августа 2011

Основываясь на вашем описании выше, я создал следующее регулярное выражение. Я надеюсь, что это то, что вы ищете.

<code><?php

$string = <<<'EOD'
{if '{$a}' = 'a'}
blabla
{if 'c' = 'c'}
    blabla
{/if}
{/if}
valami más
{if 'b' != 'b'}
blabla
{/if}
{if '{$c}' = '{$c}'}
blabla
{/if}
EOD;

$pattern = "~{if\s+'(?:\\{\\$(?:[A-Za-z0-9]+\\})|(?:[A-Za-z0-9]))'\s+(?:=|(?:!=))\s+'(?:(?:\\{\\$(?:[A-Za-z0-9]+\\}))|(?:[A-Za-z0-9]))'\\}~";

preg_match_all($pattern, $string, $matches);

echo '<pre>'.print_r($matches,1).'
'; ?>

Выходы:

Array
(
    [0] => Array
    (
        [0] => {if '{$a}' = 'a'}
        [1] => {if 'c' = 'c'}
        [2] => {if 'b' != 'b'}
        [3] => {if '{$c}' = '{$c}'}
    )

)

Обновленный ответ

Имея в виду следующие комментарии, я создал следующее регулярное выражение. Я признаю, что это далеко не лучшее решение, но оно позволяет учесть такие аргументы, как {if '{$c}' = '{$c}' && '{$b}' = '{$b}'}. Вы можете просто продублировать шаблон, чтобы включить более двух выражений в одном операторе if. Очевидно, это тогда вырастет до смешной длины! Однако, если это для шаблонного движка, возможно, ему не понадобится много расширяться? Любые другие требуемые операторы также могут быть просто добавлены в регулярное выражение в соответствующем месте.

Еще раз, я знаю, что это не лучший способ решения проблемы; Извините, я не могу создать рекурсивную версию самостоятельно. Возможно, кто-то еще сможет это сделать!

$pattern = "~{if\s+(?:(?:'(?:\\{\\$(?:[A-Za-z0-9]+\\})|(?:[A-Za-z0-9]))'\s+(?:=|(?:!=)|(?:==)|(?:<=)|(?:>=))\s+'(?:(?:\\{\\$(?:[A-Za-z0-9]+\\}))|(?:[A-Za-z0-9]))')(?:(?:\s+(?:&&|\\|\\|)\s+)(?:'(?:\\{\\$(?:[A-Za-z0-9]+\\})|(?:[A-Za-z0-9]))'\s+(?:=|(?:!=)|(?:==)|(?:<=)|(?:>=))\s+'(?:(?:\\{\\$(?:[A-Za-z0-9]+\\}))|(?:[A-Za-z0-9]))'))?)\\}~";

Проверено на:

$string = <<<'EOD'
{if '{$a}' = 'a'}
blabla
{if 'c' = 'c'}
blabla
{/if}
{/if}
valami más
{if 'b' != 'b'}
blabla
{/if}
{if '{$c}' = '{$c}'}
blabla
{/if}
{if '{$c}' = '{$c}' && '{$b}' = '{$b}'}
EOD;

Результат:

Array
(
[0] => Array
    (
        [0] => {if '{$a}' = 'a'}
        [1] => {if 'c' = 'c'}
        [2] => {if 'b' != 'b'}
        [3] => {if '{$c}' = '{$c}'}
        [4] => {if '{$c}' = '{$c}' && '{$b}' = '{$b}'}
    )
)
...