лексери проти парсери


308

Чи справді лексери та аналізатори відрізняються теоретично?

Здається модно ненавидіти регулярні вирази: кодування жахів , ще одна публікація в блозі .

Тим НЕ менше, популярні лексичні інструментів на основі: pygments , Geshi або прикрашати , все використовувати регулярні вирази. Вони ніби лексують що-небудь ...

Коли лексика достатня, коли вам потрібен EBNF?

Хтось використовував жетони, вироблені цими лексемами, з генераторами бисера або antlr parser?


2
так. Я намагаюся розібрати автоматичну клавішу. Мені вдалося створити підсвітку синтаксису, використовуючи пігменти дуже швидко. Але antlr займає набагато більше часу ... Я не бачив багато перехресного запилення між двома інструментами.
Naveen

67
Єдине модне ненавидіти регулярні вирази, коли вони неправильно використовуються. Багато людей намагаються використовувати регулярні вирази, коли потрібен безконтекстний аналіз. Вони завжди провалюються. І вони звинувачують технологію регулярного вираження. Це так, як скаржитися, що ваш молоток - це крихча пила. Щоправда, але симпатій ти не отримаєш.
Іра Бакстер

2
Я починаю набирати деяку швидкість з antlr, на щастя. Дуже багато лексингу залежить від контексту, а іноді навіть і від контексту.
Naveen

1
Основним аспектом проблеми лексера проти парсера є те, що лексери базуються на кінцевих автоматах (FSA), а точніше - на кінцевих перетворювачах (FST). Більшість формалізмів розбору (не тільки без контексту) закриті під перетином з FSA або застосуванням FST. Отже, використання простішого регулярного вираження на основі формалізму для лексеру не збільшує складність синтаксичних структур більш складних парсерних формалізмів. Це абсолютно важливе питання модульності при визначенні структури та семантики мов, із задоволенням ігнорованих високими голосовими відповідями.
babou

Слід зазначити, що лексери та парсери не повинні відрізнятися, наприклад, LLLPG та більш ранні версії ANTLR використовують однакову систему розбору LL (k) і для лексерів, і для парсерів. Основна відмінність полягає в тому, що регулярних виразів достатньо для лексерів, але не для парсерів.
Qwertie

Відповіді:


475

Що спільного між парсерами та лексемами:

  1. Вони читають символи якогось алфавіту зі свого введення.

    • Підказка: алфавіт не обов'язково повинен бути з букв. Але він повинен бути з символів, які є атомарними для мови, зрозумілої парсером / лексером.
    • Символи лексеми: символи ASCII.
    • Символи для аналізатора: конкретні лексеми, які є кінцевими символами їх граматики.
  2. Вони аналізують ці символи і намагаються співставити їх із граматикою мови, яку вони зрозуміли.

    • Ось де зазвичай криється справжня різниця. Детальніше дивіться нижче.
    • Граматику розуміють лексеми: звичайна граматика (рівень Хомського 3).
    • Граматику, яку розуміють парсери: граматика без контексту (рівень Хомського 2).
  3. Вони приєднують семантику (значення) до знайдених мовних фрагментів.

    • Лексери надають значення, класифікуючи лексеми (рядки символів із вхідних даних) як особливі лексеми . Наприклад , всі ці лексеми: *, ==, <=, ^будуть класифікуватися як «оператор» токен C / C ++ Лексера.
    • Парсери надають значення, класифікуючи рядки лексем із вхідних даних (речень) як конкретні нетермінали та будуючи дерево розбору . Наприклад , всі ці символічні рядки: [number][operator][number],[id][operator][id] , [id][operator][number][operator][number]будуть класифікуватися як «вираз» нетерміналом по C / C ++ парсеру.
  4. Вони можуть приєднувати якесь додаткове значення (дані) до розпізнаних елементів.

    • Коли лексер розпізнає послідовність символів, що становить власне число, він може перетворити його у своє двійкове значення та зберегти з маркерів "число".
    • Аналогічно, коли аналізатор розпізнає вираз, він може обчислити його значення і зберегти з вузлом "вираз" дерева синтаксису.
  5. Всі вони створюють на своєму виході відповідні пропозиції мови, яку вони розпізнають.

    • Лексичних виробляють маркери , які є пропозиції по регулярному мови вони визнають. Кожен маркер може мати внутрішній синтаксис (хоча рівень 3, а не рівень 2), але це не має значення як для вихідних даних, так і для того, хто їх читає.
    • Парсери виробляють синтаксичні дерева , які є реченнями речень без контекстної мови, яку вони розпізнають. Зазвичай це лише одне велике дерево для всього документа / вихідного файлу, тому що весь документ / вихідний файл є для них належним реченням . Але немає жодних причин, чому парсер не міг створити ряд синтаксичних дерев на своєму виході. Наприклад, це може бути аналізатор, який розпізнає теги SGML, вкладені в звичайний текст. Таким чином, він буде токенізувати документ SGML в ряд лексем:[TXT][TAG][TAG][TXT][TAG][TXT]... .

Як бачите, парсери та токенізатори мають багато спільного. Один аналізатор може бути токенізатором для іншого парсера, який читає свої вхідні маркери як символи з власного алфавіту (лексеми - це просто символи якогось алфавіту) так само, як пропозиції з однієї мови можуть бути алфавітними символами якоїсь іншої, вищого рівня мова. Наприклад, якщо *і -є символи алфавіту -M (як "символи коду Морзе"), то ви можете створити аналізатор, який розпізнає рядки цих точок і рядків як літери, закодовані в коді Морзе. Речення в мові «Морзе Код» можуть бути лексемами для якогось іншого аналізатора, для якого ці лексемиє атомними символами його мови (наприклад, мова "Англійські слова"). І ці "англійські слова" можуть бути лексемами (символами алфавіту) для аналізатора вищого рівня, який розуміє мову "англійських речень". І всі ці мови відрізняються лише складністю граматики . Нічого більше.

То що ж усе про ці "рівні граматики Чомського"? Ну, Ноам Хомський класифікував граматики на чотири рівні залежно від їх складності:

  • 3 рівень: Регулярні граматики

    Вони використовують регулярні вирази, тобто, вони можуть складатися тільки з символів алфавіту ( a, b), їх конкатенації ( ab, aba, bbbETD.), Або альтернативні варіанти (наприклад a|b).
    Вони можуть бути реалізовані як автомати з кінцевим станом (FSA), як NFA (недетермінований кінцевий автоматизатор) або кращий DFA (детермінований кінцевий автомат).
    Звичайні граматики не можуть працювати з вкладеним синтаксисом , наприклад, правильно вкладеними / зіставленими дужками(()()(()())) , вкладеними тегами HTML / BBcode, вкладеними блоками і т. Д. Це тому, що державні автомати для роботи з ним повинні мати нескінченно багато станів, щоб обробляти нескінченно багато рівнів вкладення.
  • Рівень 2: Граматики без контексту

    Вони можуть мати вкладені, рекурсивні, самоподібні гілки у своїх синтаксичних деревах, тому вони можуть добре впоратися з вкладеними структурами.
    Вони можуть бути реалізовані як державний автомат зі стеком. Цей стек використовується для представлення рівня вкладення синтаксису. На практиці вони, як правило, реалізуються як аналізатор рекурсивно-низхідного зверху зверху вниз, який використовує стек виклику процедури машини для відстеження рівня вкладення та використовує рекурсивно викликані процедури / функції для кожного нетермінального символу в їх синтаксисі.
    Але вони не можуть впоратися з контекстно-залежним синтаксисом. Наприклад, коли у вас є вираз, x+3і в одному контексті це xможе бути назва змінної, а в іншому контексті це може бути назва функції тощо.
  • Рівень 1: Контекстно-чутливі граматики

  • Рівень 0: Не обмежені граматики
    Також називаються рекурсивно перелічуваними граматиками.


70
О так? То які це "слова чи лексеми"? Вони просто пропозиції в звичайній мові, що складаються з літер алфавіту. А що це за "конструкти" чи "дерева" в аналізаторі? Вони також є реченнями , але іншою мовою вищого рівня, для якої конкретні лексеми є алфавітними символами. Різниця полягає не в тому, що ви сказали, а в СУСПІЛЬНОСТІ ВИКОРИСТАНОЇ МОВИ . Протистояти своєму -1 будь-якому посібнику з теорії розбору.
SasQ

3
@SasQ Чи було б справедливо сказати, що і Лексери, і Парсери беруть в якості граматики і серію лексем?
Параг

4
Зовсім так. Вони обидва беруть ряд символів з розпізнаного алфавіту. Для лексеру цей алфавіт складається просто з простих символів. Для розбору алфавіт складається з кінцевих символів, незалежно від того, що вони визначені. Вони також можуть бути символами, якщо ви не використовуєте лексеми та не використовуєте односимвольні ідентифікатори та одноцифрові цифри тощо (досить корисно на перших етапах розробки). Але вони зазвичай лексеми (лексичні класи), тому що лексеми - це хороша абстракція: ви можете змінити фактичні лексеми (рядки), для яких вони стоять, і парсер не бачить змін.
SasQ

6
Наприклад, ви можете використовувати символ терміналу STMT_ENDу своєму синтаксисі (для аналізатора), щоб позначити кінець інструкцій. Тепер ви можете мати маркер із тим самим ім'ям, пов'язаний з ним, що генерується лексером. Але ви можете змінити фактичну лексему, для якої вона стоїть. Напр. Ви можете визначити, STMT_ENDяк ;мати вихідний код, схожий на C / C ++. Або ви можете визначити його таким чином, endщоб воно було якось схожим на стиль Паскаля. Або ви можете визначити його як просто '\n'для закінчення інструкції в кінці рядка, як у Python. Але синтаксис вказівки (і парсера) залишається незмінним :-) Лише лексеру потрібно змінити.
SasQ

24
Години на wikipedia та google не допомогли, але ви пояснили граматики Чомського за 3 хвилини. Дякую.
енрі

107

Так, вони дуже різні як в теорії, так і в реалізації.

Лексики використовуються для розпізнавання «слів», що складають мовні елементи, оскільки структура таких слів, як правило, проста. Регулярні вирази надзвичайно добре справляються з цією простішою структурою, і є дуже високопродуктивні двигуни відповідності регулярного вираження, які використовуються для реалізації лексерів.

Парсери використовуються для розпізнавання "структури" мовних фраз. Така структура, як правило, набагато виходить за рамки того, що "регулярні вирази" можуть розпізнати, тому для отримання такої структури потрібні "контекстно-залежні" аналізатори. Контекстно-чутливі парсери важко побудувати, тому інженерний компроміс полягає у використанні "безконтекстних" граматик та додавання хаків до аналізаторів ("таблиць символів" тощо) для обробки контекстно-залежної частини.

Ні швидкість лексингу, ні синтаксичний аналіз не можуть скоротитися.

Вони можуть бути об'єднані, вирішивши використовувати технологію "розбору" для розпізнавання "слів", як зараз вивчають так звані сканери GLR-аналізаторів без сканера. Це має витрати на виконання, оскільки ви застосовуєте більш загальну техніку до того, що часто є проблемою, яка цього не потребує, і зазвичай ви платите за це накладні витрати. Там, де у вас багато вільних циклів, це накладні витрати можуть не мати значення. Якщо ви обробляєте багато тексту, то накладні значення мають значення, і класичні парсери регулярного виразу продовжуватимуться використовувати.


40
Гарне пояснення, Іра. Додавання до вашої аналогії: Хоча лексеми збираються правильно сказати слова, парсери - це правильні речення. "Див. Пробіг" та "Виконання спот" - це дійсність, що стосується лексеру. Потрібно аналізатор, щоб визначити, що структура фрази неправильна (в англійській граматиці).
Алан

Я здогадуюсь, парсер є лексером, як ходок по дереву - це аналізатор. Я не переконаний, що теорія така інша: antlr.org/wiki/display/~admin/ANTLR+v4+lexers, але я починаю розуміти відмінності у домовленості між ними ...
Naveen

4
Теорія дуже різна. Більшість технологій аналізатора намагаються певною мірою обробляти контекстні мови (деякі - лише частину, наприклад, LALR, деякі - все, наприклад, GLR). Більшість технологій лексерів намагаються робити регулярні вирази.
Іра Бакстер

3
Теорія інша, тому що її запропонували багато різних людей і використовують різні термінології та алгоритми. Але якщо придивитися до них уважно, то можна помітити схожість. Наприклад, проблема лівої рекурсії дуже схожа на проблему недетермінізму в NFA, а видалення лівої рекурсії аналогічно видаленню недетермінізму та перетворенню NFA в DFA. Маркери - це речення для токенізатора (вихід), але алфавітні символи для аналізатора (введення). Я не заперечую відмінності (рівні Хомського), але схожість дуже допомагає в дизайні.
SasQ

1
Мій офіційний лікар був у теорії категорій. Він показав, як поняття категоричної теорії снопів охоплює всі види узгодження зразків, і зміг вивести LR-синтаксичний аналіз з абстрактної категоричної специфікації. Тож насправді, якщо ви хочете достатньо абстрактно, ви можете знайти такі спільності. Справа в теорії категорій полягає в тому, що ви часто можете абстрагуватися "до кінця"; Я впевнений, що ви могли б побудувати аналізатор теорії категорій, який стирав би відмінності. Але будь-яке практичне використання має приводитись до конкретної проблемної області, і тоді відмінності виявляються справжніми.
Іра Бакстер

32

Коли лексика достатня, коли вам потрібен EBNF?

EBNF справді не додає багато до влади граматик. Це просто зручність / позначення ярликів / "синтаксичний цукор" над типовими правилами граматики Нормальної форми (ЧМС) Чомського. Наприклад, альтернатива EBNF:

S --> A | B

ви можете досягти в CNF, просто перерахувавши кожне альтернативне виробництво окремо:

S --> A      // `S` can be `A`,
S --> B      // or it can be `B`.

Необов'язковий елемент з EBNF:

S --> X?

ви можете домогтися в CNF, використовуючи нульове виробництво, тобто таке, яке можна замінити порожнім рядком (позначається тут просто порожнім виробництвом; інші використовують епсілон або лямбда або перекреслене коло):

S --> B       // `S` can be `B`,
B --> X       // and `B` can be just `X`,
B -->         // or it can be empty.

Виробництво у формі, подібній до останньої Bвище, називається "стирання", оскільки вона може стерти все, що вона стоїть в інших виробництвах (продукт порожній рядок замість чогось іншого).

Нульовий або більше повторень від EBNF:

S --> A*

ви можете обтан, використовуючи рекурсивне виробництво, тобто таке, яке вбудовується десь у ньому. Це можна зробити двома способами. Перша - це ліва рекурсія (якої зазвичай слід уникати, оскільки парсери рекурсивного спуска зверху вниз не можуть її проаналізувати):

S --> S A    // `S` is just itself ended with `A` (which can be done many times),
S -->        // or it can begin with empty-string, which stops the recursion.

Знаючи, що він генерує лише порожній рядок (в кінцевому рахунку) з наступним нулем або більше As, однаковий рядок ( але не та ж мова! ) Може бути виражений за допомогою правої рекурсії :

S --> A S    // `S` can be `A` followed by itself (which can be done many times),
S -->        // or it can be just empty-string end, which stops the recursion.

А якщо мова йде +про одне або більше повторень з EBNF:

S --> A+

це можна зробити, розбивши на один Aі використовуючи, *як і раніше:

S --> A A*

яку ви можете виразити в CNF як такому (я тут використовую правильну рекурсію; спробуйте вияснити іншу як вправу):

S --> A S   // `S` can be one `A` followed by `S` (which stands for more `A`s),
S --> A     // or it could be just one single `A`.

Знаючи це, ви, ймовірно, можете розпізнати граматику для регулярного вираження (тобто звичайної граматики ) як ту, яка може бути виражена в одному виробництві EBNF, що складається лише з термінальних символів. Більш загально, ви можете розпізнавати звичайні граматики, коли ви бачите виходи, подібні до цих:

A -->        // Empty (nullable) production (AKA erasure).
B --> x      // Single terminal symbol.
C --> y D    // Simple state change from `C` to `D` when seeing input `y`.
E --> F z    // Simple state change from `E` to `F` when seeing input `z`.
G --> G u    // Left recursion.
H --> v H    // Right recursion.

Тобто, використовуючи лише порожні рядки, символи терміналів, прості нетермінали для заміни та зміни стану та використовуючи рекурсію лише для досягнення повторення (ітерація, яка є просто лінійною рекурсією - та, яка не розгалужує деревоподібну). Нічого більш просунутого вище, тоді ви впевнені, що це звичайний синтаксис, і ви можете перейти лише з лексером для цього.

Але коли ваш синтаксис використовує рекурсію нетривіально, щоб створити деревоподібні, самоподібні вкладені структури, як-от наступна:

S --> a S b    // `S` can be itself "parenthesized" by `a` and `b` on both sides.
S -->          // or it could be (ultimately) empty, which ends recursion.

тоді ви легко можете побачити, що це неможливо зробити за допомогою регулярного вираження, тому що ви не можете вирішити це в одному виробництві EBNF жодним чином; ви закінчите заміщення на Sневизначений термін, що завжди додаватиме ще й as, і bобидві сторони. Лексери (точніше: Автоматичні дані про кінцевий стан, які використовуються лексерами) не можуть зараховувати до довільного числа (вони кінцеві, пам’ятаєте?), Тому вони не знають, скільки aз них було, щоб їх рівномірно збігати з такою кількістю bs. Граматики подібні до цього називаються безконтекстними граматиками (як мінімум), і вони потребують розбору.

Граматики без контексту добре відомі для розбору, тому їх широко використовують для опису синтаксису мов програмування. Але є більше. Іноді потрібна більш загальна граматика - коли ти маєш рахувати більше речей одночасно, незалежно. Наприклад, коли ви хочете описати мову, де можна використовувати круглі дужки та квадратні дужки, переплетені, але вони повинні бути спарені між собою правильно (дужки з дужками, круглі з круглими). Цей вид граматики називається контекстно-залежним . Ви можете розпізнати його за тим, що він має більше одного символу зліва (перед стрілкою). Наприклад:

A R B --> A S B

Ви можете вважати ці додаткові символи зліва як "контекст" для застосування правила. Там можуть бути деякі передумови, постумови і так далі Наприклад, вказане правило буде замінити Rна S, але тільки тоді , коли це між Aі B, залишивши тих , Aі Bсебе незмінним. Цей синтаксис справді важко проаналізувати, оскільки йому потрібен повноцінний апарат Тюрінга. Це зовсім інша історія, тому я закінчу тут.


1
Ви заявляєте, що EBNF - це "лише зручність / нотатка ярликів /" синтаксичний цукор "над типовими правилами граматики Нормальної форми (ЧМФ) Чомського". Але CNF майже не має нічого спільного з цією темою. EBNF можна легко перетворити на стандартний BNF. Період. Це синтаксичний цукор для стандартного BNF.
babou

11

Відповісти на запитання (не повторюючи надмірно те, що відображається в інших відповідях)

Лексери та парсери не сильно відрізняються, як підказує прийнята відповідь. Обидва засновані на простих мовних формалізмах: звичайних мовах для лексерів і, майже завжди, безконтекстних (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 (у тому сенсі, який використовується в інших відповідях тут) важко побудувати і менш ефективно. Вони також є недостатніми, щоб виразно висловити певну суть чутливості до контексту, яка може знадобитися. І вони, природно, не створюють синтаксичну структуру (наприклад, розбір дерев), зручну для отримання семантики програми, тобто для генерації компільованого коду.


Так, розбір дерев і AST відрізняються, але в значній мірі не дуже корисними способами. Дивіться моє обговорення цього: stackoverflow.com/a/1916687/120163
Ira Baxter

@IraBaxter Я не згоден з вами, але я зараз не встигаю скласти чітку відповідь на ваше повідомлення. В основному, ви дотримуєтесь прагматичної точки зору (а також я захищаю власну систему, я думаю). Це ще простіше, тому що ви використовуєте загальні парсерси CF (однак GLR може бути не найефективнішим), а не детерміновані, як у деяких системах. Я розглядаю AST як референтне уявлення, яке піддається формально визначеному лікуванню, виправдано правильним перетворенням, математичним доказуванням, неспроможним до численних конкретних уявлень тощо.
babou

"Прагматичний" погляд є причиною, за якою я стверджую, що вони не дуже відрізняються корисним чином. І я просто не вірю, що використання (ad hoc AST) дає "переконливо правильні перетворення"; ваш спеціальний AST не має явного відношення до фактичної граматики мови, що обробляється (і тут, так, моя система може бути виправданою в тому, що наша "AST", можливо, є ізоморфним еквівалентом BNF). Спеціальні AST не дають вам жодної додаткової можливості розірвати "кілька конкретних уявлень". Ви заперечуєте проти GLR (не найефективніше) здається досить безглуздим. Також вони не є недетермінованими.
Ira Baxter

Тож насправді я не розумію жодної частини вашого заперечення проти мого коментаря. Вам доведеться написати цю "чисту відповідь".
Іра Бакстер

@IraBaxter Коментарі занадто обмежені для правильної відповіді (пропозиція?). "Ad hoc" не є належним класифікатором для захисника AST, який повинен бути (іноді є) опорним синтаксисом. Це історично вірно, дивлячись як на історію концепції AST в інформатиці, так і на історію формальних систем як терміни (дерева) у відсортованій алгебрі разом з інтерпретацією. AST - це довідкова форма, а не похідна. Дивіться також сучасні системи перевірки та автоматичне створення програм. Ви можете бути упередженими тим, що вам доведеться працювати з конкретного синтаксису, розробленого іншими.
бабу

7

Існує ряд причин, через які частина аналізу компілятора зазвичай розділяється на фази лексичного аналізу та синтаксичного аналізу (синтаксичного аналізу).

  1. Простота дизайну є найважливішим фактором. Розмежування лексичного та синтаксичного аналізу часто дозволяє спростити хоча б одне із цих завдань. Наприклад, аналізатор, який повинен був мати справу з коментарями та пробілом, як синтаксичні одиниці. Лексичний аналізатор вже видалив значно складніший, ніж той, який може припускати коментарі та пробіл. Якщо ми розробляємо нову мову, розділення лексичних та синтаксичних проблем може призвести до більш чіткого загального дизайну мови.
  2. Підвищена ефективність компілятора. Окремий лексичний аналізатор дозволяє застосовувати спеціалізовані методики, які служать лише лексичному завданню, а не завдання аналізу. Крім того, спеціалізовані технології буферизації для читання вхідних символів можуть значно пришвидшити компілятор.
  3. Підвищена портативність компілятора. Особливості введення пристрою можуть бути обмежені лише лексичним аналізатором.

ресурс__ Укладачі (2-е видання) написано - Альфред В. Або Колумбійський університет Моніка С. Лам Стенфордський університет Раві Сетхі Авайя Джеффрі Д. Уллман Стенфордський університет

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.