Регулярний вираз, який ви цитуєте, - це жахливий безлад, і я не думаю, що хтось погоджується, що це читається. У той же час, значна частина цієї потворності притаманна проблемі, що вирішується: Є кілька шарів вкладання, а граматика URL є досить складною (звичайно, надто складною для спілкування на будь-якій мові). Однак, безумовно, правда, що є кращі способи описати, що описує цей регулярний вираз. То чому їх не використовують?
Велика причина - інертність і всюдисущість. Це не пояснює, наскільки вони стали настільки популярними в першу чергу, але тепер, коли вони є, кожен, хто знає регулярні вирази, може використовувати ці вміння (з дуже невеликою різницею між діалектами) на ста різних мовах та додатковому тисячі програмних засобів ( наприклад, текстові редактори та інструменти командного рядка). До речі, останні не могли б і не змогли використовувати жодне рішення, яке означає написання програм , оскільки вони сильно використовуються непрограмістами.
Незважаючи на це, регулярні вирази часто зловживають, тобто застосовуються навіть тоді, коли інший інструмент буде набагато кращим. Я не думаю, що синтаксис регулярних виразів є жахливим . Але це очевидно набагато краще за короткими та простими зразками: архетипний приклад ідентифікаторів на мовах, подібних С, [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
і створює нову продукцію, яка робить щось додаткове з нею, наприклад створити виробництво для відокремленого комою списку подій p
.
Запропонований вами підхід безумовно вирішує ці проблеми. Це просто не дуже добре їх вирішує, тому що він торгує набагато більш стислим, ніж потрібно. Перші дві проблеми можна вирішити, залишаючись у відносно простому та короткому мові, що залежить від домену. Третє, ну ... програмне рішення вимагає звичайно мови програмування загального призначення, але, на мій досвід, третя - це найменше з цих проблем. Мало шаблонів має достатньо часто зустрічатися з тієї ж складної задачі, яку програміст прагне вміти визначати нові комбінатори. І коли це необхідно, мова часто є досить складною, що вона не може і не повинна розбиратися з регулярними виразами.
Рішення для цих випадків існують. Існує приблизно десять тисяч бібліотек комбінаторів парсера, які роблять приблизно те, що ви пропонуєте, лише з різним набором операцій, часто різним синтаксисом, і майже завжди з більшою силою розбору, ніж регулярні вирази (тобто вони мають справу з контекстними мовами або деякими значущими підмножина тих). Потім є генератори аналізаторів, які працюють із описаним вище підходом "використовувати кращий DSL". І завжди є можливість записати частину розбору вручну у відповідному коді. Ви навіть можете змішувати і співставляти, використовуючи регулярні вирази для простих підзадач і виконуючи складні речі в коді, що викликає регекси.
Я не знаю достатньо про перші роки обчислень, щоб пояснити, як регулярні вирази стали настільки популярними. Але вони тут, щоб залишитися. Вам просто потрібно використовувати їх розумно, а не використовувати їх, коли це мудріше.