Устранение левой рекурсии
| Определение: |
| Говорят, что контекстно-свободная (КС) грамматика содержит непосредственную левую рекурсию, если она содержит правило вида . |
| Определение: |
| Говорят, что КС-грамматика содержит левую рекурсию (left recursion), если в ней существует вывод вида . |
Методы нисходящего разбора (top-down parsers) не в состоянии работать с леворекурсивными грамматиками. Проблема в том, что продукция вида может применяться бесконечно долго, так и не выработав некий терминальный символ, который можно было бы сравнить со строкой. Поэтому требуется преобразование грамматики, которое бы устранило левую рекурсию.
Устранение непосредственной левой рекурсии
Опишем процедуру, устраняющую все правила вида , для фиксированного нетерминала .
- Запишем все правила вывода из в виде:
, где
- — непустая последовательность терминалов и нетерминалов ();
- — непустая последовательность терминалов и нетерминалов, не начинающаяся с .
- Заменим правила вывода из на .
- Создадим новый нетерминал .
Изначально нетерминал порождает сроки вида . В новой грамматике нетерминал порождает , а порождает строки вида . Из этого очевидно, что изначальная грамматика эквивалентна новой.
Алгоритм устранения произвольной левой рекурсии
Пусть — множество всех нетерминалов.
for все нетерминалы for все нетерминалы , такие, что и рассмотреть все правила вывода из : . заменить каждое правило на . устранить непосредственную левую рекурсию для .
На итерации внешнего цикла все правила вида где заменяются на где . Таким образом остается только избавиться от непосредственной рекурсии для . Очевидно, что одна итерация алгоритма не меняет язык, а значит язык получившейся в итоге грамматики совпадает с исходным.
Алгоритм не работает для грамматик с переходами и с грамматиками имеющими .
Пример
Дана грамматика
Среди продукций непосредственной рекурсии нет, поэтому во время первой итерации внешнего цикла ничего не происходит. Во время второй итерации внешнего цикла продукция переходит в .
Грамматика имеет вид
Устраняем левую рекурсию для
Для произвольной грамматики левую рекурсию можно устранить следующим образом:
- Воспользуемся алгоритмом удаления -правил. Получим грамматику без -правил для языка .
- Воспользуемся алгоритмом устранения произвольной левой рекурсии.
- Если присутствовал в языке исходной грамматики, добавим новый начальный символ и правила .
Литература
- Хопкрофт Д., Мотвани Р., Ульман Д. — Введение в теорию автоматов, языков и вычислений, 2-е изд. : Пер. с англ. — Москва, Издательский дом «Вильямс», 2002. — 528 с. : ISBN 5-8459-0261-4 (рус.)
- Robert C. Moore — Removing Left Recursion from Context-Free Grammars