Яка різниця між парзаторами LR, SLR та LALR?


103

Яка фактична різниця між LR, SLR та LALR парсерами? Я знаю, що SLR та LALR - це типи парсерів LR, але яка насправді різниця щодо їх таблиць розбору?

І як показати, граматика - LR, SLR або LALR? Для граматики LL ми просто повинні показати, що жодна комірка таблиці розбору не повинна містити декількох правил виробництва. Будь-які подібні правила для LALR, SLR та LR?

Наприклад, як ми можемо показати, що граматика

S --> Aa | bAc | dc | bda
A --> d

LALR (1), але не SLR (1)?


EDIT (ybungalobill) : Я не отримав задовільної відповіді на те, яка різниця між LALR та LR. Таким чином, таблиці LALR мають менші розміри, але він може розпізнавати лише підмножину граматик LR. Чи може хтось детальніше зупинитися на різниці між LALR та LR? LALR (1) та LR (1) будуть достатніми для відповіді. Обидва вони використовують 1 маркер наперед, і обидва керуються таблицею! Чим вони відрізняються?


ну, навіть я шукаю належну відповідь на це, LALR (1) - це лише незначна модифікація LR (1), де розмір таблиці зменшується, щоб ми могли мінімізувати використання пам'яті ...
vikkyhacks

Відповіді:


64

SLR, LALR і LR парсери можуть бути реалізовані за допомогою однакових машин, керованих таблицею.

По суті, алгоритм синтаксичного аналізу збирає наступний маркер введення T і консультує поточний стан S (і пов'язані з ним таблиці пошуку, GOTO та скорочення), щоб вирішити, що робити:

  • SHIFT: Якщо поточна таблиця говорить SHIFT на токені T, пара (S, T) висувається на стек розбору, стан змінюється відповідно до того, що в GOTO таблиці вказано для поточного маркера (наприклад, GOTO (T) ) витягується інший маркер T ', і процес повторюється
  • ЗНИЖЕННЯ: Кожен стан має 0, 1 або багато можливих скорочень, які можуть статися в державі. Якщо аналізатор LR або LALR, маркер перевіряється наборами lookahead для всіх дійсних скорочень для стану. Якщо маркер відповідає множині пошуку для зменшення для граматичного правила G = R1 R2 .. Rn, відбувається зменшення та зсув стека: семантична дія для G викликається, стек вискакується n (від Rn) разів, пара ( S, G) висувається на стек, новий стан S 'встановлюється на GOTO (G), і цикл повторюється тим же символом T. Якщо аналізатор є аналізатором дзеркальних зображень, існує щонайменше одне правило зменшення для стан і тому зменшення може бути виконано наосліп, не шукаючи, яке зменшення застосовується. Користувачеві аналізатор дзеркальних речей знає, чи єзменшення чи ні; це легко визначити, чи кожен стан явно записує кількість скорочень, пов'язаних з ним, і чи потрібний цей підрахунок для версій L (AL) R на практиці.
  • ПОМИЛКА: Якщо ні SHIFT, ні REDUCE неможливо, оголошується помилка синтаксису.

Отже, якщо всі вони використовують одну і ту ж техніку, який сенс?

Передбачуване значення в дзеркальному дзеркалі - це його простота в реалізації; вам не доведеться перевіряти можливі скорочення, перевіряючи набори пошуку, тому що є щонайбільше один, і це єдина життєздатна дія, якщо немає виходів SHIFT із стану. Яке зменшення застосовується, може бути прикріплено спеціально до держави, тому машини для розбору дзеркальних речей не повинні полювати на нього. На практиці L (AL) R парсери обробляють корисно більший набір мов, і це так мало додаткової роботи, щоб здійснити, що ніхто не реалізує дзеркальні матеріали, окрім як навчальних занять.

Різниця між LALR і LR пов'язана з генератором таблиць. Генератори LR-парсера відслідковують усі можливі скорочення від конкретних станів та їх точний набір пошуку; Ви закінчуєте стани, в яких кожне зменшення пов'язане з його точним набором пошуку в лівому контексті. Це має тенденцію до побудови досить великих наборів держав. Генератори LALR аналізаторів готові комбінувати стани, якщо таблиці GOTO та набори для редукційних заголовків сумісні та сумісні та не конфліктують; це створює значно меншу кількість станів, ціною не в змозі розрізнити певні послідовності символів, які LR може розрізнити. Таким чином, LR-парсери можуть розбирати більший набір мов, ніж LALR-парсери, але мають дуже великі таблиці парсерів. На практиці можна знайти граматики LALR, які досить близькі до цільових мов, щоб розмір державної машини варто оптимізувати;

Отже: усі троє користуються однаковою технікою. Дзеркальна дзеркальна плата "проста" в тому сенсі, що ви можете ігнорувати крихітний апарат, але це просто не варте клопоту. LR аналізує більш широкий набір мов, але таблиці держав, як правило, досить великі. Це залишає LALR як практичний вибір.

Сказавши все це, варто знати, що парсери GLR можуть розбирати будь-яку контекстну мову, використовуючи складніші машини, але точно ті ж таблиці (включаючи меншу версію, що використовується LALR). Це означає, що GLR суворо потужніший, ніж LR, LALR та SLR; В значній мірі, якщо ви можете написати стандартну граматику BNF, GLR буде аналізувати її. Різниця в техніці полягає в тому, що GLR готовий спробувати кілька аналізів, коли виникають конфлікти між таблицею GOTO та наборами lookahead. (Наскільки GLR робить це ефективно, це геній [не мій], але не вписується в цю посаду ТА).

Це для мене надзвичайно корисний факт. Я будую програмні аналізатори та трансформатори коду та аналізатори необхідні, але "нецікаві"; цікава робота - це те, що ви робите з проаналізованим результатом, і тому фокус робиться на виконанні роботи після розбору. Використання GLR означає, що я відносно легко можу створити робочі граматики, порівняно із злому граматики, щоб потрапити у зручну форму LALR. Це дуже важливо, коли ви намагаєтеся мати справу з неакадемічними мовами, такими як C ++ або Fortran, де вам буквально потрібні тисячі правил, щоб добре обробити всю мову, і ви не хочете витрачати своє життя на те, щоб зламати правила граматики, щоб відповідати обмеженням LALR (або навіть LR).

Як своєрідний відомий приклад, C ++ вважається надзвичайно важким для розбору ... хлопці, які роблять розбір LALR. C ++ легко аналізувати, використовуючи обладнання GLR, використовуючи в значній мірі правила, наведені в задній частині посібника C ++. (У мене є саме такий аналізатор, і він обробляє не тільки ванільний C ++, а й різноманітні діалекти постачальників. Це можливо лише на практиці, оскільки ми використовуємо парсер GLR, IMHO).

[EDIT листопада 2011 року: ми розширили наш аналізатор для обробки всіх C ++ 11. GLR зробив це набагато простіше зробити. EDIT серп. 2014: Зараз обробляються всі C ++ 17. Нічого не зламалося і не погіршилося, GLR - це все ще котячий м'яч.]


AFAIK C ++ не можна розібратися з LR, оскільки він потребує нескінченного погляду вперед. Тому я не можу придумати жодних хаків, які дозволять розібратися з LR. Також LRE-аналізатори звучать багатообіцяюче.
Яків Галка

5
GCC використовується для розбору C ++ за допомогою Bison == LALR. Ви завжди можете доповнити свій аналізатор додатковим goo для обробки справ (lookahead, is-this-a-typename), які дають вам біль у душі. Питання "Наскільки болісний злом?" Для GCC це було досить болісно, ​​але вони змусили його працювати. Це не означає, що це рекомендується, що є моєю точкою щодо використання GLR.
Іра Бакстер

Я не розумію, як використання GLR допомагає вам з C ++. Якщо ви не знаєте, чи є щось назвою типу чи ні, то ви просто не знаєте, як розібратися x * y;- як допомагає використання GLR у цьому?
користувач541686

2
Справа в тому, що аналізатор GLR виробляє обидва синтаксичні розробки (як "неоднозначні піддереви") в інтегрованому синтаксичному аналізі "дерево" (справді DAG). Ви можете вирішити, який із підрядів ви хочете зберегти, пізніше, ввівши інші інформація про контекст. Наш C ++-аналізатор надзвичайно просто стосується цієї проблеми: він не намагається вирішити проблему. Це означає, що нам не доведеться заплутувати побудову таблиць символів з розбором, тому і наш парсер, і конструкція таблиці символів для C ++ індивідуально чисті, а отже, кожен з них повинен будувати та підтримувати.
Іра Бакстер

18

Аналізатори LALR об'єднують подібні стани в граматиці LR, щоб отримати таблиці стану стану парсера, які точно такого ж розміру, як і еквівалентна граматика SLR, які зазвичай на порядок менші, ніж чисті таблиці LR розбору. Однак для граматик LR, які є надто складними для того, щоб бути LALR, ці об'єднані стани призводять до розбору конфліктів або виробляють аналізатор, який не повністю розпізнає початкову граматику LR.

До речі, я вже дещо - що про це в моєму алгоритмі таблиці синтаксичного аналізу СЛР (к) тут .

Додаток

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

Таблиці LALR менші, оскільки подібні (надлишкові) стани об'єднуються разом, фактично викидаючи інформацію про контекст / пошук, яку кодують окремі стани. Перевага полягає в тому, що ви отримуєте набагато менші таблиці для розбору однієї граматики.

Недолік полягає в тому, що не всі граматики LR можуть бути кодовані як таблиці LALR, оскільки складніші граматики мають складніші канали пошуку, в результаті чого замість одного стану об'єднуються два або більше станів.

Основна відмінність полягає в тому, що алгоритм для створення таблиць LR містить більше інформації між переходами від стану до стану, тоді як алгоритм LALR цього не робить. Таким чином, алгоритм LALR не може визначити, чи слід дійсно заданий злитий стан залишити як два або більше окремих станів.


3
+1 Мені подобається ідея Honalee. Мій генератор розбору G / L (AL) R мав насіння щось подібне в ньому; він виробляє мінімальну машину LALR, і тоді я збирався розділити стани, де були конфлікти, але я ніколи не переживав. Це виглядає як приємний спосіб виготовити "LR" мінімального розміру, як набір таблиць розбору. Хоча це не допоможе GLR з точки зору того, що він може проаналізувати, він може скоротити кількість паралельних синтаксисів, які має виконати GLR, і це було б корисно.
Іра Бакстер

12

Ще одна відповідь (YAA).

Алгоритми розбору SLR (1), LALR (1) і LR (1) ідентичні тому, як сказала Іра Бакстер,
однак таблиці аналізаторів можуть бути різними через алгоритм генерації парсера.

Генератор дзеркальних аналізаторів створює стан машини LR (0) і обчислює огляди граматики (набори FIRST і FOLLOW). Це спрощений підхід і може повідомити про конфлікти, які насправді не існують у машині стану LR (0).

Генератор аналізатора LALR створює стан машини LR (0) і обчислює оглядові частини машини машини LR (0) (через термінальні переходи). Це правильний підхід, але періодично повідомляє про конфлікти, які не існували б у машині стану LR (1).

Генератор Canonical LR аналізатора обчислює стан машини LR (1), а оглядові частини вже є частиною станкової машини LR (1). Ці таблиці аналізаторів можуть бути дуже великими.

Генератор мінімального LR аналізатора обчислює стан машини LR (1), але об'єднує сумісні стани під час процесу, а потім обчислює оглядові частини машини мінімального LR (1). Ці таблиці аналізатора мають однаковий розмір або трохи більше, ніж таблиці парсерів LALR, що дає найкраще рішення.

LRSTAR 10.0 може генерувати парсери LALR (1), LR (1), CLR (1) або LR (*) в C ++, все, що потрібно для вашої граматики. Дивіться цю діаграму, яка показує різницю між LR-парсерами.

[Повне розкриття інформації: LRSTAR - це мій продукт]


5

Припустимо, аналізатор без підказки з радістю розбирає рядки для вашої граматики.

Використовуючи даний приклад, він натрапляє на рядок dc, що це робить? Чи зводить це до того S, що dcце дійсна строка, що виробляється цією граматикою? А може, ми намагалися розібратися, bdcбо навіть це є прийнятним рядком?

Оскільки люди знають, що відповідь проста, нам просто потрібно пам’ятати, чи ми щойно розбирали bчи ні. Але комп'ютери дурні :)

Оскільки аналізатор SLR (1) мав додаткову владу над LR (0) для виконання пошуку, ми знаємо, що будь-яка кількість lookahead не може сказати нам, що робити в цьому випадку; натомість нам потрібно озирнутися в наше минуле. Таким чином, на допомогу приходить канонічний аналізатор LR. Він пам'ятає минулий контекст.

Те, як він запам'ятовує цей контекст, полягає в тому, що він дисциплінує себе, що кожного разу, коли він зіткнеться з a b, він почне йти шляхом до читання bdc, як одна з можливостей. Тож коли він бачить, dвін знає, чи вже йде по стежці. Таким чином, аналізатор CLR (1) може робити те, що SLR (1) аналізатор не може!

Але тепер, оскільки нам довелося визначити стільки шляхів, стан машини стає дуже великим!

Таким чином, ми зливаємо однакові схожі шляхи, але, як очікувалося, це може породити проблеми плутанини. Однак ми готові ризикувати ціною зменшення розміру.

Це ваш аналізатор LALR (1).


Тепер, як це зробити алгоритмічно.

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


Це не точно

4

Основна відмінність таблиць аналізатора, згенерованих SLR проти LR, полягає в тому, що дії зменшення базуються на наведених нижче послідовностях для дзеркальних таблиць. Це може бути надмірно обмежуючим, в кінцевому рахунку спричиняючи конфлікт зменшення зрушень.

Аналіз LR, з іншого боку, засновує на зменшенні рішень лише на наборі терміналів, які можуть насправді слідувати зменшенню нетермінального терміналу. Цей набір терміналів часто є належним підмножиною набору Follows такого нетермінального пристрою, а отже, має менший шанс конфліктувати зі зміною дій.

LR парсери є більш потужними з цієї причини. Таблиця LR для розбору може бути надзвичайно великою.

Аналізатор LALR починається з ідеї побудови таблиці розбору LR, але поєднує генеровані стани таким чином, що призводить до значно меншого розміру таблиці. Мінус полягає в тому, що малий шанс виникнення конфліктів буде введений для деяких граматик, яких у противному випадку уникала таблиця LR.

LALR-парсери трохи менш потужні, ніж LR-парсери, але все ж більш потужні, ніж SLR-парсери. YACC та інші подібні генератори парсера, як правило, використовують LALR з цієї причини.

PS Для стислості значення SLR, LALR і LR вище дійсно означають SLR (1), LALR (1) і LR (1), тому мається на увазі одна лексема пошуку.


4

SLR-парсери розпізнають власне підмножину граматик, розпізнаваних LALR (1) парсерами, які, в свою чергу, розпізнають належний підмножина граматик, розпізнаваних за парсерами LR (1).

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

Приклад " Книги Драконів" для граматики LALR (1), яка не є дзеркальною формою, є таким:

S → L = R | R
L → * R | id
R → L

Ось один із станів цієї граматики:

S → L•= R
R → L•

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

Тут парсер може або змінити, =або зменшити R → L.

SLR (ака LR (0)) аналізатор може визначити , чи може він зменшити шляхом перевірки , якщо наступний вхідний символ в подальшому наборі з R(тобто безлічі всіх терміналів в граматиці , які можуть слідувати R). Оскільки =також є в цьому наборі, аналізатор дзеркальних даних стикається з конфліктом зменшення зрушення.

Однак, аналізатор LALR (1) використовує набір усіх терміналів, які можуть слідувати за цією конкретною продукцією R, яка є лише $(тобто кінцем введення). Таким чином, конфлікту немає.

Як зазначали попередні коментатори, парсери LALR (1) мають стільки ж станів, скільки і парсери SLR. Алгоритм розповсюдження пошуку за допомогою головного каналу використовується для прив'язки виробничих позицій до дзеркальних зображень із відповідних станів LR (1). Отриманий аналізатор LALR (1) може вводити конфлікти зменшення-зменшення, відсутні в аналізаторі LR (1), але він не може вводити конфлікти зменшення зрушення.

У вашому прикладі наступний стан LALR (1) викликає конфлікт зменшення зрушення в реалізації SLR:

S → b d•a / $
A → d• / c

Символ after /- це наступний набір для кожної продукції в аналізаторі LALR (1). У дзеркальному дзеркалі функція follow ( A) включає a, що також можна змістити.


2

На додаток до наведених вище відповідей, на цій схемі показано, як співвідносяться різні аналізатори:

введіть тут опис зображення


-2

Одна проста відповідь - це те, що всі граматики LR (1) є граматиками LALR (1). Порівняно з LALR (1), LR (1) має більше станів у пов'язаній з ним кінцевому стані (більше ніж удвічі більше станів). І це головна причина, що граматики LALR (1) вимагають більше коду для виявлення синтаксичних помилок, ніж граматики LR (1). І ще одна важлива річ, яку потрібно знати стосовно цих двох граматик, - це те, що в граматиках LR (1) ми можемо менше зменшити / зменшити конфлікти. Але в LALR (1) є більше можливостей зменшити / зменшити конфлікти.

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