Відповісти на запитання (не повторюючи надмірно те, що відображається в інших відповідях)
Лексери та парсери не сильно відрізняються, як підказує прийнята відповідь. Обидва засновані на простих мовних формалізмах: звичайних мовах для лексерів і, майже завжди, безконтекстних (CF) мовах для парсерів. Вони обоє асоціюються з досить простими обчислювальними моделями, автоматикою з кінцевим станом і автоматом штовхування. Регулярні мови - це окремий випадок без контекстних мов, щоб лексери могли бути створені за допомогою дещо складнішої технології CF. Але це не гарна ідея принаймні з двох причин.
Принциповим моментом у програмуванні є те, що системний компонент має бути створений за допомогою найбільш підходящої технології, щоб його було легко виробляти, розуміти та підтримувати. Технологія не повинна бути надмірна (використовуючи методи, набагато складніші і затратніші, ніж потрібно), а також не повинна бути на межі її потужності, вимагаючи тим самим технічних викривлень для досягнення бажаної мети.
Ось чому "Здається модним ненавидіти регулярні вирази". Хоча вони можуть зробити багато, для їх досягнення іноді потрібне дуже нечитабельне кодування, не кажучи вже про те, що різні розширення та обмеження в реалізації дещо зменшують їх теоретичну простоту. Лексери зазвичай цього не роблять, і зазвичай це проста, ефективна та відповідна технологія для розбору лексеми. Використання парсерів CF для токена було б надмірним, хоча це можливо.
Ще одна причина не використовувати формалізм CF для лексерів - це те, що тоді може виникнути спокуса використати всю потужність CF. Але це може викликати структурні проблеми щодо читання програм.
Принципово, більша частина структури програмного тексту, з якого витягується значення, - це структура дерева. Він виражає те, як формується речення (програма) розбору з синтаксичних правил. Семантика виходить композиційними прийомами (гомоморфізм для математично орієнтованих) із того, як складаються правила синтаксису для побудови дерева розбору. Отже, структура дерева є важливою. Той факт, що лексеми ототожнюються з лексером, що базується на звичайному наборі, не змінює ситуацію, тому що CF, складений з регулярних, все ще дає CF (я дуже вільно кажу про звичайні перетворювачі, які перетворюють потік символів у потік маркера).
Однак CF, складений з CF (через перетворювачі CF ... вибачте за математику), не обов'язково дає CF, і може зробити речі більш загальними, але менш простежуваними на практиці. Таким чином, CF не є відповідним інструментом для лексерів, хоча він може бути використаний.
Однією з найважливіших відмінностей між регулярними та CF є те, що регулярні мови (і перетворювачі) складаються дуже добре практично з будь-яким формалізмом різними способами, тоді як мови CF (і перетворювачі) не мають навіть самих себе (за кількома винятками).
(Зауважте, що звичайні перетворювачі можуть використовувати й інші способи, наприклад формалізацію деяких методів обробки синтаксичних помилок.)
BNF - це лише специфічний синтаксис для подання граматики CF.
EBNF - це синтаксичний цукор для BNF , який використовує засоби регулярного позначення для надання більш короткої версії граматик BNF. Його завжди можна перетворити на еквівалентний чистий BNF.
Однак звичайні позначення часто використовуються в EBNF лише для того, щоб підкреслити ці частини синтаксису, які відповідають структурі лексичних елементів, і їх слід розпізнати за допомогою лексеру, а решта - скоріше подати у прямому BNF. Але це не абсолютне правило.
Підсумовуючи, простішу структуру лексеми краще проаналізувати за допомогою більш простої технології регулярних мов, тоді як дерево орієнтована структура мови (програмного синтаксису) краще обробляється граматиками CF.
Я б запропонував також переглянути відповідь AHR .
Але це залишає відкритим питання: Чому дерева?
Дерева є хорошою основою для визначення синтаксису, оскільки
вони надають тексту просту структуру
є дуже зручні для асоціації семантики з текстом на основі цієї структури з математично добре зрозумілою технологією (композиційність за допомогою гомоморфізмів), як зазначено вище. Це фундаментальний алгебраїчний інструмент для визначення семантики математичних формалізмів.
Отже, це хороше проміжне представлення, як свідчить успіх абстрактних синтаксичних дерев (AST). Зауважте, що AST часто відрізняється від дерева розбору, оскільки технологія розбору, що використовується багатьма професіоналами (наприклад, LL або LR), застосовується лише до підмножини граматик CF, таким чином, примушуючи граматичні спотворення, які пізніше виправляються в AST. Цього можна уникнути за допомогою більш загальної технології розбору (заснованої на динамічному програмуванні), яка приймає будь-яку граматику CF.
Заява про те, що мови програмування залежать від контексту (CS), а не CF, є довільною та суперечливою.
Проблема полягає в тому, що розділення синтаксису та семантики є довільним. Перевірка декларацій або угоди типу може розглядатися як частина синтаксису, або частина семантики. Те ж саме стосується угоди про гендер і чисельність природними мовами. Але є природні мови, де згода множини залежить від власне смислового значення слів, так що воно не добре поєднується з синтаксисом.
Багато визначень мов програмування в денотаційній семантиці розміщують декларації та перевірку типів у семантиці. Так що, як це робила Іра Бакстер те, що парсери CF підлаштовуються, щоб отримати контекстну чутливість, необхідну для синтаксису, - у кращому випадку умовний погляд на ситуацію. Він може бути організований як хак в деяких компіляторах, але цього не повинно бути.
Крім того, це не просто те, що аналізатори CS (у тому сенсі, який використовується в інших відповідях тут) важко побудувати і менш ефективно. Вони також є недостатніми, щоб виразно висловити певну суть чутливості до контексту, яка може знадобитися. І вони, природно, не створюють синтаксичну структуру (наприклад, розбір дерев), зручну для отримання семантики програми, тобто для генерації компільованого коду.