\documentclass[12pt]{beamer}
\mode<presentation>
\author{Aleksej Saushev \\ \texttt{
[email protected]}}
\date{Some day}
\title[Crash course]{Parsing for Impatient}
\begin{document}
\frame{\titlepage}
\begin{frame}[fragile]{Context-free grammars}
Context-free grammar (CFG) is:
\begin{itemize}
\item Alphabet, set of terminal symbols, ``terminals.''
\item Set of non-terminal symbols, ``nonterminals.''
\item Starting symbol.
\item Rules (productions) like:
\begin{eqnarray*}
S & \rightarrow & S_0 S_1 S_2 ... S_{n-1} \\
S & \rightarrow & \_
\end{eqnarray*}
\end{itemize}
Terminals and nonterminals are disjunctive.
Recursive rules allowed.
\end{frame}
\begin{frame}[fragile]{Context-free grammars}
Sample grammar:
\begin{itemize}
\item Alphabet of decimal digits and arithmetic operations ``$+$'' and ``$-$''.
\item $E$ is the only nonterminal.
\item $E$ is starting symbol
\item Rules:
\begin{eqnarray*}
E & \rightarrow & 1 \\
E & \rightarrow & E + E
\end{eqnarray*}
\end{itemize}
\end{frame}
\begin{frame}[fragile]{Context-free grammars}
CFG is ``generative''
\begin{equation*}
E \rightarrow E + E \rightarrow E + E + E \rightarrow E + 1 + E \rightarrow E + 1 + 1 \rightarrow 1 + 1 + 1
\end{equation*}
Sentences of the language are \underline{produced} from start symbol
by rewriting strings of symbols following given rules.
\end{frame}
\begin{frame}[fragile]{Unger}
Straightforward interpretation of grammar rule: \\
symbols or rules matche substring of input string between given points.
\begin{itemize}
\item Terminal symbol matches substring of length 1
and only if the input symbol matches.
\item Non-terminal symbol matches,
if there's rule for that symbol that matches.
\item Empty rule matches empty substring.
\item Rule $S \rightarrow S_0 S_1 S_2 ... S_{n-1}$
matches substring of input string between points $p$ and $p'$,
if there exist points
$p = p_0 \leq p_1 \leq p_2 \leq ... \leq p_{n-1} \leq p_n = p'$
such that $S_k$ matches substring between points $p_{k}$ and $p_{k+1}$,
terminal symbols match equal terminal symbols
\end{itemize}
Input string matches start symbol.
\end{frame}
\begin{frame}[fragile]{Unger}
Formally:
\begin{itemize}
\item $s(S, w, p, p') := t(S), p' = p + 1, w[p] \sim T$,
\item $s(S, w, p, p') := nt(S), r(S \rightarrow S_0 ... S_{n-1}, w, p, p')$,
\item $r(S \rightarrow \_, w, p, p') := p' = p$,
\item
\begin{multline*}
r(S \rightarrow S_0 ... S_{n-1}, w, p, p') := \\
\begin{aligned}
& p = p_0 \leq ... \leq p_{n-1} \leq p_n = p', \\
& s(S_0, w, p_0, p_1), \\
& s(S_1, w, p_1, p_2), \\
& ... \\
& s(S_{n-1}, w, p_{n-1}, p_n).
\end{aligned}
\end{multline*}
\end{itemize}
\end{frame}
\begin{frame}[fragile]{Unger}
Strings are finite:
\begin{equation*}
0 \leq p \leq l
\end{equation*}
\pause
\begin{center}
Brute force search.
\end{center}
\end{frame}
\begin{frame}[fragile]{Unger}
Left recursion:
\begin{eqnarray*}
S & \rightarrow & S S, \\
S & \rightarrow & \_
\end{eqnarray*}
\begin{eqnarray*}
&& s(S, w, 0, 0), \\
&& r(S \rightarrow S S, w, 0, 0), \\
&& s(S, w, 0, 0), s(S, w, 0, 0), \\
&& r(S \rightarrow S S, w, 0, 0), s(S, w, 0, 0), \\
&& ...
\end{eqnarray*}
\end{frame}
\begin{frame}[fragile]{Unger}
Left recursion:
\begin{eqnarray*}
S & \rightarrow & S S
\end{eqnarray*}
\begin{eqnarray*}
&& s(S, w, 0, 0), \\
&& r(S \rightarrow S S, w, 0, 0), \\
&& s(S, w, 0, 0), s(S, w, 0, 0), \\
&& r(S \rightarrow S S, w, 0, 0), s(S, w, 0, 0), \\
&& ...
\end{eqnarray*}
\end{frame}
\begin{frame}[fragile]{Unger}
Reentered rule matcher with the same arguments.
Elimination of non-producing cases.
\end{frame}
\begin{frame}[fragile]{Unger}
Recursion elimination.
\begin{multline*}
\begin{aligned}
r(S \rightarrow S_0 ... S_{n-1}, w, p, p') := \\
{\rm (if~matching~already,~fail~immediately;} \\
{\rm otherwise~mark~matching),}\\
p = p_0 \leq ... \leq p_{n-1} \leq p_n = p', \\
s(S_0, w, p_0, p_1), \\
s(S_1, w, p_1, p_2), \\
... \\
s(S_{n-1}, w, p_{n-1}, p_n).
\end{aligned}
\end{multline*}
\end{frame}
\begin{frame}[fragile]{Unger}
Exponential time.
\begin{multline*}
\begin{aligned}
r(S \rightarrow S_0 ... S_{n-1}, w, p, p') := \\
{\rm (if~matching~already,~fail~immediately;} \\
{\rm otherwise~mark~matching),} \\
{\rm (if~have~result,~return~result~immediately),} \\
p = p_0 \leq ... \leq p_{n-1} \leq p_n = p', \\
s(S_0, w, p_0, p_1), \\
s(S_1, w, p_1, p_2), \\
... \\
s(S_{n-1}, w, p_{n-1}, p_n), \\
{\rm (remember~result).}
\end{aligned}
\end{multline*}
No longer exponential. (Books fail to tell you that!)
\end{frame}
\begin{frame}[fragile]{Combinators}
\begin{eqnarray*}
r'(R, w, p) & := & \{p' | r(R, w, p, p')\}. \\
s'(S, w, p) & := & \{p' | s(S, w, p, p')\}.
\end{eqnarray*}
\begin{eqnarray*}
r'(S \rightarrow S_0 ... S_{n-1}, w, p) & := & \{p' | r(S \rightarrow S_0 ... S_{n-1}, w, p, p')\}. \\
s'(S, w, p) & := & \{p' | s(S, w, p, p')\}.
\end{eqnarray*}
\begin{eqnarray*}
r(R, w, p, p') & \Leftrightarrow & p' \in r'(R, w, p). \\
s(S, w, p, p') & \Leftrightarrow & p' \in s'(S, w, p).
\end{eqnarray*}
\end{frame}
\begin{frame}[fragile]{Combinators}
\begin{equation*}
r'(S \rightarrow \_, w, p) = \{p' | r(S \rightarrow _, w, p, p')\} = \{p' | p' = p\} = \{p\}.
\end{equation*}
\begin{multline*}
s'(T, w, p)
= \{p' | s(T, w, p, p')\} \\
= \{p' | p' = p + 1, w[p] \sim T\} \\
= \{p+1 | w[p] \sim T\}.
\end{multline*}
\begin{eqnarray*}
s'(T, w, p) & = & \{p+1\},\quad {\rm when~} w[p] \sim T. \\
s'(T, w, p) & = & \{\}, \quad {\rm otherwise}.
\end{eqnarray*}
\end{frame}
\begin{frame}[fragile]{Combinators}
\begin{multline*}
s'(S, w, p) = \{p' | s(S, w, p, p')\} \\
= \{p' | R = S \rightarrow S_0 ... S_{n-1}, r(R, w, p, p')\} \\
= \{p' | R = S \rightarrow S_0 ... S_{n-1}, p' \in r'(R, w, p)\} \\
= \bigcup \{r'(R, w, p) | R = S \rightarrow S_0 ... S_{n-1}\}.
\end{multline*}
\end{frame}
\begin{frame}[fragile]{Combinators}
\begin{equation*}
r'(S \rightarrow S_0 ... S_{n-1}, w, p)
= \{p' | r(S \rightarrow S_0 ... S_{n-1}, w, p, p')\}
\end{equation*}
\begin{multline*}
\begin{aligned}
r'(S \rightarrow S_0 ... S_{n-1}, w, p) \\
= \{p' | & p = p_0 \leq ... \leq p_{n-1} \leq p_n = p', & \\
& s(S_0, w, p_0, p_1), & \\
& s(S_1, w, p_1, p_2), & \\
& ... & \\
& s(S_{n-1}, w, p_{n-1}, p_n)\} & \\
\end{aligned}
\end{multline*}
\end{frame}
\begin{frame}[fragile]{Combinators}
\begin{multline*}
\begin{aligned}
r'(S \rightarrow S_0 ... S_{n-1}, w, p) \\
= \{p' | & p = p_0 \leq ... \leq p_{n-1} \leq p_n = p', \\
& s(S_0, w, p_0, p_1), \\
& s(S_1, w, p_1, p_2), \\
& ... \\
& s(S_{n-1}, w, p_{n-1}, p_n)\} \\
\end{aligned}
\end{multline*}
%
\begin{multline*}
\begin{aligned}
r'(S \rightarrow S_0 ... S_{n-1}, w, p) \\
= \{p' | & p_0 = p, p' = p_n, \\
& p_1 \in s'(S_0, w, p_0), \\
& p_2 \in s'(S_1, w, p_1), \\
& ... \\
& p_n \in s'(S_{n-1}, w, p_{n-1})\}
\end{aligned}
\end{multline*}
\end{frame}
\begin{frame}[fragile]{Combinators}
\begin{multline*}
\begin{aligned}
r'(S \rightarrow S_0 ... S_{n-1}, w, p) \\
= \{p' | & p_0 = p, p' = p_n, \\
& p_1 \in s'(S_0, w, p_0), \\
& p_2 \in s'(S_1, w, p_1), \\
& ... \\
& p_n \in s'(S_{n-1}, w, p_{n-1})\}
\end{aligned}
\end{multline*}
%
\begin{multline*}
\begin{aligned}
r'(S \rightarrow S_0 ... S_{n-1}, w, p) \\
= \{p_n | & p_1 \in s'(S_0, w, p), \\
& p_2 \in s'(S_1, w, p_1), \\
& ... \\
& p_n \in s'(S_{n-1}, w, p_{n-1})\}
\end{aligned}
\end{multline*}
\end{frame}
\begin{frame}[fragile]{Combinators}
\begin{multline*}
\begin{aligned}
r'(S \rightarrow S_0 ... S_{n-1}, w, p) \\
= \{p_n | & p_1 \in s'(S_0, w, p), \\
& p_2 \in s'(S_1, w, p_1), \\
& ... \\
& p_n \in s'(S_{n-1}, w, p_{n-1})\}
\end{aligned}
\end{multline*}
%
\begin{multline*}
\begin{aligned}
r'(S \rightarrow S_0 ... S_{n-1}, w, p) \\
= \{p_n | & p_{n-1} \in \{p_{n-1} | & p_1 \in s'(S_0, w, p), & \\
& & p_2 \in s'(S_1, w, p_1), & \\
& & ... & \\
& & p_{n-1} \in s'(S_{n-2}, w, p_{n-2})\}, & \\
& p_n \in s'(S_{n-1}, w, p_{n-1})\} &
\end{aligned}
\end{multline*}
\end{frame}
\begin{frame}[fragile]{Combinators}
\begin{multline*}
\begin{aligned}
r'(S \rightarrow S_0 ... S_{n-1}, w, p) \\
= \{p_n | & p_{n-1} \in \{p_{n-1} | & p_1 \in s'(S_0, w, p), & \\
& & p_2 \in s'(S_1, w, p_1), & \\
& & ... & \\
& & p_{n-1} \in s'(S_{n-2}, w, p_{n-2})\}, & \\
& p_n \in s'(S_{n-1}, w, p_{n-1})\} &
\end{aligned}
\end{multline*}
%
\begin{multline*}
\begin{aligned}
r'(S \rightarrow S_0 ... S_{n-1}, w, p) \\
= \{p_n | & p_{n-1} \in r'(S \rightarrow S_0 ... S_{n-2}, w, p) \\
& p_n \in s'(S_{n-1}, w, p_{n-1})\}
\end{aligned}
\end{multline*}
\end{frame}
\begin{frame}[fragile]{Combinators}
\begin{equation*}
\{y | x \in X, y \in f(x)\} = \bigcup \{f(x) | x \in X\} = u(m(f, X)),
\end{equation*}
where $m(f, X)$ is pointwise map of set X (``map''),
$u(Y)$ is union of set of sets.
\end{frame}
\begin{frame}[fragile]{Combinators}
\begin{equation*}
\{y | x \in X, y \in f(x)\} = \bigcup \{f(x) | x \in X\} = u(m(f, X)),
\end{equation*}
%
\begin{multline*}
\begin{aligned}
r'(S \rightarrow S_0 ... S_{n-1}, w, p) \\
= \{p_n | & p_{n-1} \in r'(S \rightarrow S_0 ... S_{n-2}, w, p) \\
& p_n \in s'(S_{n-1}, w, p_{n-1})\} &
\end{aligned}
\end{multline*}
%
\begin{multline*}
\begin{aligned}
r'(S \rightarrow S_0 ... S_{n-1}, w, p)
= u(m(&(p \mapsto s'(S_{n-1}, w, p)), \\
&r'(S \rightarrow S_0 ... S_{n-2}, w, p)
\end{aligned}
\end{multline*}
\end{frame}
\begin{frame}[fragile]{Combinators}
\begin{multline*}
\begin{aligned}
r'(S \rightarrow S_0 ... S_{n-1}, w, p)
= u(m(&(p \mapsto s'(S_{n-1}, w, p)), \\
&r'(S \rightarrow S_0 ... S_{n-2}, w, p)
\end{aligned}
\end{multline*}
%
\begin{multline*}
r'(S \rightarrow S_0 ... S_{n-1}, w, p) \\
\begin{aligned}
= u(m(&(p \mapsto s'(S_{n-1}, w, p)), \\
&u(m(&(p \mapsto s'(S_{n-2}, w, p)), \\
r'(S \rightarrow S_0 ... S_{n-2}, w, p)
\end{aligned}
\end{multline*}
\end{frame}
\begin{frame}[fragile]{Combinators}
\begin{verbatim}
r'(S -> S_0 ... S_{n-1}, w, p)
= {p_n | p_1 <- s'(S_0, w, p),
p_2 <- s'(S_1, w, p_1),
...
p_{n-1} <- s'(S_{n-1}, w, p_{n-2}),
p_n <- s'(S_{n-1}, w, p_{n-1})}
= {p_n | p_{n-1} <- {p_{n-1} | p_1 <- s'(S_0, w, p),
p_2 <- s'(S_1, w, p_1),
...
p_{n-1} <- s'(S_{n-1}, w, p_{n-2})},
p_n <- s'(S_{n-1}, w, p_{n-1})}
= {p_n | p_{n-1} <- r'(S -> S_0 ... S_{n-2}, w, p),
p_n <- s'(S_{n-1}, w, p_{n-1})}
\end{verbatim}
\end{frame}
\begin{frame}[fragile]{Combinators}
\begin{verbatim}
r'(S -> S_0 ... S_{n-1}, w, p)
= {p_n | p_{n-1} <- r'(S -> S_0 ... S_{n-2}, w, p),
p_n <- s'(S_{n-1}, w, p_{n-1})}
= u(m((p +-> s'(S_{n-1}, w, p)),
r'(S -> S_0 ... S_{n-2}, w, p)))
\end{verbatim}
\end{frame}
\begin{frame}[fragile]{Combinators}
\begin{verbatim}
r'(S -> S_0 ... S_{n-1}, w, p)
= u(m((p +-> s'(S_{n-1}, w, p)),
u(m((p +-> s'(S_{n-2}, w, p)),
r'(S -> S_0 ... S_{n-3}, w, p)))))
= ...
= u(m((p +-> s'(S_{n-1}, w, p)),
u(m((p +-> s'(S_{n-2}, w, p)),
...
u(m((p +-> s'(S_1, w, p)),
r'(S -> S_0, w, p)))))))
\end{verbatim}
\end{frame}
\begin{frame}[fragile]{Combinators}
\begin{verbatim}
r'(S -> S_0 ... S_{n-1}, w, p)
= u(m((p +-> s'(S_{n-1}, w, p)),
u(m((p +-> s'(S_{n-2}, w, p)),
...
u(m((p +-> s'(S_1, w, p)),
r'(S -> S_0, w, p)))))))
= u(m((p +-> s'(S_{n-1}, w, p)),
u(m((p +-> s'(S_{n-2}, w, p)),
...
u(m((p +-> s'(S_1, w, p)),
s'(S_0, w, p)))))))
\end{verbatim}
\end{frame}
\begin{frame}[fragile]{Combinators}
\begin{verbatim}
r'(S -> S_0 ... S_{n-1}, w, p)
= u(m((p +-> s'(S_{n-1}, w, p)),
u(m((p +-> s'(S_{n-2}, w, p)),
...
u(m((p +-> s'(S_1, w, p)),
s'(S_0, w, p)))))))
\end{verbatim}
\end{frame}
\begin{frame}[fragile]{Combinators}
\begin{equation*}
\{f(x)\} = u(\{\{f(x)\}\}) = u(m(f, \{x\})).
\end{equation*}
\begin{verbatim}
{f(x)} = u({{f(x)}}) = u(m(f, {x})).
r'(S -> S_0 ... S_{n-1}, w, p)
= u(m((p +-> s'(S_{n-1}, w, p)),
u(m((p +-> s'(S_{n-2}, w, p)),
...
u(m((p +-> s'(S_1, w, p)),
s'(S_0, w, p)))))))
r'(S -> S_0 ... S_{n-1}, w, p)
= u(m((p +-> s'(S_{n-1}, w, p)),
u(m((p +-> s'(S_{n-2}, w, p)),
...
u(m((p +-> s'(S_1, w, p)),
u(m((p +-> s'(S_0, w, p)), {p})))))))).
\end{verbatim}
\end{frame}
\begin{frame}[fragile]{Combinators}
\begin{verbatim}
r'(S -> S_0 ... S_{n-1}, w, p)
= u(m((p +-> s'(S_{n-1}, w, p)),
u(m((p +-> s'(S_{n-2}, w, p)),
...
u(m((p +-> s'(S_1, w, p)),
u(m((p +-> s'(S_0, w, p)), {p})))))))).
\end{verbatim}
\end{frame}
\begin{frame}[fragile]{Combinators}
\begin{equation*}
z_i(x) := u(m((p \mapsto s'(S_i, w, p)), x))
\end{equation*}
\begin{equation*}
r'(S \rightarrow S_0 ... S_{n-1}, w, p) = (z_{n-1} \circ ... \circ z_0)({p}).
\end{equation*}
\end{frame}
%% \begin{frame}[fragile]{Combinators}
%% \begin{multline*}
%% r'(S \rightarrow S_0 ... S_{n-1}, w, p) \\
%% %
%% = \{p_n | p_1 \in s'(S_0, w, p), \\
%% p_2 \in s'(S_1, w, p_1), \\
%% ... \\
%% p_n \in s'(S_{n-1}, w, p_{n-1})\}
%% %
%% =
%% \begin{aligned}
%% \{p_n | & p_1 \in s'(S_0, w, p), \\
%% & p_2 \in s'(S_1, w, p_1), \\
%% & ... \\
%% & p_n \in s'(S_{n-1}, w, p_{n-1})\}
%% \end{aligned}
%% %
%% = u(m((p \mapsto s'(S_{n-1}, w, p)),
%% \{p_{n-1} | p_1 \in s'(S_0, w, p),
%% p_2 \in s'(S_1, w, p_1)
%% ...
%% p_{n-1} \in s'(S_{n-2}, w, p_{n-2})\}))
%% %
%% = u(m((p \mapsto s'(S_{n-1}, w, p)),
%% \{p_{n-1} | p_1 \in s'(S_0, w, p),
%% p_2 \in s'(S_1, w, p_1)
%% ...
%% p_{n-1} \in s'(S_{n-2}, w, p_{n-2})\}))
%% %
%% = u(m((p \mapsto s'(S_{n-1}, w, p)), \\
%% u(m((p \mapsto s'(S_{n-2}, w, p)), \\
%% ... \\
%% u(m((p \mapsto s'(S_1, w, p)), \\
%% s'(S_0, w, p))))))) \\
%% \end{multline*}
%% \end{frame}
\begin{frame}[fragile]{Combinators}
Rule: $S \rightarrow S_0 ... S_{n-1}$. \\
Recognizer: $r'' = s''_0 * ... * s''_{n-1}$. \\
Recognizer for symbols combines all respective rules: \\
$s = r''_0 + ... + r''_{m-1}.$
\end{frame}
\begin{frame}[fragile]{Combinators}
If mapping symbols to sets of symbols:
\begin{eqnarray*}
(s''_A * s''_B)(p) = u(m(s''_B, s''_A(p))) = u(m(s''_B, u(m(s''_A, \{p\})))). \\
(r''_1 + r''_2)(p) = u(\{r''_1(p), r''_2(p)\}) = r''_A(p) \cup r''_B(p).
\end{eqnarray*}
If mapping sets of symbols to sets of symbols:
\begin{eqnarray*}
(s''_A * s''_B)(P) = u(m(s''_B, u(m(s''_A, P)))). \\
(r''_1 + r''_2)(P) = u(\{r''_1(p), r''_2(p)\}) = m(r''_1, P) \cup m(r''_2, P).
\end{eqnarray*}
\end{frame}
\begin{frame}[fragile]{Monads}
$\{p\}$ is ``unit'', $m$ is ``map'', $u$ is ``union''.
Haskell does it alternatively:
\begin{equation*}
(x >>= f) = u(m(f, x))
\end{equation*}
\end{frame}
\begin{frame}[fragile]{LL(1)}
Predicting the rule using lookahead information.
\pause
LL(0) is either empty or single sentence.
\pause
LL(1)
\end{frame}
\begin{frame}[fragile]{LL(1)}
\begin{equation*}
s'(S, w, p) := r'(R, w, p), \quad {\rm where~} R = c(S, w[p]).
\end{equation*}
\begin{verbatim}
S -> S_0 ... S_{n-1}
..
S' -> ... S S{k+1} ... S_{m-1}
\end{verbatim}
\end{frame}
\begin{frame}[fragile]{LL(1)}
\begin{verbatim}
S -> S_0 ... S_{n-1}
..
S' -> ... S S{k+1} ... S_{m-1}
\end{verbatim}
%% \begin{equation*}
%% w[p] \in {\rm FIRST}(S_0 ... S_{n-1}) \vee ({\rm NULLABLE}(S_0 ... S_{n-1}) \wedge w[p] \in {\rm FOLLOW}(S'))
%% \end{equation*}
\begin{equation*}
w[p] \in {\rm FIRST}(S_0 ... S_{n-1})
\end{equation*}
\begin{equation*}
{\rm NULLABLE}(S_0 ... S_{n-1}) \wedge w[p] \in {\rm FOLLOW}(S')
\end{equation*}
\end{frame}
\begin{frame}[fragile]{``Nullable''}
\begin{eqnarray*}
{\rm NULLABLE}(\_) \\
{\rm NULLABLE}(S_0 ... S_{n-1}) \Leftrightarrow \forall i {\rm NULLABLE}(S_i) \\
{\rm NULLABLE}(R) \Leftrightarrow {\rm NULLABLE}({\rm rhs}(R)) \\
{\rm NULLABLE}(S) \Leftrightarrow \exists R (R = S \rightarrow ...) \Rightarrow {\rm NULLABLE}(R)
\end{eqnarray*}
\end{frame}
\begin{frame}[fragile]{``First''}
\begin{eqnarray*}
{\rm FIRST}(\_) = \{\} \\
{\rm FIRST}(S_0 ... S_{n-1}) \Leftrightarrow ... \\
{\rm FIRST}(S) \Leftrightarrow \bigcup {\rm FIRST}({\rm rhs}(R)) \\
\end{eqnarray*}
\end{frame}
\begin{frame}[fragile]{``Follow''}
\begin{eqnarray*}
{\rm FOLLOW}(S) = \bigcup_R ({\rm FIRST}(S_{k+1} ... S_{m-1}) \cup {\rm FOLLOW}({\rm lhs}(R))
\end{eqnarray*}
\end{frame}
\begin{frame}[fragile]{``Predict''}
\begin{eqnarray*}
{\rm PREDICT}(R) & = & {\rm FIRST}(R) \cup {\rm FOLLOW}({\rm lhs}(R)), \quad {\rm when~} {\rm NULLABLE}(R) \\
{\rm PREDICT}(R) & = & {\rm FIRST}(R), \quad {\rm otherwise}
\end{eqnarray*}
\end{frame}
\begin{frame}[fragile]{LL(1)}
At input string termination we choose ${\rm NULLABLE}$ rules.
\end{frame}
\end{document}