Может ли расширенная реализация регулярных выражений анализировать HTML?

Я знаю, о чем вы думаете: "Боже мой, серьезно, не снова" - но, пожалуйста, несите меня, мой вопрос больше, чем титул. Прежде чем мы начнем, я обещаю, что никогда не попытаюсь проанализировать произвольный HTML с регулярным выражением или спросить кого-нибудь еще.

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

Поскольку я не знаю деталей каких-либо конкретных реализаций, таких как perl, мои вопросы:

  • Какие функции регулярных инструментов нерегулярны? Это обратные ссылки? И на каких языках они найдены?
  • Есть ли какой-либо из этих дополнительных трюков, достаточных для анализа всех контекстно-свободных языков?
  • Если "нет" на # 2, есть ли формальная категория или класс языков, на которые эти дополнительные функции распространяются точно? Как мы можем быстро узнать, находится ли проблема, которую мы пытаемся решить, во власти наших не обязательно регулярных выражений?

Ответ 1

Ответ на ваш вопрос заключается в том, что да, так называемые расширенные регулярные выражения, которые, возможно, более правильно называются шаблонами, чем регулярные выражения в формальном смысле, - например, найденные в Perl и PCRE действительно способны рекурсивный синтаксический анализ без контекстных грамматик.

Эти публикации демонстрируют не столько теоретические, сколько практические ограничения на применение регулярных выражений к X/HTML. Первый подход, данный там, тот, который наименован наивным, больше похож на тот вид, который вы можете найти в большинстве программ, которые делают такую ​​попытку. Это можно сделать для работы с четко определенным, не общим X/HTML, часто с очень небольшими усилиями. Это его лучшее приложение, так же, как его недостаток X/HTML является наихудшим.

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

Многие неверно истолковали мое сообщение, как-то отстаивая противоположность тому, что я на самом деле говорю. Пожалуйста, не ошибитесь: я говорю, что это слишком сложно использовать. Это доказательство контр-примера. Я надеялся, что, показывая, как это сделать с помощью регулярных выражений, люди поймут, почему они не хотят идти по этой дороге. Хотя все возможно, не все целесообразны.

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

При тщательном изготовлении для этой явной цели шаблоны могут быть более устойчивыми к искаженным X/HTML, чем, как правило, синтаксические анализаторы, особенно если у вас нет реальной возможности взломать указанные парсеры, чтобы сделать их более устойчивыми к общие случаи сбоев, которые веб-браузеры склонны терпеть, но валидаторы этого не делают. Тем не менее, описанные выше грамматические шаблоны были разработаны только для хорошо сформированного, но достаточно общего HTML (хотя и без замены объекта, который достаточно легко добавлен). Исправление ошибок в парсерах - это отдельная проблема, и ни в коем случае не приятная.

Шаблоны, особенно гораздо более распространенные неграмотные, которые большинство людей привыкли видеть и использовать, гораздо лучше подходят для захвата дискретных кусков по одному, чем для полного синтаксического анализа. Другими словами, регулярные выражения обычно лучше работают для лексинга, чем для синтаксического анализа. Без грамматических регулярных выражений вы не должны пытаться анализировать грамматики.

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

# delete all nested parens
s/\((?:[^()]*+|(?0))*\)//g;

Ответ 2

Да, расширения в вопросах - это обратные ссылки, и они технически делают "regexps" NP-complete, см. абзац Wikipedia.