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
Copy file name to clipboardExpand all lines: tex/GLL-based_CFPQ.tex
+16-16Lines changed: 16 additions & 16 deletions
Original file line number
Diff line number
Diff line change
@@ -1,6 +1,6 @@
1
1
\chapter{Алгоритм на основе нисходящего анализа}
2
2
3
-
В данном разделе мы рассмотрим семейство алгоритмов нисходящего синтаксического (рекурсивный спуск, LL, GLL~\cite{Scott:2010:GP:1860132.1860320,10.1007/978-3-662-46663-6_5}) рассмотрим их обощение для задачи поиска путей с контекстно-свободными ограничениями.
3
+
В данном разделе мы рассмотрим семейство алгоритмов нисходящего синтаксического (рекурсивный спуск, LL, GLL~\cite{Scott:2010:GP:1860132.1860320,10.1007/978-3-662-46663-6_5}) и их обобщение для задачи поиска путей с контекстно-свободными ограничениями.
4
4
5
5
% и GLL~\cite{Grigorev:2017:CPQ:3166094.3166104} Другие реализации~\cite{MEDEIROS201975}
6
6
@@ -14,7 +14,7 @@ \section{Рекурсивный спуск}
14
14
15
15
У такого подхода есть два ограничения:
16
16
\begin{enumerate}
17
-
\item Не работает с леворекурсивными грамматиками, грамматиками, в которых вывод может принимать следующий вид:
17
+
\item Не работает с леворекурсивными грамматиками, то есть грамматиками, вывод в которых может принимать следующий вид:
18
18
$$
19
19
S \to\cdots\to\underline{N_i} \alpha\to\cdots\underline{N_i} \beta\to\cdots\omega
Пусть $G = \langle N, \Sigma, P, S \rangle$~--- КС-грамматика. Множество $\follow[k]$ определено для сентенциальной формы $\beta$ следующим образом:
117
-
\[\follow[k](\beta) = \{\omega\in\Sigma^* \mid\exists\gamma, \alpha: S \derives{} \gamma\beta\alpha\text{ и } \omega\in\first[k](\alpha) \}\]
117
+
\[\follow[k](\beta) = \{\omega\in\Sigma^* \mid\exists\gamma, \alpha: S \derives{} \gamma\beta\alpha\text{ и } \omega\in\first[k](\alpha) \}\]
118
118
\end{definition}
119
119
120
120
В частном случае для $k = 1$:
121
121
122
-
\[\first(\alpha) = \{ a \in\Sigma\mid\exists\gamma\in (N \cup\Sigma)^*: \alpha\derives{} a \gamma\}\text{, где } \alpha\in (N \cup\Sigma)^* \]
122
+
\[\first(\alpha) = \{ a \in\Sigma\mid\exists\gamma\in (N \cup\Sigma)^*: \alpha\derives{} a \gamma\}\text{, где } \alpha\in (N \cup\Sigma)^* \}\]
123
123
124
-
\[\follow(\beta) = \{ a \in\Sigma\mid\exists\gamma, \alpha\in (N \cup\Sigma)^* : S \derives{} \gamma\beta a \alpha\}\text{, где } \beta\in (N \cup\Sigma)^* \]
124
+
\[\follow(\beta) = \{ a \in\Sigma\mid\exists\gamma, \alpha\in (N \cup\Sigma)^* : S \derives{} \gamma\beta a \alpha\}\text{, где } \beta\in (N \cup\Sigma)^* \}\]
125
125
126
126
Множество $\first$ можно вычислить, пользуясь следующими соотношениями:
127
127
128
128
\begin{itemize}
129
129
\item$\first(a \alpha) = \{a\}, a \in\Sigma, \alpha\in (N \cup\Sigma)^* $
130
130
\item$\first(\varepsilon) = \{\varepsilon\}$
131
131
\item$\first(\alpha\beta) = \first(\alpha) \cup (\first(\beta) \text{, если } \varepsilon\in\first(\alpha))$
132
-
\item$\first(A) = \first(\alpha) \cup\first(\beta) \text{, если в грамматике есть правило } A \to\alpha\mid\beta$
132
+
\item$\first(A) = \first(\alpha) \cup\first(\beta) \text{, если в грамматике есть правила } A \to\alpha\mid\beta$
\item$\follow(S) = \follow(S) \cup\{\$\}\text{, где } S \text{--- стартовый нетерминал}$
140
140
\item Для всех правил вида $A \to\alpha X \beta: \follow(X) = \follow(X) \cup (\first(\beta) \setminus\{\varepsilon\} )$
141
141
\item Для всех правил вида $A \to\alpha X \text{ и } A \to\alpha X \beta\text{, где } \varepsilon\in\first(\beta): \follow(X) = \follow(X) \cup\follow(A)$
142
-
\item Последние два пункта применяются пока есть что добавлять в строящиеся множества.
142
+
\item Последние два пункта применяются, пока есть что добавлять в строящиеся множества.
Можно расширить данный алгоритм так, чтобы он строил дерево вывода. Дерево будет строиться сверху вниз, от корня к листьям. Для этого необходимо расширить шаги алгоритма.
394
394
\begin{itemize}
395
-
\item В ситуации, когда мы читаем очередной нетерминал (на вершине стека и во входе одинаковые терминалы), мы создаём лист с соответствующим терминалом.
395
+
\item В ситуации, когда мы читаем очередной терминал (на вершине стека и во входе одинаковые терминалы), мы создаём лист с соответствующим терминалом.
396
396
\item В ситуации, когда мы заменяем нетерминал на стеке на правую часть продукции в соответствии с управляющей таблицей, мы создаём нетерминальный узел соответствующий применяемой продукции.
397
397
\end{itemize}
398
398
399
-
Данное семейство всё так же не работает с леворекурсивными грамматиками и с неоднозначными грамматиками.
399
+
Данное семейство алгоритмов всё так же не работает с леворекурсивными грамматиками и с неоднозначными грамматиками.
400
400
401
401
Таким образом, по некоторым грамматикам можно построить LL(k) анализатор (назовём их LL(k) грамматиками), но не по всем.
402
402
С левой рекурсией, конечно, можно бороться, так как существуют алгоритмы устранения левой и скрытой левой рекурсии, а вот с неоднозначностями ничего не поделаешь.
Описанная пара позиций уже однозначно задает состояние синтаксического разбора. Имеем множество состояний и переходов между ними --- возникает естественное желание воспользоваться терминами графов для представления этой структуры. Такую конструкцию называют \textit{граф-структурированный стек} или \textit{GSS} (Graph Structured Stack), который впервые был предложен Масару Томитой ~\cite{tomita1988graph} в контексте восходящего анализа. GSS будет являться рабочей структурой нашего нового интерпретатора вместо стека для LL. Состояние разбора вместе с узлом GSS мы будет называть \textit{дескриптором}.
432
432
433
433
\begin{definition}
434
-
Пусть $G = \langle N, \Sigma, P, S \rangle$~--- КС-грамматика, $X$ слот грамматики $G$, $i$ позиция в слове $ w $ над алфавитом $\Sigma$, а $ u $ узел GSS. \textit{Дескриптором} назовём тройку $ (X, u, i) $.
434
+
Пусть $G = \langle N, \Sigma, P, S \rangle$~--- КС-грамматика, $X$~--- слот грамматики $G$, $i$~--- позиция в слове $ w $ над алфавитом $\Sigma$, а $ u $~--- узел GSS. \textit{Дескриптором} назовём тройку $ (X, u, i) $.
435
435
\end{definition}
436
436
437
-
Есть несколько способов задания GSS для алгоритма GLL. Вариант, предложенный самими авторами алгоритма, оперирует непосредственно парами из позиции слова и слота грамматики в качестве состояний (и узлов графа) --- такой метод является довольно простым и наглядным, но, как описано в работе \cite{10.1007/978-3-662-46663-6_5}, не самым эффективным. Предложим сразу чуть более оптимальное представление: заметим, что шаги разбора, соответствующие одному и тому же нетерминалу и позиции слова, должны выдавать один и тот же результат независимо от конкретной продукции грамматики, в которой стоит этот нетерминал. Поэтому заводить по узлу на каждый слот грамматики довольно избыточно --- вместо этого в качестве состояния будет использовать пары из нетерминала и позиции слова, а позиции грамматики будем записывать на рёбрах.
437
+
Есть несколько способов задания GSS для алгоритма GLL. Вариант, предложенный самими авторами алгоритма, оперирует непосредственно парами из позиции слова и слота грамматики в качестве состояний (и узлов графа). Такой метод является довольно простым и наглядным, но, как описано в работе \cite{10.1007/978-3-662-46663-6_5}, не самым эффективным. Предложим сразу чуть более оптимальное представление: заметим, что шаги разбора, соответствующие одному и тому же нетерминалу и позиции слова, должны выдавать один и тот же результат независимо от конкретной продукции грамматики, в которой стоит этот нетерминал. Поэтому заводить по узлу на каждый слот грамматики довольно избыточно --- вместо этого в качестве состояния будем использовать пары из нетерминала и позиции слова, а позиции грамматики будем записывать на рёбрах.
438
438
439
439
Итак, мы научились задавать состояния с помощью дескрипторов, а также определились со вспомогательной структурой GSS. Теперь можно перейти к рассмотрению непосредственно самого алгоритма, суть которого довольно проста и напоминает BFS по неявному графу.
440
440
441
-
Дескриптор задает состояние, которое необходимо обработать. При этом мы без какой-либо дополнительной информации можем продолжить анализ входа из состояния, задаваемого этим дескриптором. В процессе обработки мы можем получить несколько новых состояний. Поэтому будем поддерживать множество $ R $ дескрипторов на обработку --- на каждом шаге извлекаем один из множества, проводим анализ и кладем в множество новые полученные.
441
+
Дескриптор задает состояние, которое необходимо обработать. При этом мы без какой-либо дополнительной информации можем продолжить анализ входа из состояния, задаваемого этим дескриптором. В процессе обработки мы можем получить несколько новых состояний. Поэтому будем поддерживать множество $ R $ дескрипторов на обработку --- на каждом шаге извлекаем один из множества, проводим анализ и добавляем во множество новые полученные.
442
442
443
-
При каких условиях этот процесс будет конечен? Ну, например, если мы каждое состояние будем обрабатывать не более одного раза. И действительно, поскольку наш интерпретатор является ``чистым'' в том смысле, что для оного и того же состояния каждый раз будут получены одинаковые результаты, проводить анализ дважды не имеет смысла. Поэтому будем также поддерживать множество $ U $ всех полученных в ходе разбора дескрипторов, и добавлять в $ R $ только те, которых еще нет в $ U $.
443
+
При каких условиях этот процесс будет конечен? Ну, например, если мы каждое состояние будем обрабатывать не более одного раза. И действительно, поскольку наш интерпретатор является ``чистым'' в том смысле, что для одного и того же состояния каждый раз будут получены одинаковые результаты, проводить анализ дважды не имеет смысла. Поэтому будем также поддерживать множество $ U $ всех полученных в ходе разбора дескрипторов, и добавлять в $ R $ только те, которых еще нет в $ U $.
444
444
445
445
И наконец, заключительная и самая главная часть --- как происходит обработка дескриптора?
446
446
Пусть дескриптор имеет вид $ (X, u, i) $, а входное слово обозначим $ W $. Есть три возможных варианта, в зависимости от вида позиции грамматики $ X $ --- разберем каждый из них по отдельности;
447
447
448
448
\begin{itemize}
449
-
\item$ X ::= \alpha\cdot t \beta$, т.е. указатель смотрит на терминал --- в этом случае новых дескрипторов добавлено не будет. Если $ W[i] = t $, то мы сдвигаем указатель слота, переходя к рассмотрению $ X ::= \alpha t \cdot\beta$, и инкрементируем позицию $ i $ в слове. В противном же случае сразу переходим к следующему дескриптору, т.о. терминируя текущую ветвь разбора.
449
+
\item$ X ::= \alpha\cdot t \beta$, т.е. указатель смотрит на терминал --- в этом случае новых дескрипторов добавлено не будет. Если $ W[i] = t $, то мы сдвигаем указатель слота, переходя к рассмотрению $ X ::= \alpha t \cdot\beta$, и инкрементируем позицию $ i $ в слове. В противном же случае сразу переходим к следующему дескриптору, таким образом терминируя текущую ветвь разбора.
450
450
451
451
\item$ X ::= \alpha\cdot A \beta$, т.е. указатель смотрит на нетерминал. Нам нужен GSS узел $ v $ вида $ (A, i) $ и ребро $ (u, X ::= \alpha A \cdot\beta, v) $ (ребро из $ u $ в $ v $ с пометкой $ X ::= \alpha A \cdot\beta$). Если такой узел и ребро уже существуют в нашем GSS, берем их, иначе --- создаём. Далее в $ R $ добавляем по дескриптору для узла $ v $ и каждого правила грамматики из ячейки управляющей таблицы для нетерминала $ A $ (конечно, если их еще не было в $ U $). На этом обработка текущего дескриптора завершается.
0 commit comments