Устранение левой рекурсии — различия между версиями
(→Устранение произвольной левой рекурсии) |
м |
||
| Строка 13: | Строка 13: | ||
<tex>A \rightarrow A\alpha_1\,|\,\ldots\,|\,A\alpha_n\,|\,\beta_1\,|\,\ldots\,|\,\beta_m </tex>, где | <tex>A \rightarrow A\alpha_1\,|\,\ldots\,|\,A\alpha_n\,|\,\beta_1\,|\,\ldots\,|\,\beta_m </tex>, где | ||
<ul> | <ul> | ||
| − | <li> <tex>\alpha</tex> {{---}} непустая последовательность терминалов и нетерминалов (<tex>\alpha \nrightarrow \ | + | <li> <tex>\alpha</tex> {{---}} непустая последовательность терминалов и нетерминалов (<tex>\alpha \nrightarrow \varepsilon </tex>);</li> |
<li> <tex>\beta</tex> {{---}} непустая последовательность терминалов и нетерминалов, не начинающаяся с <tex>A</tex>.</li> | <li> <tex>\beta</tex> {{---}} непустая последовательность терминалов и нетерминалов, не начинающаяся с <tex>A</tex>.</li> | ||
</ul> | </ul> | ||
| Строка 44: | Строка 44: | ||
Для произвольной грамматики <tex>\Gamma</tex> левую рекурсию можно устранить следующим образом: | Для произвольной грамматики <tex>\Gamma</tex> левую рекурсию можно устранить следующим образом: | ||
| − | #Воспользуемся [[Удаление_eps-правил_из_грамматики | алгоритмом удаления <tex> \varepsilon </tex>-правил]]. Получим грамматику без <tex> \varepsilon </tex>-правил для языка <tex>L(\Gamma) \setminus \lbrace \ | + | #Воспользуемся [[Удаление_eps-правил_из_грамматики | алгоритмом удаления <tex> \varepsilon </tex>-правил]]. Получим грамматику без <tex> \varepsilon </tex>-правил для языка <tex>L(\Gamma) \setminus \lbrace \varepsilon \rbrace</tex>. |
#Воспользуемся алгоритмом ''устранения произвольной левой рекурсии''. | #Воспользуемся алгоритмом ''устранения произвольной левой рекурсии''. | ||
| − | #Если <tex>\ | + | #Если <tex>\varepsilon</tex> присутствовал в языке исходной грамматики, добавим новый начальный символ <tex>S'</tex> и правила <tex>S' \rightarrow S \, | \, \varepsilon </tex>. |
Версия 20:53, 23 января 2012
| Определение: |
| Говорят, что контекстно-свободная(КС) грамматика содержит непосредственную левую рекурсию, если она содержит правило вида . |
| Определение: |
| Говорят, что КС-грамматика содержит левую рекурсию, если в ней существует вывод вида . |
Содержание
Устранение непосредственной левой рекурсии
Опишем процедуру, устраняющую все правила вида , для фиксированного нетерминала .
- Запишем все правила вывода из в виде:
, где
- — непустая последовательность терминалов и нетерминалов ();
- — непустая последовательность терминалов и нетерминалов, не начинающаяся с .
- Заменим правила вывода из на .
- Создадим новый нетерминал .
Устранение произвольной левой рекурсии
Пусть — множество всех нетерминалов.
for i = 1 to n
for j = 1 to i – 1
рассмотреть все правила вывода из : .
заменить каждое правило на .
устранить непосредственную левую рекурсию для .
Таким образом, после применения алгоритма все правила вывода имеют вид:
- , где — терминал, — произвольный нетерминал;
- , где , — нетерминалы из исходной грамматики;
- , где — новый нетерминал, — нетерминал из исходной грамматики.
Если теперь перенумеровать нетерминалы, сохранив порядок для старых и присвоив всем новым меньшие номера, то все правила будут иметь вид:
- , где — терминал;
- , где .
Алгоритм устранения левой рекурсии
Для произвольной грамматики левую рекурсию можно устранить следующим образом:
- Воспользуемся алгоритмом удаления -правил. Получим грамматику без -правил для языка .
- Воспользуемся алгоритмом устранения произвольной левой рекурсии.
- Если присутствовал в языке исходной грамматики, добавим новый начальный символ и правила .
Литература
- Хопкрофт Д., Мотвани Р., Ульман Д. — Введение в теорию автоматов, языков и вычислений, 2-е изд. : Пер. с англ. — Москва, Издательский дом «Вильямс», 2002. — 528 с. : ISBN 5-8459-0261-4 (рус.)