Я пытаюсь написать простой парсер шаблонов 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:
- Пропустить условие, если значение переменной не существует или содержит ложное значение.
- Должен поддерживать вложенные условия.
К сожалению, мое понимание регулярных выражений очень ограничено, мне удалось построить простое регулярное выражение (возможно, менее приемлемое), поэтому в основном мне нужно поддерживать условия, которые можно записать в этом формате.
{если что-то} что-то {/ if}
Как вы можете видеть из кода, я привел пример, где сообщение содержит две не связанные переменные и есть переменная 'external', которая содержит две другие, если условия вложены друг в друга.
Когда все переменные содержат истинные значения, кажется, что все работает должным образом, но если вы установите переменную на ложное значение и если эта переменная вложена внутрь, тогда текст в переменной $ message не анализируется должным образом. Я получаю дополнительный ненужный закрывающий тег {/ if}.
Когда я проверил место, где он проверяет, является ли значение переменной пустым, я заметил, что он не дал мне нужную часть блока условий if, чтобы я мог найти и заменить оператор if, где условие не истинно.
Я думаю, что мое регулярное выражение неверно, но я не уверен, возможно ли сделать это с помощью регулярных выражений того, что я спрашиваю, должен ли я попробовать другой новый подход, или есть только одно небольшое исправление, которое требует быть готовым?
По крайней мере, я хотел бы знать правильный алгоритм, как решить эту проблему с учетом указанных выше требований.
Заранее благодарим вас за всю информацию, которую вы можете предоставить мне.