Регулярное выражение, которое вы цитируете, - ужасный беспорядок, и я не думаю, что кто-то согласится с тем, что оно читаемо В то же время, большая часть этого безобразия присуща решаемой проблеме: существует несколько уровней вложения, а грамматика URL-адреса относительно сложна (безусловно, слишком сложна, чтобы общаться кратко на любом языке). Тем не менее, это правда, что есть лучшие способы описать то, что описывает это регулярное выражение. Так почему они не используются?
Большая причина в инерции и вездесущности. Во-первых, это не объясняет, как они стали настолько популярными, но теперь, когда они есть, любой, кто знает регулярные выражения, может использовать эти навыки (с очень небольшим количеством различий между диалектами) на сотне разных языков и еще тысяче программных инструментов ( например, текстовые редакторы и инструменты командной строки). Кстати, последний не будет и не сможет использовать какое-либо решение, которое сводится к написанию программ , потому что они активно используются не программистами.
Несмотря на это, регулярные выражения часто чрезмерно используются, то есть применяются даже тогда, когда другой инструмент будет намного лучше. Я не думаю, что синтаксис регулярных выражений ужасен . Но это явно намного лучше в коротких и простых шаблонах: архетипический пример идентификаторов в C-подобных языках [a-zA-Z_][a-zA-Z0-9_]*
может быть прочитан с абсолютным минимумом знания регулярных выражений, и как только эта полоса будет достигнута, она будет и очевидной, и лаконичной. Требовать меньше персонажей - это не плохо, а совсем наоборот. Быть кратким - это добродетель, если вы остаетесь понятными.
Есть по крайней мере две причины, по которым этот синтаксис превосходит простые шаблоны, подобные этим: он не требует экранирования для большинства символов, поэтому он читает относительно естественно и использует все доступные знаки препинания для выражения различных простых комбинаторов синтаксического анализа. Может быть , самое главное, он не требует вообще ничего для секвенирования. Вы пишете первое, а затем то, что следует за этим. Сравните это с вашим followedBy
, особенно если следующий шаблон - не буквальное, а более сложное выражение.
Итак, почему они терпят неудачу в более сложных случаях? Я вижу три основные проблемы:
Там нет возможности абстракции. Формальные грамматики, которые происходят из той же области теоретической информатики, что и регулярные выражения, имеют набор производств, поэтому они могут давать имена промежуточным частям шаблона:
# This is not equivalent to the regex in the question
# It's just a mock-up of what a grammar could look like
url ::= protocol? '/'? '/'? '/'? (domain_part '.')+ tld
protocol ::= letter+ ':'
...
Как мы могли видеть выше, пробелы, не имеющие особого значения, полезны для того, чтобы сделать форматирование более простым для глаз. То же самое с комментариями. Регулярные выражения не могут этого сделать, потому что пробел - это просто литерал ' '
. Обратите внимание: некоторые реализации допускают «подробный» режим, в котором пропуски игнорируются и возможны комментарии.
Нет мета-языка для описания общих моделей и комбинаторов. Например, можно написать digit
правило один раз и продолжать использовать его в контекстно-свободной грамматике, но нельзя определить, так сказать, «функцию», которая получает продукт p
и создает новый продукт, который делает с ним что-то дополнительное, например, create производство для списка случаев, разделенных запятыми p
.
Подход, который вы предлагаете, безусловно, решает эти проблемы. Это просто не решает их очень хорошо, потому что он торгует гораздо более кратко, чем необходимо. Первые две проблемы могут быть решены, оставаясь при этом в относительно простом и лаконичном предметно-ориентированном языке. Третий, ну ... программное решение, конечно, требует языка программирования общего назначения, но, по моему опыту, третий, безусловно, является наименьшей из этих проблем. У немногих шаблонов достаточно вхождений в ту же сложную задачу, которую программист жаждет определить новые комбинаторы. И когда это необходимо, язык часто бывает достаточно сложным, чтобы его нельзя было и не нужно анализировать с помощью регулярных выражений.
Решения для этих случаев существуют. Существует приблизительно десять тысяч библиотек синтаксических анализаторов, которые делают примерно то, что вы предлагаете, просто с другим набором операций, часто с другим синтаксисом и почти всегда с большей мощностью синтаксического анализа, чем регулярные выражения (т. Е. Они имеют дело с контекстно-свободными языками или некоторыми значительными подмножество тех). Кроме того, существуют генераторы синтаксических анализаторов, которые используют подход «лучше использовать DSL», описанный выше. И всегда есть возможность написать часть анализа вручную в правильном коде. Вы можете даже смешивать и сопоставлять, используя регулярные выражения для простых подзадач и делая сложные вещи в коде, вызывая регулярные выражения.
Я не знаю достаточно о первых годах вычислений, чтобы объяснить, как регулярные выражения стали настолько популярными. Но они здесь, чтобы остаться. Вы просто должны использовать их с умом, а не использовать их, когда это будет разумнее.