Я використовую термінологію та позначення з статті Ерлі . Можливо, що опис, який ви читаєте, відрізняється.
Часто здається, що загальні алгоритми розбору CF спочатку подаються у формі розпізнавача, а потім управління інформацією, необхідною для фактичної побудови дерев розбору та розбору лісів, начебто додається як задум. Однією з причин може бути те, що для зберігання інформації, необхідної для побудови спільного лісу, потрібен кубічний простір
O(n3) де n - довжина вхідного рядка, який розбирається, але потреба у просторі є лише квадратом O(n2)для визнання, коли ця інформація не зберігається. Причина збільшення складності простору досить проста: розмір лісу для розбору може бути кубічним.
Найгірша складність у часі O(n3), як добре відомо.
Найкращим посиланням на алгоритм Ерлі, звичайно, є документ Ерлі , але це не дуже явно щодо побудови лісу для розбору. Це насправді може бути безладною справою, набагато більше, ніж з'явиться швидка розмова розділу 7, сторінка 101. Правда, Ерлі говорить не про розбір лісу чи про ліс, а про " фактичне представлення всіх можливих дерев розбору ". І для цього є вагома причина: якби він спробував створити ліс відповідно до своєї граматики, його космічна (звідси і час) складна складність би піднялася наO(ns+1) де s- розмір найдовшого правила праворуч. Ось чому інші алгоритми використовують граматики у двійковій формі (не обов'язково Хомська нормальна форма (CNF)).
Власне, Ерлі використовує бінарну форму неявно , тому що це необхідно для кубічної часової складності. Це одна з головних ролей точки правила в державах. Але ця неявна бінарна форма створює синтаксичні розбори та ліси відповідно до бінарнізованої граматики, а не за первісною, що, я побоююся, є головним джерелом неясності. Про це докладніше далі.
Один хороший спосіб зрозуміти, як виходить ліс, - це, мабуть, подивитися на нього у більш простому випадку, алгоритмі CYK . Він також часто описується як розпізнавач, а в кінці додається аспект парсера . Ви можете подивитися опис у wikipedia. Інформація, необхідна для побудови лісу, - це те, що вони зберігають у таблиці «бекпоінтер».
Backpointers - це, по суті, покажчики на підрядки (асоційований символ), які утворюють складові рядка за деяким правилом. Вони дають усі можливі способи розбору підрядка. Нагадаємо, що CYK використовує двійкову форму, як правило, CNF, щоб все було простіше. Аналізатор CYK має принципово таку ж динамічну структуру програмування, що і Ерлі, але набагато простіший. Тож розуміння цього добре може стати вагомою підмогою.
Повертаючись до алгоритму Ерлі, я не вважаю, що вам потрібен вектор Ерлі, щоб прийняти рішення або побудувати розбір дерев і лісів. Те, що Ерлі називає вектором у своїй роботі, відображається лише на сторінці 97, у третьому пункті реалізації. Це лише пристрій для прискорення пошуку станів, що вказують назад на деяке задане положення рядка k, щоб отримати кращу складність. Але вся інформація знаходиться у державних наборах, реалізованих як списки держав. Однак цієї інформації недостатньо для створення лісу дерев розбору, оскільки алгоритм не відслідковує спосіб (шляхи) стану. Дійсно, вектор навіть використовується для ефективного відкидання стану, вже знайденого, незалежно від того, як він був знайдений.
У розділі 7 статті Ерлі він пояснює, що для того, щоб "перетворити розпізнавальник у аналізатор", тобто мати змогу відновити дерева розбору, слід слідкувати за тим, як виконуються завершення.
Кожен раз, коли ми виконуємо операцію завершення, додаючи стан
E→αD.βg (ігноруючи lookahead) ми будуємо вказівник з екземпляра D в такому стані до держави D→γ.fщо змусило нас зробити операцію. Це вказує на цеD розбирався як γ. У випадку, коли D неоднозначний, буде набір покажчиків від нього, по одному для кожної завершеної операції, яка викликалаE→αD.βgдодати до конкретного набору стану. Кожен символ в
γ також буде мати вказівники від неї (якщо вона не є термінальною) тощо, таким чином представляючи дерево походження для D.
Зауважте, що в цьому тексті f і g - це індекси в проаналізованому рядку, який вказує з того, з чого розпочалося розпізнавання правила лівої частини (як передбачив символ правої частини). f - це рядковий індекс, де розпізнавання D→γ стартував, і закінчувався в індексі g. Ці "покажчики на завершення" є еквівалентом Ерлі з описаних опорних покажчиків (не надто добре у вікіпедії) для парсерної версії CYK.
З такого вказівника (як описано в цитаті) ми знаємо, що D
в екземплярі правила E→αD.βg може бути сам розвинутий у дерево (або ліс), що аналізує вхідний рядок w з індексу f+1 індексувати g, яку ми відзначаємо wf+1:g. Вузли відразу внизуD задаються правилом D→γ. Шукаючи завершення, до якого призводятьD→γ.f Тоді ми можемо знайти інші такі покажчики, які розповідають, як останній символ Dбуло отримано, а значить, більше інформації про можливі дерева розбору. Також дивлячись на завершення, яке розпізнавало символ до останнього у наборах стану Earleir, ви виявляєте, як його було отримано тощо.
Якщо припустити, що ви зберегли всі необхідні вказівники, як зазначено в статті, ви можете отримати всі спільні представлення дерева, починаючи з останнього символу, розпізнаного парсером, який, звичайно, є початковим символом граматики.
Але я також пропустив безладну частину . Припустимо, у вас є правило
U→XYZ, яку я вибираю правою стороною довше 2 символів та іншим правилом W→UV, за неоднозначну граматику.
Цілком може статися, що аналізатор розбере wf+1:g в X,
wg+1:h в Y і обидва wh+1:i і wh+1:j в
Z. Отже, з правиломU→XYZ, Обоє wf+1:i і
wf+1:j розібратися в U.
Тоді може бути і те, і інше wi+1:k і wj+1:k обидва розбору на V. Тоді з правиломW→UV, рядок
wf+1:k розібратися в W двома різними способами, які відповідають неоднозначності граматики.
Звичайно, щоб уникнути повторень обчислень, алгоритм Ерлі намагатиметься поділити якомога більше двох обчислень. Те, що насправді поділиться, - це, очевидно, визнання (і аналіз)wf+1:g і wg+1:h в X і Y. Але це насправді зробить трохи більше: він також поділить початок двох чітких розбірів, які розпізнаютьU з правилом U→XYZ. Я маю на увазі, що державаU→XY.Zf буде знайдено лише один раз (стосовно того, що я описую), у встановленому стані Sh. Це буде спільна частина двох синтаксисів. Звичайно, речі будуть тимчасово розходитися під час розборуZ оскільки вони відповідають розрізним підрядкам, поки вони знову не сходяться, коли все розбирається на W, коли стан W→UV.f виробляється двічі в наборі штату Sk.
Тож ліс синтаксичних дерев може бути дуже дивним, з різновидами сиамських подвійних підтрубок, які можуть розділяти перші два краї якогось вузла, але не третій край. Іншими словами, це може бути дуже незграбна структура. Це може пояснити, чому Ерлі називає це " фактичним представленням усіх можливих дерев розбору ", не будучи більш конкретним.
Будь-яка спроба хірургічно відокремити сиамських близнюків без зміни граматики призведе до збільшення складності. Правильний спосіб зробити це - бінарнізація граматики.
Я сподіваюся, що це вам допоможе. Дай мені знати. Але я наполягаю на тому, що добре розуміння розбору CYK може допомогти. Є й інші алгоритми, більш прості, ніж Ерлі, які дозволяють ефективно аналізувати всі мови CF.
Ви можете знайти більш загальну інформацію про цю проблему щодо розбору лісів у двох інших відповідях, які я дав: /cstheory/7374#18006 та https://linguistics.stackexchange.com/questions/4619#6120 . Але вони не вдаються до конкретних деталей алгоритму Ерлі.