Я опишу алгоритм, який працює. Час роботи не повинно бути дуже поганим. Ви можете також обчислити досить багато цього.
Я припускаю, що не містить нетерміналів (хоча, мабуть, легко адаптуватися до цього випадку) і що ви не знаєте , або походження . Я також припускаю, що ваша граматика не містить творів, які ніколи не використовуються в жодному слові (наприклад, ).x y a A → AахуаА → А
Основне питання дійсно розібрати , як ви хочете знати , що саме стан ви в кінцевому підсумку в, так що ви знаєте , що може слідувати . Це не так просто, як ти не знаєш .a xаах
Ми використовуємо адаптацію алгоритму Ерлі . Вам потрібно спочатку розібратися в цьому алгоритмі. Наш алгоритм працює майже однаково, за винятком того, що наші кроки ініціалізації та завершення відрізняються.
Для ініціалізації, ми насіння нашого першого набору з елементом Ерелі для кожного входження (перший символ в ) в будь-якому виробництві вашої граматики. Встановлюємо задній покажчик цього елемента на -1, недійсне значення. Це важливо при нашому модифікованому завершенні. По суті, -1 означає «я не знаю, звідки було розпочато це виробництво». aа1а
Тепер ми виконуємо алгоритм Ерлі окремо для кожного можливого такого початкового елемента Ерлі. Ми не можемо просто зробити їх усі одночасно, оскільки синтаксиси можуть заважати один одному. Я не можу легко побачити швидший метод, ніж зворотний трек тут.
Для кроку завершення нам залишається лише внести модифікацію для обробки -1 задніх покажчиків. Коли ми закінчили виробництво, походження якого ми не знаємо, ми потрапили в біду. Тим НЕ менше, метод , який використовується для обчислення Набори щодоL A L R ( 1 ) подальшого по Pennello і DeRemer рятує нас: то , що нам тут потрібно саме те Набори щодо подальшого . Кожен предмет у цих наборах пошуку шукає відповідне положення у граматиці, що в свою чергу відповідає можливому продовженню завершеного виробництва. L A L R ( 1 )L A L R ( 1 )
На жаль, я дійсно не бачу іншого вибору, ніж знову відкликатись тут. Для кожної позиції в наборі пошуку, ви виконуєте етап завершення з цим положенням і продовжуєте розбір звідти. Ви робите це окремо для кожного розбору. Зауважте, що якщо ваша граматика , ваш lookahead однозначно визначить, в яку позицію ви повинні піти, тому вам не доведеться відступати.L A L R ( 1 )
Ви продовжуєте вищевказаний алгоритм на один символ поза , де ви вважаєте цей додатковий, віртуальний символ "будь-яким символом", що негайно дає вам набір "слідувати", який ви шукаєте - будь-коли фаза сканера знайде щось для цього остаточного Набір, ви можете додати цього символу до набору відповідей.а
Редагувати: Я думаю, що я знайшов метод, який видаляє більшу частину накладних витрат, запроваджених зворотним трекінгом. Ми пов’язуємо з кожним елементом Earley набір ідентифікаторів, які є рядками, оскільки нам потрібно буде використовувати префікси цих ідентифікаторів. Під час ініціалізації ми додаємо всі початкові елементи до набору Earley і пов’язуємо унікальний ідентифікатор з кожним набором.
На кроках сканера та передбачувача ідентифікатори переносяться на нові елементи. Елементи Earley в тому ж наборі Earley, які відрізняються лише своїми ідентифікаторами, об'єднуються разом, об'єднуючи свої ідентифікатори разом. Зауважте, що ми можемо виконувати кроки сканування та передбачувача на цих нових елементах за допомогою ідентифікаторів, не виконуючи цей крок для кожного ідентифікатора окремо.
Комплектувач розглядає ідентифікатори окремо і завершує елемент лише у тому випадку, якщо відповідний елемент у попередньому наборі елементів має ідентифікатор, який є префіксом ідентифікатора. Для кожного можливого завершення (так для кожного елемента в наборі пошуку ) ми додаємо унікальний символ до ідентифікаторів завершених елементів.L A L R ( 1 )
По суті, ми робимо зворотне відстеження за допомогою цих ідентифікаторів, щоб ми не виконували подвійної роботи в кроці сканування та передбачувача.