<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ru">
		<id>http://neerc.ifmo.ru/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=78.37.136.251&amp;*</id>
		<title>Викиконспекты - Вклад участника [ru]</title>
		<link rel="self" type="application/atom+xml" href="http://neerc.ifmo.ru/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=78.37.136.251&amp;*"/>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%BB%D1%83%D0%B6%D0%B5%D0%B1%D0%BD%D0%B0%D1%8F:%D0%92%D0%BA%D0%BB%D0%B0%D0%B4/78.37.136.251"/>
		<updated>2026-04-17T12:28:03Z</updated>
		<subtitle>Вклад участника</subtitle>
		<generator>MediaWiki 1.30.0</generator>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=LL(k)-%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B0%D1%82%D0%B8%D0%BA%D0%B8,_%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D1%81%D1%82%D0%B2%D0%B0_FIRST_%D0%B8_FOLLOW&amp;diff=61645</id>
		<title>LL(k)-грамматики, множества FIRST и FOLLOW</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=LL(k)-%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B0%D1%82%D0%B8%D0%BA%D0%B8,_%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D1%81%D1%82%D0%B2%D0%B0_FIRST_%D0%B8_FOLLOW&amp;diff=61645"/>
				<updated>2017-06-14T22:34:44Z</updated>
		
		<summary type="html">&lt;p&gt;78.37.136.251: /* Алгоритм устранения правого ветвленения */ s/необходимым/достаточным/&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Наибольший интерес в построении синтаксических анализаторов (парсеров) представляют LL(1)-грамматики, так как для них возможно построение нисходящих парсеров без возврата, то есть без корректировки выбранных правил в [[Формальные грамматики | грамматике]]. LL(1)-грамматики являются подмножеством [[Контекстно-свободные грамматики, вывод, лево- и правосторонний вывод, дерево разбора#csgrammar | КС-грамматик]]. Однако для достаточно большого количества [[Основные определения, связанные со строками#deflanguage | формальных языков]] можно построить LL(1)-грамматику, например, для языка арифметических выражений и даже для некоторых языков программирования, в частности можно и для языка Java. &lt;br /&gt;
&lt;br /&gt;
== LL(k)-грамматика ==&lt;br /&gt;
Дадим теперь формально определение LL(k)-грамматики.&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=defLLK &lt;br /&gt;
|definition=&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;\Gamma =\langle \Sigma, N, S, P \rangle&amp;lt;/tex&amp;gt; {{---}} КС-грамматика. Рассмотрим два произвольных левосторонних вывода слова &amp;lt;tex&amp;gt; w &amp;lt;/tex&amp;gt; в этой грамматике:&lt;br /&gt;
* &amp;lt;tex&amp;gt; S \Rightarrow^* p A \beta \Rightarrow  p \alpha \beta \Rightarrow^* p y \eta &amp;lt;/tex&amp;gt;&lt;br /&gt;
* &amp;lt;tex&amp;gt; S \Rightarrow^* p A \beta \Rightarrow  p \alpha' \beta \Rightarrow^* p y \xi &amp;lt;/tex&amp;gt;&lt;br /&gt;
где &amp;lt;tex&amp;gt; p &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; y &amp;lt;/tex&amp;gt; {{---}} цепочки из терминалов, уже разобранная часть слова &amp;lt;tex&amp;gt; w &amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt; A &amp;lt;/tex&amp;gt; {{---}} нетерминал грамматики, в которой есть правила &amp;lt;tex&amp;gt; A \to \alpha &amp;lt;/tex&amp;gt; и  &amp;lt;tex&amp;gt; A \to \alpha' &amp;lt;/tex&amp;gt;, причём &amp;lt;tex&amp;gt; \alpha, \alpha', \beta, \eta, \xi &amp;lt;/tex&amp;gt; {{---}} последовательности из терминалов и нетерминалов.&amp;lt;br&amp;gt;&lt;br /&gt;
Если из выполнения условий, что &amp;lt;tex&amp;gt; |y| = k &amp;lt;/tex&amp;gt; или &amp;lt;tex&amp;gt; |y| &amp;lt; k, \eta = \xi = \varepsilon &amp;lt;/tex&amp;gt;, следует равенство &amp;lt;tex&amp;gt; \alpha = \alpha' &amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt; \Gamma &amp;lt;/tex&amp;gt; называется '''LL(k)-грамматикой'''.&lt;br /&gt;
}}&lt;br /&gt;
LL(1)-грамматика является частным случаем. Её определение почти такое же, только вместо строки &amp;lt;tex&amp;gt; y &amp;lt;/tex&amp;gt; один символ &amp;lt;tex&amp;gt; c \in \Sigma \cup \{\varepsilon\} &amp;lt;/tex&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Неформально это означает, что, посмотрев на очередной символ после уже выведенной части слова, можно однозначно определить, какое правило из грамматики выбрать.&lt;br /&gt;
&lt;br /&gt;
== FIRST и FOLLOW ==&lt;br /&gt;
Ключевую роль в построении парсеров для LL(1)-грамматик играют множества &amp;lt;tex&amp;gt; \mathrm{FIRST} &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; \mathrm{FOLLOW} &amp;lt;/tex&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt; c &amp;lt;/tex&amp;gt; {{---}} символ из алфавита &amp;lt;tex&amp;gt; \Sigma &amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt; \alpha,\ \beta &amp;lt;/tex&amp;gt; {{---}} строки из нетерминалов и терминалов (возможно пустые), &amp;lt;tex&amp;gt; S,\ A &amp;lt;/tex&amp;gt; {{---}} нетерминалы грамматики (начальный и произвольный соответственно), &amp;lt;tex&amp;gt; \$ &amp;lt;/tex&amp;gt; {{---}} символ окончания слова. Тогда определим &amp;lt;tex&amp;gt; \mathrm{FIRST} &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; \mathrm{FOLLOW} &amp;lt;/tex&amp;gt; следующим образом: &lt;br /&gt;
{{Определение&lt;br /&gt;
|id=deffirst&lt;br /&gt;
|definition=&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathrm{FIRST}(\alpha) = \{c \mid \alpha \Rightarrow^* c \beta \} \cup \{ \varepsilon\ \mathrm{if}\ \alpha \Rightarrow^* \varepsilon \} &amp;lt;/tex&amp;gt; &lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=deffirst&lt;br /&gt;
|definition=&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathrm{FOLLOW}(A) = \{c \mid S \Rightarrow^* \alpha A c \beta \} \cup \{ \$ \ \mathrm{if}\ S \Rightarrow^* \alpha A \} &amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
Другими словами, &amp;lt;tex&amp;gt; \mathrm{FIRST}(\alpha) &amp;lt;/tex&amp;gt; {{---}} все символы (терминалы), с которых могут начинаться всевозможные выводы из &amp;lt;tex&amp;gt; \alpha &amp;lt;/tex&amp;gt;, а &amp;lt;tex&amp;gt; \mathrm{FOLLOW}(A) &amp;lt;/tex&amp;gt; {{---}} всевозможные символы, которые встречаются после нетерминала &amp;lt;tex&amp;gt; A &amp;lt;/tex&amp;gt; во всех [[Удаление бесполезных символов из грамматики | небесполезных]] правилах грамматики.&lt;br /&gt;
&lt;br /&gt;
'''Замечание:''' более общим случаем множества &amp;lt;tex&amp;gt; \mathrm{FIRST} &amp;lt;/tex&amp;gt; является множество &amp;lt;tex&amp;gt; \mathrm{FIRST}_k &amp;lt;/tex&amp;gt;, однако в данном конспекте оно не используется.&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=deffirstk&lt;br /&gt;
|definition=&lt;br /&gt;
&amp;lt;tex&amp;gt; \mathrm{FIRST}_k(\alpha) = \{w \mid \alpha \Rightarrow^* w \beta,\ |w| \leqslant k \} \cup \{ \varepsilon\ \mathrm{if}\ \alpha \Rightarrow^* \varepsilon \} &amp;lt;/tex&amp;gt; &lt;br /&gt;
}}&lt;br /&gt;
=== Примеры ===&lt;br /&gt;
Множества &amp;lt;tex&amp;gt; \mathrm{FIRST} &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; \mathrm{FOLLOW} &amp;lt;/tex&amp;gt; могут отличаться даже для одной грамматики, если она задана разными правилами. Рассмотрим пример двух различных грамматик для языка правильных скобочных последовательностей.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tex&amp;gt; A \to (A)A \mid \varepsilon &amp;lt;/tex&amp;gt;&lt;br /&gt;
* &amp;lt;tex&amp;gt; B \to BB \mid (B) \mid \varepsilon &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| Правило&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| FIRST&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| FOLLOW&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ (,\   \varepsilon\ \} &amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 40px&amp;quot;| &amp;lt;tex&amp;gt;\{\ ),\   \$\ \} &amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ (,\   \varepsilon\ \} &amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\{\ (,\ ),\   \$\ \} &amp;lt;/tex&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Теорема о связи LL(1)-грамматики с множествами FIRST и FOLLOW ==&lt;br /&gt;
Далее будет показано, как множества &amp;lt;tex&amp;gt; \mathrm{FIRST} &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; \mathrm{FOLLOW} &amp;lt;/tex&amp;gt; связаны с понятием LL(1)-грамматики.&lt;br /&gt;
{{Теорема&lt;br /&gt;
|id=thLL1 &lt;br /&gt;
|statement= &amp;lt;tex&amp;gt;\Gamma =\langle \Sigma, N, S, P \rangle&amp;lt;/tex&amp;gt; {{---}} LL(1)-грамматика &amp;lt;tex&amp;gt; \Leftrightarrow &amp;lt;/tex&amp;gt;&lt;br /&gt;
# &amp;lt;tex&amp;gt; A \to \alpha,\ A \to \beta, A \in N \ \Rightarrow \ \mathrm{FIRST}(\alpha) \cap \mathrm{FIRST}(\beta) = \varnothing&amp;lt;/tex&amp;gt;&lt;br /&gt;
# &amp;lt;tex&amp;gt; A \to \alpha,\ A \to \beta, A \in N,\ \varepsilon \in \mathrm{FIRST}(\alpha) \ \Rightarrow \ \mathrm{FOLLOW}(A) \cap \mathrm{FIRST}(\beta) = \varnothing&amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
&amp;lt;tex&amp;gt; \Leftarrow &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Предположим, что данная грамматика не будет LL(1)-грамматикой. Значит, у какого-то слова &amp;lt;tex&amp;gt; w &amp;lt;/tex&amp;gt; существует два различных левосторонних вывода.&lt;br /&gt;
* &amp;lt;tex&amp;gt; S \Rightarrow^* p A \gamma \Rightarrow  p \alpha \gamma \Rightarrow^* p c \alpha' \gamma &amp;lt;/tex&amp;gt;&lt;br /&gt;
* &amp;lt;tex&amp;gt; S \Rightarrow^* p A \gamma \Rightarrow  p \beta \gamma \Rightarrow^* p c \beta' \gamma &amp;lt;/tex&amp;gt;&lt;br /&gt;
Но это противоречит тому, что &amp;lt;tex&amp;gt; \mathrm{FIRST}(\alpha) \cap \mathrm{FIRST}(\beta) = \varnothing &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Аналогично проверятся второе условие. Если, например, &amp;lt;tex&amp;gt; \alpha \Rightarrow^* \varepsilon &amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt; \varepsilon \in \mathrm{FIRST}(\alpha) &amp;lt;/tex&amp;gt;, и &amp;lt;tex&amp;gt; \mathrm{FOLLOW}(A) \cap \mathrm{FIRST}(\beta) \ne \varnothing &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \Rightarrow &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Предположим, что есть два различных правила &amp;lt;tex&amp;gt; A \to \alpha &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; A \to \beta &amp;lt;/tex&amp;gt; таких, что &amp;lt;tex&amp;gt; c \in \mathrm{FIRST}(\alpha) \cap \mathrm{FIRST}(\beta) &amp;lt;/tex&amp;gt;. Тогда:&lt;br /&gt;
* &amp;lt;tex&amp;gt; S \Rightarrow^* p A \gamma \Rightarrow  p \alpha \gamma \Rightarrow^* p c \alpha' \gamma &amp;lt;/tex&amp;gt;&lt;br /&gt;
* &amp;lt;tex&amp;gt; S \Rightarrow^* p A \gamma \Rightarrow  p \beta \gamma \Rightarrow^* p c \beta' \gamma &amp;lt;/tex&amp;gt;&lt;br /&gt;
Последний переход можно совершить, так как &amp;lt;tex&amp;gt; c &amp;lt;/tex&amp;gt; лежит в пересечении множеств &amp;lt;tex&amp;gt; \mathrm{FIRST} &amp;lt;/tex&amp;gt; двух правил вывода. Так как грамматика &amp;lt;tex&amp;gt; \Gamma &amp;lt;/tex&amp;gt; является LL(1)-грамматикой, то из [[#defLLK | определения]] следует, что &amp;lt;tex&amp;gt; \alpha = \beta &amp;lt;/tex&amp;gt;. Это противоречит предположению, что &amp;lt;tex&amp;gt; \alpha &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; \beta &amp;lt;/tex&amp;gt; {{---}} различные правила.&lt;br /&gt;
&lt;br /&gt;
Второе условие проверяется аналогичным образом.&lt;br /&gt;
}}&lt;br /&gt;
=== Следствия ===&lt;br /&gt;
Сформулируем несколько важных cледствий из теоремы.&lt;br /&gt;
==== Левая рекурсия ====&lt;br /&gt;
{{Утверждение&lt;br /&gt;
|author=1&lt;br /&gt;
|statement=Грамматика &amp;lt;tex&amp;gt; \Gamma &amp;lt;/tex&amp;gt; cодержит левую рекурсию &amp;lt;tex&amp;gt; \Rightarrow \ \Gamma &amp;lt;/tex&amp;gt; не является LL(1)-грамматикой.&lt;br /&gt;
|proof=&lt;br /&gt;
Если грамматика содержит левую рекурсию, значит, в ней существует какой-то нетерминал &amp;lt;tex&amp;gt; A &amp;lt;/tex&amp;gt; с правилами &amp;lt;tex&amp;gt; A \to A \alpha \mid \beta &amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt; \beta &amp;lt;/tex&amp;gt; {{---}} строка из терминалов и нетерминалов, не начинающаяся с &amp;lt;tex&amp;gt; A &amp;lt;/tex&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Тогда понятно, что &amp;lt;tex&amp;gt; \mathrm{FIRST}(A\alpha) \cap \mathrm{FIRST}(\beta) \ne \varnothing &amp;lt;/tex&amp;gt;, и это противоречит первому условию [[#thLL1 | теоремы]].&lt;br /&gt;
}}&lt;br /&gt;
Чтобы избавиться от левой рекурсии, можно воспользоваться [[Устранение левой рекурсии | алгоритмом устранения левой рекурсии]].&lt;br /&gt;
==== Левая факторизация ====&lt;br /&gt;
{{Утверждение&lt;br /&gt;
|author=2&lt;br /&gt;
|statement=Грамматика &amp;lt;tex&amp;gt; \Gamma &amp;lt;/tex&amp;gt; cодержит правое ветвление &amp;lt;tex&amp;gt; \Rightarrow \ \Gamma &amp;lt;/tex&amp;gt; не является LL(1)-грамматикой.&lt;br /&gt;
|proof=&lt;br /&gt;
Наличие в грамматике правого ветвления означает, что существует правило &amp;lt;tex&amp;gt; A \to \alpha \beta \mid \alpha \gamma, \alpha \ne \varepsilon &amp;lt;/tex&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Очевидно, что &amp;lt;tex&amp;gt; \mathrm{FIRST}(\alpha \beta) \cap \mathrm{FIRST}(\alpha \gamma) \ne \varnothing &amp;lt;/tex&amp;gt;. Поэтому грамматика не будет LL(1)-грамматикой по первому условию [[#thLL1 | теоремы]].&lt;br /&gt;
}}&lt;br /&gt;
===== Алгоритм устранения правого ветвленения =====&lt;br /&gt;
Чтобы избавиться от правого ветвления, нужно воспользоваться алгоритмом левой факторизации. Его суть заключается в следующем: для каждого нетерминала &amp;lt;tex&amp;gt; A &amp;lt;/tex&amp;gt; ищем самый длинный префикс, общий для двух или более правил вывода из &amp;lt;tex&amp;gt; A &amp;lt;/tex&amp;gt;. Важно, чтобы как можно больше строк имело общий префикс, и можно было вынести части правил после общего префикса в отдельный нетерминал. Более формально, рассмотрим правила &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; A \to \alpha \beta_1 \mid \ldots \mid \alpha \beta_n \mid \gamma_1 \mid \ldots \mid \gamma_m &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Причём &amp;lt;tex&amp;gt; \alpha \ne \varepsilon &amp;lt;/tex&amp;gt;, а наибольший общий префикс &amp;lt;tex&amp;gt; \alpha &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; \gamma_i\ (1 \leqslant i \leqslant m&amp;lt;/tex&amp;gt;) равен &amp;lt;tex&amp;gt; \varepsilon &amp;lt;/tex&amp;gt;. Тогда изменим грамматику следующим образом, введя новый нетерминал &amp;lt;tex&amp;gt; A' &amp;lt;/tex&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; A \to \alpha A' \mid \gamma_1 \mid \ldots \mid \gamma_m &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; A' \to \beta_1 \mid \ldots \mid \beta_n &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Алгоритм завершится, когда в грамматике не будет правого ветвления. Он отработает конечное число шагов, так как каждый раз длина правой части правил уменьшается ходя бы на единицу, а тривиальные префиксы мы не рассматриваем. К тому же, алгоритм не меняет язык грамматики, следовательно, является корректным.&lt;br /&gt;
&lt;br /&gt;
'''Замечание:''' отсутствие левой рекурсии и правого ветвления в грамматике не является достаточным условием того, что она будет LL(1)-грамматикой. После их устранения грамматика всё ещё может остаться не LL(1)-грамматикой.&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
* [[Нормальная форма Хомского]]&lt;br /&gt;
* [[Существенно неоднозначные языки]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* [http://en.wikipedia.org/wiki/LL_grammar Wikipedia {{---}} LL grammar]&lt;br /&gt;
* [http://www.math.spbu.ru/user/mbk/PDF/Ch-11.pdf LL(k)-грамматики и трансляция]&lt;br /&gt;
* Альфред Ахо, Рави Сети, Джеффри Ульман. Компиляторы. Принципы, технологии, инструменты. Издательство Вильямс, 2003. ISBN 5-8459-0189-8&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория: Методы трансляции]]&lt;br /&gt;
[[Категория: Нисходящий разбор]]&lt;/div&gt;</summary>
		<author><name>78.37.136.251</name></author>	</entry>

	</feed>