PHP шаблонизатор, если анализатор условий - PullRequest
0 голосов
/ 31 октября 2018

Я пытаюсь написать простой парсер шаблонов PHP для целей обучения и пытаюсь реализовать логику условий, мой парсер будет очень ограниченным, но это нормально, я просто заинтересован в достижении того, что я решил сделать.

Вот код:

$pat = '/{if (\b[A-Za-z0-9_]+\b)}(.*?){\\/if}/s';

$message = '{if another}Another{/if} {if outer}Outer {if inner}Inner {if innermost}Innermost{/if}{/if}{/if}';
$vars = ['another' => false, 'outer' => true, 'inner' => true, 'innermost' => true];

while (preg_match_all($pat, $message, $m)) {
    foreach ($m[1] as $n => $key) {
        $all = $m[0][$n];
        $text = $m[2][$n];

        if (!isset($vars[$key]) || empty($vars[$key])) {
            $message = str_replace($all, '', $message);
              } else {
                  $message = str_replace($all, $text, $message);
              }
          }
      }

      echo $message;

Требования к парсеру для условий if:

  1. Пропустить условие, если значение переменной не существует или содержит ложное значение.
  2. Должен поддерживать вложенные условия.

К сожалению, мое понимание регулярных выражений очень ограничено, мне удалось построить простое регулярное выражение (возможно, менее приемлемое), поэтому в основном мне нужно поддерживать условия, которые можно записать в этом формате.

{если что-то} что-то {/ if}

Как вы можете видеть из кода, я привел пример, где сообщение содержит две не связанные переменные и есть переменная 'external', которая содержит две другие, если условия вложены друг в друга.

Когда все переменные содержат истинные значения, кажется, что все работает должным образом, но если вы установите переменную на ложное значение и если эта переменная вложена внутрь, тогда текст в переменной $ message не анализируется должным образом. Я получаю дополнительный ненужный закрывающий тег {/ if}.

Когда я проверил место, где он проверяет, является ли значение переменной пустым, я заметил, что он не дал мне нужную часть блока условий if, чтобы я мог найти и заменить оператор if, где условие не истинно.

Я думаю, что мое регулярное выражение неверно, но я не уверен, возможно ли сделать это с помощью регулярных выражений того, что я спрашиваю, должен ли я попробовать другой новый подход, или есть только одно небольшое исправление, которое требует быть готовым?

По крайней мере, я хотел бы знать правильный алгоритм, как решить эту проблему с учетом указанных выше требований.

Заранее благодарим вас за всю информацию, которую вы можете предоставить мне.

1 Ответ

0 голосов
/ 31 октября 2018

Вы не можете сделать это с помощью регулярного выражения, хотя большинство движков имеют мощные расширения, и некоторые могут позволить вам сделать это. См. этот вопрос для получения подробной информации о сопоставлении вложенных структур. См. Также этот ответ об ограничениях регулярных выражений.

«Правильный» способ сделать это с помощью парсера. Введение в синтаксический анализ слишком велико для ответа StackOverflow. Я рекомендую прочитать Инженерное дело: Компилятор или что-то более легкое (и бесплатное) Давайте создадим компилятор или Создание интерпретаторов .

Основной подход заключается в том, чтобы найти грамматику для шаблона (или, если это не удалось, восстановить ее самостоятельно) и определить лексические элементы или токены. То есть вы можете использовать регулярное выражение для сопоставления {if var_name}, {/if} и обычного текста, а затем работать с этими элементами. Проблема становится намного легче, когда у вас есть это разделение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...