Ответ на ваш вопрос заключается в том, что да, так называемые «расширенные регулярные выражения», которые, возможно, более правильно называть шаблонами, чем регулярные выражения в формальном смысле, такие как те, что встречаются в Perl и PCRE, действительно способен к рекурсивному синтаксическому анализу контекстно-свободных грамматик .
Пара подходов этой публикации иллюстрирует не столько теоретические, сколько практические ограничения для применения регулярных выражений к X / HTML. Первый из приведенных здесь подходов, помеченных как «наивный», больше похож на тот, который вы можете найти в большинстве программ, которые предпринимают такую попытку. Это можно сделать для работы с четко определенным неуниверсальным X / HTML, часто с минимальными усилиями. Это лучшее приложение, так же как открытый X / HTML - худшее.
Второй подход, помеченный как wizardly, использует для анализа фактическую грамматику. Как таковой, он полностью такой же мощный, как и любой другой грамматический подход. Тем не менее, это также далеко за пределами возможностей подавляющего большинства случайных программистов. Это также рискует воссоздать идеальное колесо для получения отрицательной выгоды. Я написал это, чтобы показать, что можно сделать, но что практически ни при каких обстоятельствах не должно быть . Я хотел показать людям, почему они хотят использовать синтаксический анализатор в открытом X / HTML, показывая им, как чертовски сложно даже приблизиться к правильному подходу, даже используя некоторые из самых мощных доступных на данный момент средств сопоставления с образцом.
Многие неправильно истолковали мою публикацию как что-то, защищающее противоположное тому, что я на самом деле говорю. Пожалуйста, не делайте ошибку: я говорю, что это слишком сложно для использования. Это доказательство контрпримером. Я надеялся, что, показав, как это сделать с помощью регулярных выражений, люди поймут, почему они не хотят пойти по этому пути. Хотя все возможно, не все целесообразно.
Мое эмпирическое правило таково, что если требуемое регулярное выражение относится только к первой категории, я вполне могу его использовать, но если оно требует полностью грамматического подхода ко второй категории, я использую чужой уже написанный синтаксический анализатор. Поэтому, хотя я могу написать синтаксический анализатор, я не вижу причин для этого, и много чего не сделаю.
При тщательном создании для этой явной цели шаблоны могут быть более устойчивыми к искаженному X / HTML, чем обычно готовые парсеры, особенно если у вас нет реальной возможности взломать упомянутые парсеры чтобы сделать их более устойчивыми к распространенным сбоям, которые веб-браузеры обычно допускают, а валидаторы - нет. Тем не менее, приведенные выше грамматические шаблоны были разработаны только для правильно сформированного, но достаточно универсального HTML-кода (хотя и без замены сущности, которая достаточно легко добавляется). Восстановление ошибок в парсерах - это отдельная проблема, и ни в коем случае не приятная.
Паттерны, особенно гораздо более распространенные не грамматические, которые большинство людей привыкли видеть и использовать, гораздо лучше подходят для захвата дискретных фрагментов по одному, чем для создания полного синтаксического анализа. Другими словами, регулярные выражения обычно работают лучше для лексирования, чем для синтаксического анализа. Без грамматических регулярных выражений не следует пытаться разбирать грамматики.
Но не заходите слишком далеко. Я, конечно, не имею в виду, что вам следует немедленно обратиться к полноценному парсеру только потому, что вы хотите заняться чем-то, что определено рекурсивно. Самым простым и, пожалуй, наиболее часто встречающимся примером такого рода вещей является шаблон для обнаружения вложенных элементов, например, скобки. Мне очень свойственно просто добавить что-то простое в мой код и покончить с этим:
# delete all nested parens
s/\((?:[^()]*+|(?0))*\)//g;