You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Иерархию языков, распознаваемых различными классами алгоритмов, можно представить как изображено на рисунке~\ref{fig:ll_lr_comparison}.
4
8
@@ -10,9 +14,85 @@ \section{Сравнение классов LL и LR}
10
14
\label{fig:ll_lr_comparison}
11
15
\end{marginfigure}
12
16
13
-
Из диаграммы видно, что класс языков, распознаваемых LL(k) алгоритмом уже, чем класс языков, распознаваемый LR(k) алгоритмом, при любом конечном $k$. Приведём несколько примеров.
14
-
\begin{enumerate}
15
-
\item$L = \{a^mb^nc \mid m \geq n \geq0\}$ является LR(0), но для него не существует LL(1) грамматики.
16
-
\item$L = \{ a^n b^n + a^n c^n \mid n > 0\}$ является LR, но не LL.
17
-
\item Больше примеров можно найти в работе Джона Битти~\cite{BEATTY1980193}.
18
-
\end{enumerate}
17
+
Из диаграммы видно, что класс языков, распознаваемых $LL(k)$ алгоритмом, уже, чем класс языков, распознаваемых $LR(k)$ алгоритмом, при любом конечном $k$. Ниже мы разберём два классических примера языков, демонстрирующих данное различие.
18
+
19
+
\begin{example}
20
+
\label{ex:ll_lr_ambnc}
21
+
Рассмотрим язык $L_1 = \{ a^m b^n c \mid m \geq n \geq0\}$. Покажем, что он является $LR(0)$, но не является $LL(1)$.
22
+
23
+
Язык $L_1$ порождается следующей грамматикой $G_1 = \langle\{S, T\}, \{a, b, c\}, P, S \rangle$, где $P$ состоит из правил:
24
+
\begin{align*}
25
+
S &\to a S \mid T c \mid c \\
26
+
T &\to a T b \mid a b
27
+
\end{align*}
28
+
29
+
Интуитивно, $T$ порождает $a^n b^n$ (n \geq 1), $S \to a S$ добавляет <<лишние>> $a$, а $S \to T c$ и $S \to c$ завершают вывод, добавляя терминальный символ $c$.
30
+
31
+
Покажем, что $G_1$ является $LR(0)$. Расширим грамматику, пронумеровав продукции:
32
+
\begin{align*}
33
+
(0)\; S' &\to S \$ & (3)\; S &\to c \\
34
+
(1)\; S &\to a S & (4)\; T &\to a T b \\
35
+
(2)\; S &\to T c & (5)\; T &\to a b
36
+
\end{align*}
37
+
38
+
$LR(0)$-автомат для расширенной грамматики $G_1$\fixit{изображён}{Нормально разложить автомат. Провреить, что он кореектен.} \fixit{на рисунке}{Нормально оформить оисунок и ссылку на него (через figure и т.д.)}
Состояния, содержащие пункты свёртки~--- это 3 ($S \to c\cdot$), 5 ($S \to aS\cdot$), 7 ($T \to ab\cdot$), 8 ($T \to aTb\cdot$) и 9 ($S \to Tc\cdot$). Каждое из них содержит ровно один такой пункт и не содержит пунктов сдвига. Конфликтов нет~--- грамматика $LR(0)$.
45
+
46
+
Теперь покажем, что $G_1$ не является $LL(1)$. Вычислим множества $\first$:
47
+
\[
48
+
\first(S) = \{a, c\}, \qquad\first(T) = \{a\}.
49
+
\]
50
+
Для продукций $S$\fixit{имеем:}{Поправить вёрстку}
51
+
\[
52
+
\first(a S) = \{a\}, \qquad\first(T c) = \first(T) \cup (\first(c) \text{ т.к. } \varepsilon\notin\first(T)) = \{a\}.
53
+
\]
54
+
Пересечение $\first(a S) \cap\first(T c) = \{a\}$ непусто. При предпросмотре символа $a$$LL(1)$-анализатор не может выбрать между продукциями $S \to a S$ и $S \to T c$~--- конфликт.
55
+
56
+
Более того, $L_1$ не является $LL(k)$ ни для какого фиксированного $k$. Действительно, в любой момент разбора, когда прочитано несколько $a$, необходимо решить, будут ли эти $a$ впоследствии спарены с символами $b$ или останутся <<лишними>>. Разница между числом $a$ и числом $b$ может быть сколь угодно большой, поэтому для принятия верного решения требуется заглянуть за все символы $a$~--- предпросмотр неограниченной глубины. Следовательно, язык принадлежит классу $LR(0)$, но не принадлежит классу $LL(k)$ ни при каком $k$.
57
+
\end{example}
58
+
59
+
\begin{example}
60
+
\label{ex:ll_lr_anbnancn}
61
+
Рассмотрим язык $L_2 = \{ a^n b^n \mid n > 0\}\cup\{ a^n c^n \mid n > 0\}$. Покажем, что он является $LR(0)$, но не является $LL(k)$ ни для какого $k$.
62
+
63
+
Язык $L_2$ порождается грамматикой $G_2 = \langle\{S, A, B\}, \{a, b, c\}, P, S \rangle$, где $P$:
(0)\; S' &\to S \$ & (3)\; A &\to a A b & (5)\; B &\to a B c \\
75
+
(1)\; S &\to A & (4)\; A &\to a b & (6)\; B &\to a c \\
76
+
(2)\; S &\to B
77
+
\end{align*}
78
+
79
+
$LR(0)$-автомат для расширенной грамматики $G_2$\fixit{изображён}{Нормально разложить автомат. Провреить, что он кореектен.} \fixit{на рисунке}{Нормально оформить оисунок и ссылку на него (через figure и т.д.)}.
Состояния, содержащие пункты свёртки~--- это 2 ($S \to A\cdot$), 3 ($S \to B\cdot$), 8 ($A \to ab\cdot$), 9 ($B \to ac\cdot$), 10 ($A \to aAb\cdot$) и 11 ($B \to aBc\cdot$). Как и в первом примере, каждое из них содержит ровно один пункт и не содержит пунктов сдвига. Конфликтов нет~--- грамматика $LR(0)$.
86
+
87
+
Покажем, что $G_2$ не является $LL(k)$ ни для какого $k$. Вычислим $\first$:
88
+
\[
89
+
\first(A) = \first(B) = \{a\}.
90
+
\]
91
+
Поскольку $\first(A) \cap\first(B) = \{a\}\neq\varnothing$, $LL(1)$-анализатор не может выбрать между $S \to A$ и $S \to B$ при предпросмотре символа $a$.
92
+
93
+
Более того, при любом фиксированном $k$ предпросмотр $k$ символов не помогает: для $n > k$ первые $k$ символов цепочки~--- это $a^k$, и на основании них невозможно определить, с каким символом~--- $b$ или $c$~--- эти $a$ должны быть спарены. Различающий символ находится на позиции $n$, которая может быть сколь угодно большой. Таким образом, $L_2$ не является $LL(k)$ ни для какого конечного $k$.
94
+
95
+
Данный пример особенно наглядно демонстрирует принципиальное различие между восходящими и нисходящими анализаторами: $LR$-анализатор принимает решение о свёртке, уже увидев различающий символ ($b$ или $c$), в то время как $LL$-анализатор вынужден предсказывать, какую продукцию применять, до того как релевантная информация становится доступной.
96
+
\end{example}
97
+
98
+
Больше примеров языков, разделяющих классы $LL(k)$ и $LR(k)$, можно найти в работе Джона Битти~\sidecite{BEATTY1980193}.
Copy file name to clipboardExpand all lines: tex/part_02_Foundations/chapter_07_ClassicalParsing/main.tex
+2Lines changed: 2 additions & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -2,6 +2,8 @@
2
2
\chapter{Классические алгоритмы синтаксического анализа для строк}
3
3
\tikzsetfigurename{ClassicalParsing_}
4
4
5
+
\mytodo{Унифицировать вёрстку стеков в примерах для LL и LR}
6
+
5
7
В данной главе мы рассмотрим классические алгоритмы синтаксического анализа для строк.
6
8
Эти алгоритмы составляют фундамент, на котором далее будут построены алгоритмы поиска путей с контекстно-свободными ограничениями в графах (главы~\ref{chpt:CFPQ_CYK}--\ref{chpt:GLR}).
0 commit comments