Эта статья может быть слишком технической для понимания большинством читателей . Ноябрь 2015 г. ) ( Узнайте, как и когда удалить этот шаблон сообщения ) ( |
В формальной теории языка в информатике , левая рекурсия является частным случаем рекурсии , где строка распознаются как часть языка, тем , что он разлагается в строку из того же языка (слева) и суффикс (на право). Например, можно распознать сумму, потому что она может быть разбита на сумму и подходящий суффикс.
С точкой зрения контекстно-свободной грамматики , А нетерминальный лево-рекурсивным , если крайний левый символ в одном из своих производств сам (в случае прямой левой рекурсии) или может быть сделаны себя с помощью некоторой последовательности замен (в случае непрямого левая рекурсия).
Определение [ править ]
Грамматика является леворекурсивной тогда и только тогда, когда существует нетерминальный символ, который может образовывать сентенциальную форму с самим собой в качестве крайнего левого символа. [1] Символично,
- ,
где обозначает операцию выполнения одной или нескольких замен, а представляет собой любую последовательность оконечных и нетерминальных символов.
Прямая левая рекурсия [ править ]
Прямая левая рекурсия возникает, когда определение может быть удовлетворено только одной заменой. Требуется правило формы
где - последовательность нетерминалов и терминалов. Например, правило
является непосредственно леворекурсивным. Парсер рекурсивного спуска слева направо для этого правила может выглядеть так:
недействительным Выражение () { Выражение (); совпадение ( '+' ); Срок (); }
и такой код при выполнении попадет в бесконечную рекурсию.
Косвенная левая рекурсия [ править ]
Косвенная левая рекурсия возникает, когда определение левой рекурсии выполняется с помощью нескольких замен. Это влечет за собой набор правил, следующих по шаблону
где - последовательности, каждая из которых может давать пустую строку , а могут быть любые последовательности оконечных и нетерминальных символов. Обратите внимание, что эти последовательности могут быть пустыми. Вывод
затем выдает как крайний левый в своей окончательной форме предложения.
Удаление левой рекурсии [ править ]
Левая рекурсия часто создает проблемы для синтаксических анализаторов, либо потому, что она приводит их к бесконечной рекурсии (как в случае с большинством нисходящих синтаксических анализаторов ), либо потому, что они ожидают правил в нормальной форме, которые запрещают ее (как в случае многих восходящих парсеров ). парсеры , в том числе алгоритм CYK ). Поэтому грамматика часто предварительно обрабатывается для устранения левой рекурсии.
Удаление прямой левой рекурсии [ править ]
Общий алгоритм удаления прямой левой рекурсии следующий. В этот метод внесено несколько улучшений. [2] Для леворекурсивного нетерминала отбросьте все правила формы и рассмотрите оставшиеся:
где:
- каждый - непустая последовательность нетерминалов и терминалов, и
- каждый - это последовательность нетерминалов и терминалов, не начинающаяся с .
Замените их двумя наборами продукции, один набор для :
и еще один набор для свежего нетерминала (часто называемого "хвостом" или "остальным"):
Повторяйте этот процесс до тех пор, пока не останется прямой левой рекурсии.
В качестве примера рассмотрим набор правил
Это можно переписать, чтобы избежать левой рекурсии, как
Удаление всей левой рекурсии [ править ]
Установив топологический порядок на нетерминалах, вышеупомянутый процесс может быть расширен, чтобы также исключить косвенную левую рекурсию [ необходима цитата ] :
- Входы Грамматика: набор нетерминалов и их продукции
- Выходные данные Измененная грамматика, генерирующая тот же язык, но без левой рекурсии.
- Для каждого нетерминала :
- Повторяйте, пока итерация не оставит грамматику неизменной:
- Для каждого правила , представляющего собой последовательность терминалов и нетерминалов:
- Если начинается с нетерминального и :
- Пусть будет без его руководства .
- Удалите правило .
- Для каждого правила :
- Добавьте правило .
- Если начинается с нетерминального и :
- Для каждого правила , представляющего собой последовательность терминалов и нетерминалов:
- Удалите прямую левую рекурсию, как описано выше.
- Повторяйте, пока итерация не оставит грамматику неизменной:
- Для каждого нетерминала :
Обратите внимание, что этот алгоритм очень чувствителен к нетерминальному порядку; оптимизации часто сосредотачиваются на правильном выборе этого порядка. [ требуется разъяснение ]
Ловушки [ править ]
Хотя приведенные выше преобразования сохраняют язык, сгенерированный грамматикой, они могут изменять деревья синтаксического анализа , свидетельствующие о распознавании строк. При соответствующем учете перезапись дерева может восстановить оригиналы, но если этот шаг пропустить, различия могут изменить семантику синтаксического анализа.
Ассоциативность особенно уязвима; левоассоциативные операторы обычно появляются в правой ассоциативной структуре в соответствии с новой грамматикой. Например, начиная с этой грамматики:
стандартные преобразования для удаления левой рекурсии дают следующее:
Анализ строки «1-2-3» с первой грамматикой в анализаторе LALR (который может обрабатывать леворекурсивные грамматики) привел бы к дереву синтаксического анализа:
Это дерево синтаксического анализа группирует термины слева, давая правильную семантику (1-2) - 3 .
Парсинг со второй грамматикой дает
который при правильной интерпретации означает 1 + (-2 + (-3)) , также правильный, но менее точный для ввода и намного сложнее реализовать для некоторых операторов. Обратите внимание, как термины справа появляются глубже в дереве, так же как праворекурсивная грамматика упорядочивает их для 1 - (2 - 3) .
Учет левой рекурсии при синтаксическом анализе сверху вниз [ править ]
Формальная грамматика , которая содержит левую рекурсию не может быть проанализирована с помощью LL (к) -parser или другого наивныма метода рекурсивного спуска , если он не преобразуется в слабо эквивалентную правой рекурсии формы. Напротив, левая рекурсия предпочтительнее для парсеров LALR, потому что она приводит к меньшему использованию стека, чем правая рекурсия . Однако более сложные нисходящие синтаксические анализаторы могут реализовать общие контекстно-свободные грамматики с помощью сокращения. В 2006 году Фрост и Хафиз описали алгоритм, который учитывает неоднозначные грамматики с прямыми леворекурсивными производственными правилами . [3]Этот алгоритм был расширен до полного алгоритма синтаксического анализа для размещения косвенной, а также прямой левой рекурсии за полиномиальное время и для генерации компактных представлений полиномиального размера потенциально экспоненциального числа деревьев синтаксического анализа для весьма неоднозначных грамматик Фростом, Хафизом и Каллаганом в 2007 году. . [4] Затем авторы реализовали алгоритм в виде набора комбинаторов синтаксического анализатора, написанных на языке программирования Haskell . [5]
См. Также [ править ]
- Хвостовая рекурсия
Ссылки [ править ]
- ^ Заметки по теории формального языка и синтаксическому анализу , Джеймс Пауэр, факультет компьютерных наук Национального университета Ирландии, Мейнут Мейнут, графство Килдэр, Ирландия. JPR02
- ↑ Мур, Роберт С. (май 2000 г.). «Удаление левой рекурсии из контекстно-свободных грамматик» (PDF) . 6-я конференция по прикладной обработке естественного языка : 249–255.
- ^ Frost, R .; Р. Хафиз (2006). «Новый алгоритм нисходящего синтаксического анализа для устранения неоднозначности и левой рекурсии за полиномиальное время» . Уведомления ACM SIGPLAN . 41 (5): 46–54. DOI : 10.1145 / 1149982.1149988 ., доступный у автора по адресу http://hafiz.myweb.cs.uwindsor.ca/pub/p46-frost.pdf. Архивировано 8 января 2015 г. на Wayback Machine.
- ^ Frost, R .; Р. Хафиз; П. Каллаган (июнь 2007 г.). «Модульный и эффективный анализ сверху вниз для неоднозначных леворекурсивных грамматик» (PDF) . 10-й Международный семинар по технологиям синтаксического анализа (IWPT), ACL-SIGPARSE : 109–120. Архивировано из оригинального (PDF) 27 мая 2011 года.
- ^ Frost, R .; Р. Хафиз; П. Каллаган (январь 2008 г.). Комбинаторы синтаксического анализатора для неоднозначных леворекурсивных грамматик (PDF) . 10-й Международный симпозиум по практическим аспектам декларативных языков (PADL), ACM-SIGPLAN . Конспект лекций по информатике. 4902 . С. 167–181. DOI : 10.1007 / 978-3-540-77442-6_12 . ISBN 978-3-540-77441-9.
Внешние ссылки [ править ]
- Практические соображения по грамматике LALR (1)