У чому різниця між синтаксичним аналізом LR (0) та SLR?


82

Я працюю над своїми концепціями компіляторів, однак я трохи заплутаний ... Гугління нікуди не дійшло до певної відповіді.

Чи аналізатори SLR та LR (0) однакові? Якщо ні, то в чому різниця?

Відповіді:


249

І синтаксичні аналізатори LR (0) і SLR (1) - це синтаксичні аналізатори знизу вгору, спрямовані та передбачувальні . Це означає що

  • Синтаксичні аналізатори намагаються застосувати виробництво в зворотному порядку, щоб зменшити вхідне речення назад до символу старту ( знизу вгору )
  • Синтаксичні аналізатори сканують вхідні дані зліва направо ( направлені )
  • Синтаксичні аналізатори намагаються передбачити, які скорочення застосовувати, не обов'язково бачачи всі вхідні дані ( передбачувальні )

І LR (0), і SLR (1) є парсерами зсуву / зменшення , що означає, що вони обробляють маркери вхідного потоку, розміщуючи їх у стеку, і в кожній точці або переміщують маркер, штовхаючи його в стек, або зменшуючи деякий послідовність терміналів і нетерміналів на вершині стека до якогось нетермінального символу. Можна продемонструвати, що будь-яку граматику можна проаналізувати знизу вгору, використовуючи синтаксичний аналізатор зсув / зменшення, але цей парсер може бути не детермінованим . Тобто синтаксичному аналізаторові, можливо, доведеться «здогадуватися», застосовувати зсув чи зменшення, і в кінцевому підсумку йому доведеться повернутися назад, щоб зрозуміти, що він зробив неправильний вибір. Яким би потужним не був ви побудований детермінований синтаксичний зсув / зменшення, він ніколи не зможе проаналізувати всі граматики.

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

Прошу вибачення, якщо це довгий виклад, але нам це потрібно, щоб мати змогу вирішити різницю між синтаксичним аналізом LR (0) та SLR (1). Синтаксичний аналізатор LR (0) - це парсер зсуву / зменшення, який використовує нульові маркери lookahead, щоб визначити, яку дію вжити (отже, 0). Це означає, що в будь-якій конфігурації синтаксичного аналізатора парсер повинен мати однозначну дію для вибору - або він зміщує певний символ, або застосовує конкретне зменшення. Якщо потрібно зробити два або більше варіантів, синтаксичний аналізатор зазнає невдачі, і ми говоримо, що граматика не є LR (0).

Нагадаємо, що два можливі конфлікти LR - це зміна / зменшення та зменшення / зменшення. В обох цих випадках є щонайменше дві дії, які міг би здійснити автомат LR (0), і він не може визначити, яку з них використовувати. Оскільки принаймні однією із суперечливих дій є скорочення, розумною лінією атаки було б намагатися зробити так, щоб синтаксичний аналізатор був обережнішим, коли він виконує певне скорочення. Більш конкретно, припустимо, що синтаксичному аналізатору дозволено переглядати наступний маркер вхідних даних, щоб визначити, чи слід його зміщувати чи зменшувати. Якщо ми дозволимо парсеру зменшувати лише тоді, коли це «має сенс» робити це (для деякого визначення поняття «має сенс»), то ми можемо усунути конфлікт, встановивши, що автомат конкретно вибере або змістити, або зменшити в певний крок.

У SLR (1) ("Спрощений LR (1)") парсеру дозволяється переглядати один маркер lookahead, приймаючи рішення про те, чи слід його зміщувати чи зменшувати. Зокрема, коли аналізатор хоче спробувати зменшити щось у формі A → w (для нетерміналу A та рядка w), він переглядає наступний маркер вводу. Якщо цей маркер міг легально з'явитися після нетерміналу А в якомусь похідному, парсер зменшує. В іншому випадку це не так. Інтуїція тут полягає в тому, що в деяких випадках немає сенсу робити спроби зменшення, оскільки з огляду на токени, які ми бачили дотепер, і майбутній маркер, не існує можливого способу, щоб зменшення коли-небудь було правильним.

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

На практиці, однак, дзеркальне відображення (1) все ще є досить слабким методом синтаксичного аналізу. Найчастіше ви побачите, що використовуються парсери LALR (1) ("Lookahead LR (1)"). Вони теж працюють, намагаючись вирішити конфлікти в парсері LR (0), але правила, які вони використовують для вирішення конфліктів, набагато точніші, ніж ті, що використовуються в SLR (1), і, отже, набагато більша кількість граматик є LALR (1) ніж дзеркальні (1). Щоб бути дещо конкретнішим, аналізатори SLR (1) намагаються вирішити конфлікти, переглядаючи структуру граматики, щоб дізнатись більше інформації про те, коли змінювати, а коли зменшувати. Синтаксичні аналізатори LALR (1) розглядають як граматику, так і синтаксичний аналізатор LR (0), щоб отримати ще більш конкретну інформацію про те, коли змінювати, а коли зменшувати. Оскільки LALR (1) може розглянути структуру синтаксичного аналізатора LR (0), він може точніше визначити, коли певні конфлікти є помилковими.yaccі bisonза замовчуванням виробляють парсери LALR (1).

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

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

Зовсім недавно набув популярності новий алгоритм синтаксичного аналізу, який називається GLR (0) ("Узагальнений LR (0)"). Замість того, щоб намагатися вирішити конфлікти, які виникають у синтаксичному аналізаторі LR (0), парсер GLR (0) замість цього працює, намагаючись паралельно пробувати всі можливі варіанти. За допомогою деяких розумних трюків це можна зробити дуже ефективно для багатьох граматик. Більше того, GLR (0) може проаналізувати будь-яку безконтекстну граматику взагалі , навіть граматики, які не можуть бути проаналізовані парсером LR (k) для будь-якого k. Інші парсери також можуть це робити (наприклад, парсер Ерлі або синтаксичний аналізатор CYK), хоча GLR (0), як правило, швидший на практиці.

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

Сподіваюся, це допомагає!


24
Це відмінна відповідь. Точно відповідає на питання дуже чітко та освітньо. Одна з найкращих відповідей, з якою я стикався на SO.
NealB

2
@templatetypedef: Я думаю, вам слід трохи пояснити різницю між L (AL) R (1) та SLR (1), саме тому SLR (1) існує як цікавий вибір. Але +1.
Айра Бакстер,

@Ira Baxter - Я щойно оновила дискусію, щоб трохи більше поговорити про LALR (1) та LR (1). Чи можете ви переглянути це і повідомити, чи є щось, на вашу думку, що я повинен додати?
templatetypedef

1
У синтаксичних аналізаторах @newbie LR (0) дійсно є таблиця ACTION, але дія залежить виключно від стану, а не стану плюс наступного маркера.
templatetypedef

1
@newbie Елемент, який ви вказали вище, є елементом зменшення. Вступ АКЦІЇ для цього стану мав би зменшити.
templatetypedef

1

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

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