Вложенность конструкций. Regexp (регулярные выражения).

программирование regexp mvc preg_match регулярные-выражения

Доброго время суток. При разработке своего "легковесного" шаблонизатора, ал-я CMF MODx, столкнулся с проблемой вложенности конструкций.

То, что скармливаем (упрощённая для восприятия конструкция):

[[SNIPPET_1
:if
&is=`var`
&then=`[[$CHUNK_1
:if
&is=`var`
&then=`[[SNIPPET_2
:filter
&name=`var`
]]`
]]`
&else=`[[CHUNK_2:upper]]`
:filter
&name=`var`
]]

:if, :filter – фильтры (модификаторы), а &is, &name… - переменные фильтров. Переменные фильтров (&is=var), как можно догадаться должны содержать всё что угодно: от простой строки до html-кода приправленного переменными шаблона (сниппетами, чанками и т.д.)

Проблема заключается в том, как закрыть в данном случае [[SNIPPET_1]], при наличии в нём других переменных шаблона. Стоить заметить, что [[SNIPPET_1]] имеет два применённых к нему фильтра: :if и :filter. Это тоже необходимо учитывать.

Было бы чудесно распарсить данную конструкцию, КАК ЕСТЬ (т.е. учитывать и перевод строки – удобство восприятия)

Собственно, regexp pattern, который применён в проекте:

preg_replace_callback(
'/\[{2}([\$\*\@\%\~]?|\+{1,2})([\w-\.]+)\s*((?:\:[\w]+\s*(?:\s*\&[\w]*\=`(?:.[^\n]*)`)*\s*)*)\s*\]{2}/iu',
function ($call) { },
$subject
)
Выделяет отдельно название переменной шаблона (SNIPPET_1, CHUNK_1, SNIPPET_2…), его тип ("" - сниппет, "$" - чанк, "~" - ссылка…) и фильтры с их содержимым (:if&is=var&then=[[$CHUNK_1]] :filter&name=var). В данном случае, [^\n] является заглушкой, т.е. содержимое переменной фильтра пишется в одну строку без переходов на следующую, чтобы определяет конец переменной фильтра, а именно: &then=[[$CHUNK_1:if&is=var&then=[[SNIPPET_2:filter&name=var]]]] Согласитесь, не очень читабельно получается. Далее парсится в массив конструкция фильтров. Определяется имя фильтра (if, filter…) и переменные каждого фильтра. Regxp pattern:

preg_match_all('/\:([\w]*)((?:\s*\&[\w]*\=`(?:.[^\n]*|)`\s*)*)/iu', $call[3], $found);
И в заключении, цикличный пробег по каждому из фильтров и выполнение функции (соответствует названию фильтра). Для примера приведу функцию фильтра :if :

preg_match_all('/\&([\w]*)\=\`((?:.[^\&]*)?(?(?=:).*?\`\]\](?:.[^&]*)?|(?:.[^\&\:])?))\`/iu', $subject, $found);


Резюмируя: Уважаемые Гуру регулярных выражений, поделитесь опытом, как закрыть конструкцию при наличии в ней вложенности аналогичных конструкций.
Ответы:
Думается, что никак. Потому что Ваша синтаксическая конструкция не является регулярной.
Хотя я не гуру, может и можно что-то придумать)


12 лет назад

RPI.su - самая большая русскоязычная база вопросов и ответов. Наш проект был реализован как продолжение популярного сервиса otvety.google.ru, который был закрыт и удален 30 апреля 2015 года. Мы решили воскресить полезный сервис Ответы Гугл, чтобы любой человек смог публично узнать ответ на свой вопрос у интернет сообщества.

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

Чтобы связаться с нами по любому вопросу О САЙТЕ (реклама, сотрудничество, отзыв о сервисе), пишите на почту [email protected]. Только все общие вопросы размещайте на сайте, на них ответ по почте не предоставляется.