Устранение левой рекурсии — различия между версиями
| MikhailOK (обсуждение | вклад) м (→Алгоритм устранения левой рекурсии) | MikhailOK (обсуждение | вклад)  м (→Алгоритм устранения левой рекурсии) | ||
| Строка 9: | Строка 9: | ||
| Приведем алгоритм, позволяющий для к.с. грамматики '''без ε-правил''' построить эквивалентную ей к.с. грамматику (без ε-правил), не содержащую левой рекурсии. | Приведем алгоритм, позволяющий для к.с. грамматики '''без ε-правил''' построить эквивалентную ей к.с. грамматику (без ε-правил), не содержащую левой рекурсии. | ||
| − | Для произвольной грамматики <tex>\Gamma</tex> левую рекурсию можно устранить следующим образом | + | Для произвольной грамматики <tex>\Gamma</tex> левую рекурсию можно устранить следующим образом: | 
| − | # | + | #Воспользоваться [[Удаление_eps-правил_из_грамматики | алгоритмом удаления ε-правил]]. Получим грамматику без ε-правил для языка <tex>L(\Gamma) \setminus \lbrace \epsilon \rbrace</tex> | 
| − | # | + | #Воспользоваться алгоритмом для новой грамматики | 
| #Если <tex>\epsilon</tex> присутствовал в языке исходной грамматики, добавить новый начальный символ <tex>S'</tex> и правила <tex>S' \rightarrow S \, | \, \epsilon </tex> | #Если <tex>\epsilon</tex> присутствовал в языке исходной грамматики, добавить новый начальный символ <tex>S'</tex> и правила <tex>S' \rightarrow S \, | \, \epsilon </tex> | ||
| ===Устранение непосредственной левой рекурсии=== | ===Устранение непосредственной левой рекурсии=== | ||
Версия 02:23, 16 октября 2010
| Определение: | 
| Говорят, что к.с. грамматика содержит непосредственную левую рекурсию, если она содержит правило вида . | 
| Определение: | 
| Говорят, что к.с. грамматика содержит левую рекурсию, если в ней существует вывод вида . | 
Алгоритм устранения левой рекурсии
Приведем алгоритм, позволяющий для к.с. грамматики без ε-правил построить эквивалентную ей к.с. грамматику (без ε-правил), не содержащую левой рекурсии.
Для произвольной грамматики левую рекурсию можно устранить следующим образом:
- Воспользоваться алгоритмом удаления ε-правил. Получим грамматику без ε-правил для языка
- Воспользоваться алгоритмом для новой грамматики
- Если присутствовал в языке исходной грамматики, добавить новый начальный символ и правила
Устранение непосредственной левой рекурсии
Опишем процедуру, устраняющую все правила вида для фиксированного нетерминала .
Запишем все правила вывода из в виде
где
- - непустая последовательность терминалов и нетерминалов ()
- - непустая последовательность терминалов и нетерминалов, не начинающаяся с .
Заменим правила вывода из на:
И создадим новый нетерминал
Устранение произвольной левой рекурсии
Пусть множество всех нетерминалов
-  for i = 1 to n {
- for j = 1 to i – 1 {
- рассмотреть все правила вывода из
 
- 
- заменить каждое правило на
 
 
- }
- устранить прямую левую рекурсию для
 
- for j = 1 to i – 1 {
- }
Инвариант: после итераций внутреннего цикла для
- для правые части правил вывода из не начинаются с
- правые части правил вывода из не начинаются с
- правые части правил вывода не начинаются с добавленных алгоритмом нетерминалов
- грамматика не содержит ε-правил
(проверяется индукцией по парам )
Таким образом, после применения алгоритма все правила вывода имеют вид
- , где - терминал, - произвольный нетерминал
- , где , - нетерминалы из исходной грамматики
- , где - новый нетерминал, - нетерминал из исходной грамматики
Если теперь перенумеровать нетерминалы, сохранив порядок для старых и присвоив всем новым меньшие номера, то все правила будут иметь вид
- , где - терминал
- , где
