532
|
1 |
% Chapter Template
|
|
2 |
|
|
3 |
\chapter{Regular Expressions and POSIX Lexing} % Main chapter title
|
|
4 |
|
|
5 |
\label{Inj} % In chapter 2 \ref{Chapter2} we will introduce the concepts
|
|
6 |
%and notations we
|
564
|
7 |
% used for describing the lexing algorithm by Sulzmann and Lu,
|
|
8 |
%and then give the algorithm and its variant and discuss
|
532
|
9 |
%why more aggressive simplifications are needed.
|
|
10 |
|
538
|
11 |
In this chapter, we define the basic notions
|
|
12 |
for regular languages and regular expressions.
|
583
|
13 |
This is essentially a description in ``English''
|
637
|
14 |
the functions and datatypes of our formalisation in Isabelle/HOL.
|
|
15 |
We also define what $\POSIX$ lexing means,
|
638
|
16 |
followed by the first lexing algorithm by Sulzmanna and Lu \parencite{Sulzmann2014}
|
564
|
17 |
that produces the output conforming
|
622
|
18 |
to the $\POSIX$ standard\footnote{In what follows
|
583
|
19 |
we choose to use the Isabelle-style notation
|
564
|
20 |
for function applications, where
|
583
|
21 |
the parameters of a function are not enclosed
|
564
|
22 |
inside a pair of parentheses (e.g. $f \;x \;y$
|
|
23 |
instead of $f(x,\;y)$). This is mainly
|
622
|
24 |
to make the text visually more concise.}.
|
532
|
25 |
|
538
|
26 |
\section{Basic Concepts}
|
622
|
27 |
Formal language theory usually starts with an alphabet
|
538
|
28 |
denoting a set of characters.
|
637
|
29 |
Here we use the datatype of characters from Isabelle,
|
541
|
30 |
which roughly corresponds to the ASCII characters.
|
564
|
31 |
In what follows, we shall leave the information about the alphabet
|
541
|
32 |
implicit.
|
|
33 |
Then using the usual bracket notation for lists,
|
622
|
34 |
we can define strings made up of characters as:
|
532
|
35 |
\begin{center}
|
|
36 |
\begin{tabular}{lcl}
|
541
|
37 |
$\textit{s}$ & $\dn$ & $[] \; |\; c :: s$
|
532
|
38 |
\end{tabular}
|
|
39 |
\end{center}
|
583
|
40 |
where $c$ is a variable ranging over characters.
|
622
|
41 |
The $::$ stands for list cons and $[]$ for the empty
|
|
42 |
list.
|
637
|
43 |
For brevity, a singleton list is sometimes written as $[c]$.
|
541
|
44 |
Strings can be concatenated to form longer strings in the same
|
637
|
45 |
way we concatenate two lists, which we shall write as $s_1 @ s_2$.
|
541
|
46 |
We omit the precise
|
538
|
47 |
recursive definition here.
|
|
48 |
We overload this concatenation operator for two sets of strings:
|
532
|
49 |
\begin{center}
|
|
50 |
\begin{tabular}{lcl}
|
541
|
51 |
$A @ B $ & $\dn$ & $\{s_A @ s_B \mid s_A \in A \land s_B \in B \}$\\
|
532
|
52 |
\end{tabular}
|
|
53 |
\end{center}
|
538
|
54 |
We also call the above \emph{language concatenation}.
|
532
|
55 |
The power of a language is defined recursively, using the
|
|
56 |
concatenation operator $@$:
|
|
57 |
\begin{center}
|
|
58 |
\begin{tabular}{lcl}
|
|
59 |
$A^0 $ & $\dn$ & $\{ [] \}$\\
|
541
|
60 |
$A^{n+1}$ & $\dn$ & $A @ A^n$
|
532
|
61 |
\end{tabular}
|
|
62 |
\end{center}
|
564
|
63 |
The union of all powers of a language
|
|
64 |
can be used to define the Kleene star operator:
|
532
|
65 |
\begin{center}
|
|
66 |
\begin{tabular}{lcl}
|
536
|
67 |
$A*$ & $\dn$ & $\bigcup_{i \geq 0} A^i$ \\
|
532
|
68 |
\end{tabular}
|
|
69 |
\end{center}
|
|
70 |
|
538
|
71 |
\noindent
|
564
|
72 |
However, to obtain a more convenient induction principle
|
538
|
73 |
in Isabelle/HOL,
|
536
|
74 |
we instead define the Kleene star
|
532
|
75 |
as an inductive set:
|
538
|
76 |
|
532
|
77 |
\begin{center}
|
538
|
78 |
\begin{mathpar}
|
564
|
79 |
\inferrule{\mbox{}}{[] \in A*\\}
|
538
|
80 |
|
564
|
81 |
\inferrule{s_1 \in A \;\; s_2 \in A*}{s_1 @ s_2 \in A*}
|
538
|
82 |
\end{mathpar}
|
532
|
83 |
\end{center}
|
564
|
84 |
\noindent
|
541
|
85 |
We also define an operation of "chopping off" a character from
|
|
86 |
a language, which we call $\Der$, meaning \emph{Derivative} (for a language):
|
532
|
87 |
\begin{center}
|
|
88 |
\begin{tabular}{lcl}
|
|
89 |
$\textit{Der} \;c \;A$ & $\dn$ & $\{ s \mid c :: s \in A \}$\\
|
|
90 |
\end{tabular}
|
|
91 |
\end{center}
|
538
|
92 |
\noindent
|
583
|
93 |
This can be generalised to ``chopping off'' a string
|
|
94 |
from all strings within a set $A$,
|
541
|
95 |
namely:
|
532
|
96 |
\begin{center}
|
|
97 |
\begin{tabular}{lcl}
|
541
|
98 |
$\textit{Ders} \;s \;A$ & $\dn$ & $\{ s' \mid s@s' \in A \}$\\
|
532
|
99 |
\end{tabular}
|
|
100 |
\end{center}
|
538
|
101 |
\noindent
|
541
|
102 |
which is essentially the left quotient $A \backslash L$ of $A$ against
|
622
|
103 |
the singleton language with $L = \{s\}$.
|
|
104 |
However, for our purposes here, the $\textit{Ders}$ definition with
|
541
|
105 |
a single string is sufficient.
|
532
|
106 |
|
577
|
107 |
The reason for defining derivatives
|
622
|
108 |
is that they provide another approach
|
577
|
109 |
to test membership of a string in
|
|
110 |
a set of strings.
|
|
111 |
For example, to test whether the string
|
638
|
112 |
$bar$ is contained in the set $\{foo, bar, brak\}$, one can take derivative of the set with
|
577
|
113 |
respect to the string $bar$:
|
|
114 |
\begin{center}
|
622
|
115 |
\begin{tabular}{lll}
|
577
|
116 |
$S = \{foo, bar, brak\}$ & $ \stackrel{\backslash b}{\rightarrow }$ &
|
622
|
117 |
$\{ar, rak\}$ \\
|
|
118 |
& $\stackrel{\backslash a}{\rightarrow}$ & $\{r \}$\\
|
|
119 |
& $\stackrel{\backslash r}{\rightarrow}$ & $\{[]\}$\\
|
|
120 |
%& $\stackrel{[] \in S \backslash bar}{\longrightarrow}$ & $bar \in S$\\
|
577
|
121 |
\end{tabular}
|
|
122 |
\end{center}
|
|
123 |
\noindent
|
637
|
124 |
and in the end, test whether the set
|
638
|
125 |
contains the empty string.\footnote{We use the infix notation $A\backslash c$
|
|
126 |
instead of $\Der \; c \; A$ for brevity, as it will always be
|
|
127 |
clear from the context that we are operating
|
622
|
128 |
on languages rather than regular expressions.}
|
|
129 |
|
|
130 |
In general, if we have a language $S$,
|
|
131 |
then we can test whether $s$ is in $S$
|
577
|
132 |
by testing whether $[] \in S \backslash s$.
|
564
|
133 |
With the sequencing, Kleene star, and $\textit{Der}$ operator on languages,
|
532
|
134 |
we have a few properties of how the language derivative can be defined using
|
|
135 |
sub-languages.
|
577
|
136 |
For example, for the sequence operator, we have
|
622
|
137 |
something similar to a ``chain rule'':
|
532
|
138 |
\begin{lemma}
|
536
|
139 |
\[
|
|
140 |
\Der \; c \; (A @ B) =
|
|
141 |
\begin{cases}
|
538
|
142 |
((\Der \; c \; A) \, @ \, B ) \cup (\Der \; c\; B) , & \text{if} \; [] \in A \\
|
|
143 |
(\Der \; c \; A) \, @ \, B, & \text{otherwise}
|
536
|
144 |
\end{cases}
|
|
145 |
\]
|
532
|
146 |
\end{lemma}
|
|
147 |
\noindent
|
|
148 |
This lemma states that if $A$ contains the empty string, $\Der$ can "pierce" through it
|
|
149 |
and get to $B$.
|
583
|
150 |
The language derivative for $A*$ can be described using the language derivative
|
532
|
151 |
of $A$:
|
|
152 |
\begin{lemma}
|
538
|
153 |
$\textit{Der} \;c \;(A*) = (\textit{Der}\; c A) @ (A*)$\\
|
532
|
154 |
\end{lemma}
|
|
155 |
\begin{proof}
|
583
|
156 |
There are two inclusions to prove:
|
532
|
157 |
\begin{itemize}
|
564
|
158 |
\item{$\subseteq$}:\\
|
532
|
159 |
The set
|
637
|
160 |
\[ S_1 = \{s \mid c :: s \in A*\} \]
|
532
|
161 |
is enclosed in the set
|
637
|
162 |
\[ S_2 = \{s_1 @ s_2 \mid s_1 \, s_2.\; s_1 \in \{s \mid c :: s \in A\} \land s_2 \in A* \}. \]
|
|
163 |
This is because for any string $c::s$ satisfying $c::s \in A*$,
|
|
164 |
%whenever you have a string starting with a character
|
|
165 |
%in the language of a Kleene star $A*$,
|
|
166 |
%then that
|
|
167 |
the character $c$, together with a prefix of $s$
|
|
168 |
%immediately after $c$
|
|
169 |
forms the first iteration of $A*$,
|
|
170 |
and the rest of the $s$ is also $A*$.
|
|
171 |
This coincides with the definition of $S_2$.
|
564
|
172 |
\item{$\supseteq$}:\\
|
532
|
173 |
Note that
|
538
|
174 |
\[ \Der \; c \; (A*) = \Der \; c \; (\{ [] \} \cup (A @ A*) ) \]
|
583
|
175 |
holds.
|
|
176 |
Also the following holds:
|
536
|
177 |
\[ \Der \; c \; (\{ [] \} \cup (A @ A*) ) = \Der\; c \; (A @ A*) \]
|
564
|
178 |
where the $\textit{RHS}$ can be rewritten
|
|
179 |
as \[ (\Der \; c\; A) @ A* \cup (\Der \; c \; (A*)) \]
|
|
180 |
which of course contains $\Der \; c \; A @ A*$.
|
532
|
181 |
\end{itemize}
|
|
182 |
\end{proof}
|
538
|
183 |
|
|
184 |
\noindent
|
622
|
185 |
The clever idea of Brzozowski was to find counterparts of $\Der$ and $\Ders$
|
|
186 |
for regular expressions.
|
|
187 |
To introduce them, we need to first give definitions for regular expressions,
|
|
188 |
which we shall do next.
|
532
|
189 |
|
536
|
190 |
\subsection{Regular Expressions and Their Meaning}
|
564
|
191 |
The \emph{basic regular expressions} are defined inductively
|
532
|
192 |
by the following grammar:
|
|
193 |
\[ r ::= \ZERO \mid \ONE
|
|
194 |
\mid c
|
|
195 |
\mid r_1 \cdot r_2
|
|
196 |
\mid r_1 + r_2
|
|
197 |
\mid r^*
|
|
198 |
\]
|
538
|
199 |
\noindent
|
564
|
200 |
We call them basic because we will introduce
|
637
|
201 |
additional constructors in later chapters, such as negation
|
538
|
202 |
and bounded repetitions.
|
564
|
203 |
We use $\ZERO$ for the regular expression that
|
|
204 |
matches no string, and $\ONE$ for the regular
|
622
|
205 |
expression that matches only the empty string.\footnote{
|
|
206 |
Some authors
|
564
|
207 |
also use $\phi$ and $\epsilon$ for $\ZERO$ and $\ONE$
|
638
|
208 |
but we prefer this notation.}
|
564
|
209 |
The sequence regular expression is written $r_1\cdot r_2$
|
|
210 |
and sometimes we omit the dot if it is clear which
|
|
211 |
regular expression is meant; the alternative
|
|
212 |
is written $r_1 + r_2$.
|
|
213 |
The \emph{language} or meaning of
|
|
214 |
a regular expression is defined recursively as
|
|
215 |
a set of strings:
|
532
|
216 |
%TODO: FILL in the other defs
|
|
217 |
\begin{center}
|
|
218 |
\begin{tabular}{lcl}
|
564
|
219 |
$L \; \ZERO$ & $\dn$ & $\phi$\\
|
|
220 |
$L \; \ONE$ & $\dn$ & $\{[]\}$\\
|
|
221 |
$L \; c$ & $\dn$ & $\{[c]\}$\\
|
622
|
222 |
$L \; (r_1 + r_2)$ & $\dn$ & $ L \; r_1 \cup L \; r_2$\\
|
|
223 |
$L \; (r_1 \cdot r_2)$ & $\dn$ & $ L \; r_1 @ L \; r_2$\\
|
|
224 |
$L \; (r^*)$ & $\dn$ & $ (L\;r)*$
|
532
|
225 |
\end{tabular}
|
|
226 |
\end{center}
|
536
|
227 |
\noindent
|
622
|
228 |
%Now with language derivatives of a language and regular expressions and
|
|
229 |
%their language interpretations in place, we are ready to define derivatives on regular expressions.
|
637
|
230 |
With $L$, we are ready to introduce Brzozowski derivatives on regular expressions.
|
638
|
231 |
We do so by first introducing what properties they should satisfy.
|
622
|
232 |
|
532
|
233 |
\subsection{Brzozowski Derivatives and a Regular Expression Matcher}
|
564
|
234 |
%Recall, the language derivative acts on a set of strings
|
|
235 |
%and essentially chops off a particular character from
|
|
236 |
%all strings in that set, Brzozowski defined a derivative operation on regular expressions
|
|
237 |
%so that after derivative $L(r\backslash c)$
|
|
238 |
%will look as if it was obtained by doing a language derivative on $L(r)$:
|
622
|
239 |
%Recall that the language derivative acts on a
|
|
240 |
%language (set of strings).
|
|
241 |
%One can decide whether a string $s$ belongs
|
|
242 |
%to a language $S$ by taking derivative with respect to
|
|
243 |
%that string and then checking whether the empty
|
|
244 |
%string is in the derivative:
|
|
245 |
%\begin{center}
|
|
246 |
%\parskip \baselineskip
|
|
247 |
%\def\myupbracefill#1{\rotatebox{90}{\stretchto{\{}{#1}}}
|
|
248 |
%\def\rlwd{.5pt}
|
|
249 |
%\newcommand\notate[3]{%
|
|
250 |
% \unskip\def\useanchorwidth{T}%
|
|
251 |
% \setbox0=\hbox{#1}%
|
|
252 |
% \def\stackalignment{c}\stackunder[-6pt]{%
|
|
253 |
% \def\stackalignment{c}\stackunder[-1.5pt]{%
|
|
254 |
% \stackunder[-2pt]{\strut #1}{\myupbracefill{\wd0}}}{%
|
|
255 |
% \rule{\rlwd}{#2\baselineskip}}}{%
|
|
256 |
% \strut\kern7pt$\hookrightarrow$\rlap{ \footnotesize#3}}\ignorespaces%
|
|
257 |
%}
|
|
258 |
%\Longstack{
|
|
259 |
%\notate{$\{ \ldots ,\;$
|
|
260 |
% \notate{s}{1}{$(c_1 :: s_1)$}
|
|
261 |
% $, \; \ldots \}$
|
|
262 |
%}{1}{$S_{start}$}
|
|
263 |
%}
|
|
264 |
%\Longstack{
|
|
265 |
% $\stackrel{\backslash c_1}{\longrightarrow}$
|
|
266 |
%}
|
|
267 |
%\Longstack{
|
|
268 |
% $\{ \ldots,\;$ \notate{$s_1$}{1}{$(c_2::s_2)$}
|
|
269 |
% $,\; \ldots \}$
|
|
270 |
%}
|
|
271 |
%\Longstack{
|
|
272 |
% $\stackrel{\backslash c_2}{\longrightarrow}$
|
|
273 |
%}
|
|
274 |
%\Longstack{
|
|
275 |
% $\{ \ldots,\; s_2
|
|
276 |
% ,\; \ldots \}$
|
|
277 |
%}
|
|
278 |
%\Longstack{
|
|
279 |
% $ \xdashrightarrow{\backslash c_3\ldots\ldots} $
|
|
280 |
%}
|
|
281 |
%\Longstack{
|
|
282 |
% \notate{$\{\ldots, [], \ldots\}$}{1}{$S_{end} =
|
|
283 |
% S_{start}\backslash s$}
|
|
284 |
%}
|
|
285 |
%\end{center}
|
|
286 |
%\begin{center}
|
|
287 |
% $s \in S_{start} \iff [] \in S_{end}$
|
|
288 |
%\end{center}
|
|
289 |
%\noindent
|
|
290 |
Brzozowski noticed that $\Der$
|
579
|
291 |
can be ``mirrored'' on regular expressions which
|
564
|
292 |
he calls the derivative of a regular expression $r$
|
|
293 |
with respect to a character $c$, written
|
577
|
294 |
$r \backslash c$. This infix operator
|
638
|
295 |
takes regular expression $r$ as input
|
|
296 |
and a character as a right operand.
|
577
|
297 |
The derivative operation on regular expression
|
|
298 |
is defined such that the language of the derivative result
|
|
299 |
coincides with the language of the original
|
579
|
300 |
regular expression being taken
|
638
|
301 |
derivative with respect to the same characters, namely
|
579
|
302 |
\begin{property}
|
|
303 |
|
|
304 |
\[
|
|
305 |
L \; (r \backslash c) = \Der \; c \; (L \; r)
|
|
306 |
\]
|
|
307 |
\end{property}
|
|
308 |
\noindent
|
622
|
309 |
Pictorially, this looks as follows:\\
|
|
310 |
\vspace{3mm}
|
579
|
311 |
|
577
|
312 |
\parskip \baselineskip
|
|
313 |
\def\myupbracefill#1{\rotatebox{90}{\stretchto{\{}{#1}}}
|
|
314 |
\def\rlwd{.5pt}
|
|
315 |
\newcommand\notate[3]{%
|
|
316 |
\unskip\def\useanchorwidth{T}%
|
|
317 |
\setbox0=\hbox{#1}%
|
|
318 |
\def\stackalignment{c}\stackunder[-6pt]{%
|
|
319 |
\def\stackalignment{c}\stackunder[-1.5pt]{%
|
|
320 |
\stackunder[-2pt]{\strut #1}{\myupbracefill{\wd0}}}{%
|
|
321 |
\rule{\rlwd}{#2\baselineskip}}}{%
|
|
322 |
\strut\kern8pt$\hookrightarrow$\rlap{ \footnotesize#3}}\ignorespaces%
|
|
323 |
}
|
|
324 |
\Longstack{
|
|
325 |
\notate{$r$}{1}{$L \; r = \{\ldots, \;c::s_1,
|
|
326 |
\;\ldots\}$}
|
|
327 |
}
|
|
328 |
\Longstack{
|
579
|
329 |
$\stackrel{\backslash c}{\xrightarrow{\hspace*{8cm}}}$
|
577
|
330 |
}
|
|
331 |
\Longstack{
|
579
|
332 |
\notate{$r\backslash c$}{1}{$L \; (r\backslash c)=
|
577
|
333 |
\{\ldots,\;s_1,\;\ldots\}$}
|
622
|
334 |
}\\
|
|
335 |
\vspace{ 3mm }
|
|
336 |
|
579
|
337 |
The derivatives on regular expression can again be
|
638
|
338 |
generalised to strings.
|
622
|
339 |
One could compute $r_{start} \backslash s$ and test membership of $s$
|
|
340 |
in $L \; r_{start}$ by checking
|
579
|
341 |
whether the empty string is in the language of
|
638
|
342 |
$r_{end}$ (that is $r_{start}\backslash s$).\\
|
579
|
343 |
|
622
|
344 |
\vspace{2mm}
|
579
|
345 |
\Longstack{
|
|
346 |
\notate{$r_{start}$}{4}{
|
|
347 |
\Longstack{$L \; r_{start} = \{\ldots, \;$
|
|
348 |
\notate{$s$}{1}{$c_1::s_1$}
|
|
349 |
$, \ldots\} $
|
|
350 |
}
|
|
351 |
}
|
|
352 |
}
|
|
353 |
\Longstack{
|
|
354 |
$\stackrel{\backslash c_1}{ \xrightarrow{\hspace*{1.8cm}} }$
|
|
355 |
}
|
|
356 |
\Longstack{
|
|
357 |
\notate{$r_1$}{3}{
|
|
358 |
$r_1 = r_{start}\backslash c_1$,
|
|
359 |
$L \; r_1 = $
|
|
360 |
\Longstack{
|
|
361 |
$\{ \ldots,\;$ \notate{$s_1$}{1}{$c_2::s_2$}
|
|
362 |
$,\; \ldots \}$
|
|
363 |
}
|
|
364 |
}
|
|
365 |
}
|
|
366 |
\Longstack{
|
|
367 |
$\stackrel{\backslash c_2}{\xrightarrow{\hspace*{1.8cm}}}$
|
|
368 |
}
|
|
369 |
\Longstack{
|
|
370 |
$r_2$
|
|
371 |
}
|
|
372 |
\Longstack{
|
|
373 |
$ \xdashrightarrow{\hspace*{0.3cm} \backslash c_3 \ldots \ldots \ldots \hspace*{0.3cm}} $
|
|
374 |
}
|
|
375 |
\Longstack{
|
|
376 |
\notate{$r_{end}$}{1}{
|
|
377 |
$L \; r_{end} = \{\ldots, \; [], \ldots\}$}
|
|
378 |
}
|
|
379 |
|
|
380 |
|
638
|
381 |
We have the property that
|
579
|
382 |
\begin{property}
|
|
383 |
$s \in L \; r_{start} \iff [] \in L \; r_{end}$
|
|
384 |
\end{property}
|
|
385 |
\noindent
|
637
|
386 |
Next, we give the recursive definition of derivative on
|
|
387 |
regular expressions so that it satisfies the properties above.
|
638
|
388 |
%The derivative function, written $r\backslash c$,
|
|
389 |
%takes a regular expression $r$ and character $c$, and
|
|
390 |
%returns a new regular expression representing
|
|
391 |
%the original regular expression's language $L \; r$
|
|
392 |
%being taken the language derivative with respect to $c$.
|
626
|
393 |
\begin{table}
|
|
394 |
\begin{center}
|
579
|
395 |
\begin{tabular}{lcl}
|
|
396 |
$\ZERO \backslash c$ & $\dn$ & $\ZERO$\\
|
|
397 |
$\ONE \backslash c$ & $\dn$ & $\ZERO$\\
|
|
398 |
$d \backslash c$ & $\dn$ &
|
|
399 |
$\mathit{if} \;c = d\;\mathit{then}\;\ONE\;\mathit{else}\;\ZERO$\\
|
|
400 |
$(r_1 + r_2)\backslash c$ & $\dn$ & $r_1 \backslash c \,+\, r_2 \backslash c$\\
|
|
401 |
$(r_1 \cdot r_2)\backslash c$ & $\dn$ & $\mathit{if} \, [] \in L(r_1)$\\
|
|
402 |
& & $\mathit{then}\;(r_1\backslash c) \cdot r_2 \,+\, r_2\backslash c$\\
|
|
403 |
& & $\mathit{else}\;(r_1\backslash c) \cdot r_2$\\
|
|
404 |
$(r^*)\backslash c$ & $\dn$ & $(r\backslash c) \cdot r^*$\\
|
|
405 |
\end{tabular}
|
626
|
406 |
\end{center}
|
|
407 |
\caption{Derivative on Regular Expressions}
|
|
408 |
\label{table:der}
|
|
409 |
\end{table}
|
564
|
410 |
\noindent
|
579
|
411 |
The most involved cases are the sequence case
|
|
412 |
and the star case.
|
|
413 |
The sequence case says that if the first regular expression
|
|
414 |
contains an empty string, then the second component of the sequence
|
|
415 |
needs to be considered, as its derivative will contribute to the
|
|
416 |
result of this derivative:
|
|
417 |
\begin{center}
|
|
418 |
\begin{tabular}{lcl}
|
583
|
419 |
$(r_1 \cdot r_2 ) \backslash c$ & $\dn$ &
|
|
420 |
$\textit{if}\;\,([] \in L(r_1))\;
|
638
|
421 |
\textit{then} \; (r_1 \backslash c) \cdot r_2 + r_2 \backslash c$ \\
|
579
|
422 |
& & $\textit{else} \; (r_1 \backslash c) \cdot r_2$
|
|
423 |
\end{tabular}
|
|
424 |
\end{center}
|
|
425 |
\noindent
|
|
426 |
Notice how this closely resembles
|
|
427 |
the language derivative operation $\Der$:
|
564
|
428 |
\begin{center}
|
|
429 |
\begin{tabular}{lcl}
|
|
430 |
$\Der \; c \; (A @ B)$ & $\dn$ &
|
|
431 |
$ \textit{if} \;\, [] \in A \;
|
|
432 |
\textit{then} \;\, ((\Der \; c \; A) @ B ) \cup
|
|
433 |
\Der \; c\; B$\\
|
|
434 |
& & $\textit{else}\; (\Der \; c \; A) @ B$\\
|
|
435 |
\end{tabular}
|
|
436 |
\end{center}
|
|
437 |
\noindent
|
583
|
438 |
The derivative of the star regular expression $r^*$
|
579
|
439 |
unwraps one iteration of $r$, turns it into $r\backslash c$,
|
|
440 |
and attaches the original $r^*$
|
|
441 |
after $r\backslash c$, so that
|
|
442 |
we can further unfold it as many times as needed:
|
|
443 |
\[
|
|
444 |
(r^*) \backslash c \dn (r \backslash c)\cdot r^*.
|
|
445 |
\]
|
|
446 |
Again,
|
637
|
447 |
the structure is the same as the language derivative of the Kleene star:
|
532
|
448 |
\[
|
564
|
449 |
\textit{Der} \;c \;(A*) \dn (\textit{Der}\; c A) @ (A*)
|
532
|
450 |
\]
|
564
|
451 |
In the above definition of $(r_1\cdot r_2) \backslash c$,
|
|
452 |
the $\textit{if}$ clause's
|
|
453 |
boolean condition
|
|
454 |
$[] \in L(r_1)$ needs to be
|
|
455 |
somehow recursively computed.
|
|
456 |
We call such a function that checks
|
|
457 |
whether the empty string $[]$ is
|
|
458 |
in the language of a regular expression $\nullable$:
|
|
459 |
\begin{center}
|
|
460 |
\begin{tabular}{lcl}
|
|
461 |
$\nullable(\ZERO)$ & $\dn$ & $\mathit{false}$ \\
|
|
462 |
$\nullable(\ONE)$ & $\dn$ & $\mathit{true}$ \\
|
|
463 |
$\nullable(c)$ & $\dn$ & $\mathit{false}$ \\
|
|
464 |
$\nullable(r_1 + r_2)$ & $\dn$ & $\nullable(r_1) \vee \nullable(r_2)$ \\
|
|
465 |
$\nullable(r_1\cdot r_2)$ & $\dn$ & $\nullable(r_1) \wedge \nullable(r_2)$ \\
|
|
466 |
$\nullable(r^*)$ & $\dn$ & $\mathit{true}$ \\
|
|
467 |
\end{tabular}
|
|
468 |
\end{center}
|
|
469 |
\noindent
|
|
470 |
The $\ZERO$ regular expression
|
|
471 |
does not contain any string and
|
|
472 |
therefore is not \emph{nullable}.
|
|
473 |
$\ONE$ is \emph{nullable}
|
|
474 |
by definition.
|
|
475 |
The character regular expression $c$
|
|
476 |
corresponds to the singleton set $\{c\}$,
|
|
477 |
and therefore does not contain the empty string.
|
|
478 |
The alternative regular expression is nullable
|
|
479 |
if at least one of its children is nullable.
|
|
480 |
The sequence regular expression
|
|
481 |
would require both children to have the empty string
|
|
482 |
to compose an empty string, and the Kleene star
|
|
483 |
is always nullable because it naturally
|
579
|
484 |
contains the empty string.
|
532
|
485 |
\noindent
|
638
|
486 |
We have the following two correspondences between
|
564
|
487 |
derivatives on regular expressions and
|
|
488 |
derivatives on a set of strings:
|
|
489 |
\begin{lemma}\label{derDer}
|
608
|
490 |
\mbox{}
|
579
|
491 |
\begin{itemize}
|
|
492 |
\item
|
532
|
493 |
$\textit{Der} \; c \; L(r) = L (r\backslash c)$
|
579
|
494 |
\item
|
|
495 |
$c\!::\!s \in L(r)$ \textit{iff} $s \in L(r\backslash c)$.
|
|
496 |
\end{itemize}
|
532
|
497 |
\end{lemma}
|
579
|
498 |
\begin{proof}
|
|
499 |
By induction on $r$.
|
|
500 |
\end{proof}
|
532
|
501 |
\noindent
|
638
|
502 |
which are the main properties of derivatives
|
|
503 |
that enables us later to reason about the correctness of
|
622
|
504 |
derivative-based matching.
|
532
|
505 |
We can generalise the derivative operation shown above for single characters
|
|
506 |
to strings as follows:
|
|
507 |
|
|
508 |
\begin{center}
|
|
509 |
\begin{tabular}{lcl}
|
|
510 |
$r \backslash_s (c\!::\!s) $ & $\dn$ & $(r \backslash c) \backslash_s s$ \\
|
583
|
511 |
$r \backslash_s [\,] $ & $\dn$ & $r$
|
532
|
512 |
\end{tabular}
|
|
513 |
\end{center}
|
|
514 |
|
|
515 |
\noindent
|
564
|
516 |
When there is no ambiguity, we will
|
|
517 |
omit the subscript and use $\backslash$ instead
|
583
|
518 |
of $\backslash_s$ to denote
|
532
|
519 |
string derivatives for brevity.
|
622
|
520 |
Brzozowski's derivative-based
|
|
521 |
regular-expression matching algorithm can then be described as:
|
532
|
522 |
|
|
523 |
\begin{definition}
|
564
|
524 |
$\textit{match}\;s\;r \;\dn\; \nullable \; (r\backslash s)$
|
532
|
525 |
\end{definition}
|
|
526 |
|
|
527 |
\noindent
|
637
|
528 |
Assuming the string is given as a sequence of characters, say $c_0c_1 \ldots c_n$,
|
|
529 |
this algorithm, presented graphically, is as follows:
|
532
|
530 |
|
601
|
531 |
\begin{equation}\label{matcher}
|
532
|
532 |
\begin{tikzcd}
|
583
|
533 |
r_0 \arrow[r, "\backslash c_0"] & r_1 \arrow[r, "\backslash c_1"] &
|
|
534 |
r_2 \arrow[r, dashed] & r_n \arrow[r,"\textit{nullable}?"] &
|
|
535 |
\;\textrm{true}/\textrm{false}
|
532
|
536 |
\end{tikzcd}
|
|
537 |
\end{equation}
|
|
538 |
|
|
539 |
\noindent
|
622
|
540 |
It is relatively
|
|
541 |
easy to show that this matcher is correct, namely
|
539
|
542 |
\begin{lemma}
|
564
|
543 |
$\textit{match} \; s\; r = \textit{true} \; \textit{iff} \; s \in L(r)$
|
539
|
544 |
\end{lemma}
|
|
545 |
\begin{proof}
|
637
|
546 |
By induction on $s$ using the property of derivatives:
|
583
|
547 |
lemma \ref{derDer}.
|
539
|
548 |
\end{proof}
|
601
|
549 |
\begin{figure}
|
564
|
550 |
\begin{center}
|
539
|
551 |
\begin{tikzpicture}
|
|
552 |
\begin{axis}[
|
|
553 |
xlabel={$n$},
|
|
554 |
ylabel={time in secs},
|
601
|
555 |
%ymode = log,
|
539
|
556 |
legend entries={Naive Matcher},
|
|
557 |
legend pos=north west,
|
|
558 |
legend cell align=left]
|
|
559 |
\addplot[red,mark=*, mark options={fill=white}] table {NaiveMatcher.data};
|
|
560 |
\end{axis}
|
|
561 |
\end{tikzpicture}
|
583
|
562 |
\caption{Matching the regular expression $(a^*)^*b$ against strings of the form
|
|
563 |
$\protect\underbrace{aa\ldots a}_\text{n \textit{a}s}
|
|
564 |
$ using Brzozowski's original algorithm}\label{NaiveMatcher}
|
601
|
565 |
\end{center}
|
539
|
566 |
\end{figure}
|
|
567 |
\noindent
|
564
|
568 |
If we implement the above algorithm naively, however,
|
|
569 |
the algorithm can be excruciatingly slow, as shown in
|
|
570 |
\ref{NaiveMatcher}.
|
|
571 |
Note that both axes are in logarithmic scale.
|
637
|
572 |
Around two dozen characters
|
638
|
573 |
this algorithm already ``explodes'' with the regular expression
|
564
|
574 |
$(a^*)^*b$.
|
622
|
575 |
To improve this situation, we need to introduce simplification
|
|
576 |
rules for the intermediate results,
|
638
|
577 |
such as $r + r \rightarrow r$ or $\ONE \cdot r \rightarrow r$,
|
539
|
578 |
and make sure those rules do not change the
|
|
579 |
language of the regular expression.
|
638
|
580 |
One simple-minded simplification function
|
622
|
581 |
that achieves these requirements
|
|
582 |
is given below (see Ausaf et al. \cite{AusafDyckhoffUrban2016}):
|
564
|
583 |
\begin{center}
|
|
584 |
\begin{tabular}{lcl}
|
|
585 |
$\simp \; r_1 \cdot r_2 $ & $ \dn$ &
|
|
586 |
$(\simp \; r_1, \simp \; r_2) \; \textit{match}$\\
|
|
587 |
& & $\quad \case \; (\ZERO, \_) \Rightarrow \ZERO$\\
|
|
588 |
& & $\quad \case \; (\_, \ZERO) \Rightarrow \ZERO$\\
|
|
589 |
& & $\quad \case \; (\ONE, r_2') \Rightarrow r_2'$\\
|
|
590 |
& & $\quad \case \; (r_1', \ONE) \Rightarrow r_1'$\\
|
|
591 |
& & $\quad \case \; (r_1', r_2') \Rightarrow r_1'\cdot r_2'$\\
|
|
592 |
$\simp \; r_1 + r_2$ & $\dn$ & $(\simp \; r_1, \simp \; r_2) \textit{match}$\\
|
|
593 |
& & $\quad \; \case \; (\ZERO, r_2') \Rightarrow r_2'$\\
|
|
594 |
& & $\quad \; \case \; (r_1', \ZERO) \Rightarrow r_1'$\\
|
|
595 |
& & $\quad \; \case \; (r_1', r_2') \Rightarrow r_1' + r_2'$\\
|
583
|
596 |
$\simp \; r$ & $\dn$ & $r\quad\quad (otherwise)$
|
564
|
597 |
|
|
598 |
\end{tabular}
|
|
599 |
\end{center}
|
|
600 |
If we repeatedly apply this simplification
|
|
601 |
function during the matching algorithm,
|
|
602 |
we have a matcher with simplification:
|
|
603 |
\begin{center}
|
|
604 |
\begin{tabular}{lcl}
|
|
605 |
$\derssimp \; [] \; r$ & $\dn$ & $r$\\
|
|
606 |
$\derssimp \; c :: cs \; r$ & $\dn$ & $\derssimp \; cs \; (\simp \; (r \backslash c))$\\
|
|
607 |
$\textit{matcher}_{simp}\; s \; r $ & $\dn$ & $\nullable \; (\derssimp \; s\;r)$
|
|
608 |
\end{tabular}
|
|
609 |
\end{center}
|
|
610 |
\begin{figure}
|
539
|
611 |
\begin{tikzpicture}
|
|
612 |
\begin{axis}[
|
|
613 |
xlabel={$n$},
|
|
614 |
ylabel={time in secs},
|
601
|
615 |
%ymode = log,
|
|
616 |
%xmode = log,
|
564
|
617 |
grid = both,
|
539
|
618 |
legend entries={Matcher With Simp},
|
|
619 |
legend pos=north west,
|
|
620 |
legend cell align=left]
|
|
621 |
\addplot[red,mark=*, mark options={fill=white}] table {BetterMatcher.data};
|
|
622 |
\end{axis}
|
564
|
623 |
\end{tikzpicture}
|
|
624 |
\caption{$(a^*)^*b$
|
|
625 |
against
|
|
626 |
$\protect\underbrace{aa\ldots a}_\text{n \textit{a}s}$ Using $\textit{matcher}_{simp}$}\label{BetterMatcher}
|
|
627 |
\end{figure}
|
|
628 |
\noindent
|
|
629 |
The running time of $\textit{ders}\_\textit{simp}$
|
583
|
630 |
on the same example of Figure \ref{NaiveMatcher}
|
|
631 |
is now ``tame'' in terms of the length of inputs,
|
|
632 |
as shown in Figure \ref{BetterMatcher}.
|
539
|
633 |
|
637
|
634 |
So far, the story is use Brzozowski derivatives and
|
|
635 |
simplify as much as possible, and at the end test
|
622
|
636 |
whether the empty string is recognised
|
|
637 |
by the final derivative.
|
583
|
638 |
But what if we want to
|
|
639 |
do lexing instead of just getting a true/false answer?
|
622
|
640 |
Sulzmann and Lu \cite{Sulzmann2014} first came up with a nice and
|
|
641 |
elegant (arguably as beautiful as the definition of the
|
|
642 |
Brzozowski derivative) solution for this.
|
538
|
643 |
|
539
|
644 |
\section{Values and the Lexing Algorithm by Sulzmann and Lu}
|
564
|
645 |
In this section, we present a two-phase regular expression lexing
|
|
646 |
algorithm.
|
|
647 |
The first phase takes successive derivatives with
|
|
648 |
respect to the input string,
|
|
649 |
and the second phase does the reverse, \emph{injecting} back
|
|
650 |
characters, in the meantime constructing a lexing result.
|
|
651 |
We will introduce the injection phase in detail slightly
|
|
652 |
later, but as a preliminary we have to first define
|
|
653 |
the datatype for lexing results,
|
|
654 |
called \emph{value} or
|
608
|
655 |
sometimes also \emph{lexical value}.
|
|
656 |
Values and regular
|
|
657 |
expressions correspond to each other
|
|
658 |
as illustrated in the following
|
538
|
659 |
table:
|
|
660 |
|
|
661 |
\begin{center}
|
|
662 |
\begin{tabular}{c@{\hspace{20mm}}c}
|
|
663 |
\begin{tabular}{@{}rrl@{}}
|
|
664 |
\multicolumn{3}{@{}l}{\textbf{Regular Expressions}}\medskip\\
|
|
665 |
$r$ & $::=$ & $\ZERO$\\
|
|
666 |
& $\mid$ & $\ONE$ \\
|
|
667 |
& $\mid$ & $c$ \\
|
|
668 |
& $\mid$ & $r_1 \cdot r_2$\\
|
|
669 |
& $\mid$ & $r_1 + r_2$ \\
|
|
670 |
\\
|
|
671 |
& $\mid$ & $r^*$ \\
|
|
672 |
\end{tabular}
|
|
673 |
&
|
|
674 |
\begin{tabular}{@{\hspace{0mm}}rrl@{}}
|
|
675 |
\multicolumn{3}{@{}l}{\textbf{Values}}\medskip\\
|
|
676 |
$v$ & $::=$ & \\
|
|
677 |
& & $\Empty$ \\
|
591
|
678 |
& $\mid$ & $\Char \; c$ \\
|
538
|
679 |
& $\mid$ & $\Seq\,v_1\, v_2$\\
|
591
|
680 |
& $\mid$ & $\Left \;v$ \\
|
|
681 |
& $\mid$ & $\Right\;v$ \\
|
538
|
682 |
& $\mid$ & $\Stars\,[v_1,\ldots\,v_n]$ \\
|
|
683 |
\end{tabular}
|
|
684 |
\end{tabular}
|
|
685 |
\end{center}
|
|
686 |
\noindent
|
564
|
687 |
A value has an underlying string, which
|
|
688 |
can be calculated by the ``flatten" function $|\_|$:
|
|
689 |
\begin{center}
|
|
690 |
\begin{tabular}{lcl}
|
|
691 |
$|\Empty|$ & $\dn$ & $[]$\\
|
|
692 |
$|\Char \; c|$ & $ \dn$ & $ [c]$\\
|
591
|
693 |
$|\Seq \; v_1, \;v_2|$ & $ \dn$ & $ v_1| @ |v_2|$\\
|
|
694 |
$|\Left \; v|$ & $ \dn$ & $ |v|$\\
|
|
695 |
$|\Right \; v|$ & $ \dn$ & $ |v|$\\
|
|
696 |
$|\Stars \; []|$ & $\dn$ & $[]$\\
|
|
697 |
$|\Stars \; v::vs|$ & $\dn$ & $ |v| @ |\Stars(vs)|$
|
564
|
698 |
\end{tabular}
|
|
699 |
\end{center}
|
|
700 |
Sulzmann and Lu used a binary predicate, written $\vdash v:r $,
|
|
701 |
to indicate that a value $v$ could be generated from a lexing algorithm
|
622
|
702 |
with input $r$. They call it the value inhabitation relation,
|
|
703 |
defined by the rules.
|
628
|
704 |
\begin{figure}[H]
|
538
|
705 |
\begin{mathpar}
|
591
|
706 |
\inferrule{\mbox{}}{\vdash \Char \; c : \mathbf{c}} \hspace{2em}
|
564
|
707 |
|
|
708 |
\inferrule{\mbox{}}{\vdash \Empty : \ONE} \hspace{2em}
|
|
709 |
|
591
|
710 |
\inferrule{\vdash v_1 : r_1 \;\; \vdash v_2 : r_2 }{\vdash \Seq \; v_1,\; v_2 : (r_1 \cdot r_2)}
|
564
|
711 |
|
591
|
712 |
\inferrule{\vdash v_1 : r_1}{\vdash \Left \; v_1 : r_1+r_2}
|
564
|
713 |
|
591
|
714 |
\inferrule{\vdash v_2 : r_2}{\vdash \Right \; v_2:r_1 + r_2}
|
538
|
715 |
|
591
|
716 |
\inferrule{\forall v \in vs. \vdash v:r \land |v| \neq []}{\vdash \Stars \; vs : r^*}
|
564
|
717 |
\end{mathpar}
|
628
|
718 |
\caption{The inhabitation relation for values and regular expressions}\label{fig:inhab}
|
626
|
719 |
\end{figure}
|
564
|
720 |
\noindent
|
|
721 |
The condition $|v| \neq []$ in the premise of star's rule
|
|
722 |
is to make sure that for a given pair of regular
|
|
723 |
expression $r$ and string $s$, the number of values
|
|
724 |
satisfying $|v| = s$ and $\vdash v:r$ is finite.
|
601
|
725 |
This additional condition was
|
|
726 |
imposed by Ausaf and Urban to make their proofs easier.
|
622
|
727 |
Given a string and a regular expression, there can be
|
564
|
728 |
multiple values for it. For example, both
|
|
729 |
$\vdash \Seq(\Left \; ab)(\Right \; c):(ab+a)(bc+c)$ and
|
|
730 |
$\vdash \Seq(\Right\; a)(\Left \; bc ):(ab+a)(bc+c)$ hold
|
|
731 |
and the values both flatten to $abc$.
|
|
732 |
Lexers therefore have to disambiguate and choose only
|
637
|
733 |
one of the values to be generated. $\POSIX$ is one of the
|
564
|
734 |
disambiguation strategies that is widely adopted.
|
|
735 |
|
638
|
736 |
Ausaf et al. \cite{AusafDyckhoffUrban2016}
|
564
|
737 |
formalised the property
|
|
738 |
as a ternary relation.
|
|
739 |
The $\POSIX$ value $v$ for a regular expression
|
538
|
740 |
$r$ and string $s$, denoted as $(s, r) \rightarrow v$, can be specified
|
622
|
741 |
in the following rules\footnote{The names of the rules are used
|
|
742 |
as they were originally given in \cite{AusafDyckhoffUrban2016}.}:
|
|
743 |
\begin{figure}[p]
|
564
|
744 |
\begin{mathpar}
|
|
745 |
\inferrule[P1]{\mbox{}}{([], \ONE) \rightarrow \Empty}
|
|
746 |
|
|
747 |
\inferrule[PC]{\mbox{}}{([c], c) \rightarrow \Char \; c}
|
|
748 |
|
|
749 |
\inferrule[P+L]{(s,r_1)\rightarrow v_1}{(s, r_1+r_2)\rightarrow \Left \; v_1}
|
|
750 |
|
|
751 |
\inferrule[P+R]{(s,r_2)\rightarrow v_2\\ s \notin L \; r_1}{(s, r_1+r_2)\rightarrow \Right \; v_2}
|
|
752 |
|
|
753 |
\inferrule[PS]{(s_1, v_1) \rightarrow r_1 \\ (s_2, v_2)\rightarrow r_2\\
|
|
754 |
\nexists s_3 \; s_4. s_3 \neq [] \land s_3 @ s_4 = s_2 \land
|
|
755 |
s_1@ s_3 \in L \; r_1 \land s_4 \in L \; r_2}{(s_1 @ s_2, r_1\cdot r_2) \rightarrow
|
|
756 |
\Seq \; v_1 \; v_2}
|
|
757 |
|
|
758 |
\inferrule[P{[]}]{\mbox{}}{([], r^*) \rightarrow \Stars([])}
|
|
759 |
|
|
760 |
\inferrule[P*]{(s_1, v) \rightarrow v \\ (s_2, r^*) \rightarrow \Stars \; vs \\
|
|
761 |
|v| \neq []\\ \nexists s_3 \; s_4. s_3 \neq [] \land s_3@s_4 = s_2 \land
|
|
762 |
s_1@s_3 \in L \; r \land s_4 \in L \; r^*}{(s_1@s_2, r^*)\rightarrow \Stars \;
|
|
763 |
(v::vs)}
|
|
764 |
\end{mathpar}
|
622
|
765 |
\caption{The inductive POSIX rules given by Ausaf et al.
|
|
766 |
\cite{AusafDyckhoffUrban2016}.
|
|
767 |
This ternary relation, written $(s, r) \rightarrow v$,
|
|
768 |
formalises the POSIX constraints on the
|
601
|
769 |
value $v$ given a string $s$ and
|
|
770 |
regular expression $r$.
|
|
771 |
}
|
622
|
772 |
\end{figure}\afterpage{\clearpage}
|
538
|
773 |
\noindent
|
579
|
774 |
|
622
|
775 |
%\begin{figure}
|
|
776 |
%\begin{tikzpicture}[]
|
|
777 |
% \node [minimum width = 6cm, rectangle split, rectangle split horizontal,
|
|
778 |
% rectangle split parts=2, rectangle split part fill={red!30,blue!20}, style={draw, rounded corners, inner sep=10pt}]
|
|
779 |
% (node1)
|
|
780 |
% {$r_{token1}$
|
|
781 |
% \nodepart{two} $\;\;\; \quad r_{token2}\;\;\;\quad$ };
|
|
782 |
% %\node [left = 6.0cm of node1] (start1) {hi};
|
|
783 |
% \node [left = 0.2cm of node1] (middle) {$v.s.$};
|
|
784 |
% \node [minimum width = 6cm, left = 0.2cm of middle, rectangle split, rectangle split horizontal,
|
|
785 |
% rectangle split parts=2, rectangle split part fill={red!30,blue!20}, style={draw, rounded corners, inner sep=10pt}]
|
|
786 |
% (node2)
|
|
787 |
% {$\quad\;\;\;r_{token1}\quad\;\;\;$
|
|
788 |
% \nodepart{two} $r_{token2}$ };
|
|
789 |
% \node [below = 0.1cm of node2] (text1) {\checkmark preferred by POSIX};
|
|
790 |
% \node [above = 1.5cm of middle, minimum width = 6cm,
|
|
791 |
% rectangle, style={draw, rounded corners, inner sep=10pt}]
|
|
792 |
% (topNode) {$s$};
|
|
793 |
% \path[->,draw]
|
|
794 |
% (topNode) edge node {split $A$} (node2)
|
|
795 |
% (topNode) edge node {split $B$} (node1)
|
|
796 |
% ;
|
|
797 |
%
|
|
798 |
%
|
|
799 |
%\end{tikzpicture}
|
|
800 |
%\caption{Maximum munch example: $s$ matches $r_{token1} \cdot r_{token2}$}\label{munch}
|
|
801 |
%\end{figure}
|
637
|
802 |
The above $\POSIX$ rules follow the intuition described below:
|
538
|
803 |
\begin{itemize}
|
564
|
804 |
\item (Left Priority)\\
|
637
|
805 |
Match the leftmost regular expression when multiple options for matching
|
622
|
806 |
are available. See P+L and P+R where in P+R $s$ cannot
|
|
807 |
be in the language of $L \; r_1$.
|
564
|
808 |
\item (Maximum munch)\\
|
|
809 |
Always match a subpart as much as possible before proceeding
|
622
|
810 |
to the next part of the string.
|
579
|
811 |
For example, when the string $s$ matches
|
622
|
812 |
$r_{part1}\cdot r_{part2}$, and we have two ways $s$ can be split:
|
|
813 |
Then the split that matches a longer string for the first part
|
|
814 |
$r_{part1}$ is preferred by this maximum munch rule.
|
637
|
815 |
The side-condition
|
622
|
816 |
\begin{center}
|
|
817 |
$\nexists s_3 \; s_4. s_3 \neq [] \land s_3 @ s_4 = s_2 \land
|
|
818 |
s_1@ s_3 \in L \; r_1 \land s_4 \in L \; r_2$
|
|
819 |
\end{center}
|
637
|
820 |
in PS causes this.
|
622
|
821 |
%(See
|
|
822 |
%\ref{munch} for an illustration).
|
538
|
823 |
\end{itemize}
|
564
|
824 |
\noindent
|
|
825 |
These disambiguation strategies can be
|
|
826 |
quite practical.
|
538
|
827 |
For instance, when lexing a code snippet
|
564
|
828 |
\[
|
|
829 |
\textit{iffoo} = 3
|
|
830 |
\]
|
622
|
831 |
using a regular expression
|
|
832 |
for keywords and
|
|
833 |
identifiers:
|
|
834 |
%(for example, keyword is a nonempty string starting with letters
|
|
835 |
%followed by alphanumeric characters or underscores):
|
564
|
836 |
\[
|
622
|
837 |
r_{keyword} + r_{identifier}.
|
564
|
838 |
\]
|
622
|
839 |
If we want $\textit{iffoo}$ to be recognized
|
|
840 |
as an identifier
|
|
841 |
where identifiers are defined as usual (letters
|
|
842 |
followed by letters, numbers or underscores),
|
|
843 |
then a match with a keyword (if)
|
564
|
844 |
followed by
|
622
|
845 |
an identifier (foo) would be incorrect.
|
638
|
846 |
POSIX lexing generates what is included by lexing.
|
564
|
847 |
|
622
|
848 |
\noindent
|
|
849 |
We know that a POSIX
|
|
850 |
value for regular expression $r$ is inhabited by $r$.
|
541
|
851 |
\begin{lemma}
|
|
852 |
$(r, s) \rightarrow v \implies \vdash v: r$
|
|
853 |
\end{lemma}
|
|
854 |
\noindent
|
622
|
855 |
The main property about a $\POSIX$ value is that
|
538
|
856 |
given the same regular expression $r$ and string $s$,
|
|
857 |
one can always uniquely determine the $\POSIX$ value for it:
|
|
858 |
\begin{lemma}
|
|
859 |
$\textit{if} \,(s, r) \rightarrow v_1 \land (s, r) \rightarrow v_2\quad \textit{then} \; v_1 = v_2$
|
|
860 |
\end{lemma}
|
539
|
861 |
\begin{proof}
|
564
|
862 |
By induction on $s$, $r$ and $v_1$. The inductive cases
|
|
863 |
are all the POSIX rules.
|
|
864 |
Probably the most cumbersome cases are
|
|
865 |
the sequence and star with non-empty iterations.
|
567
|
866 |
We shall give the details for proving the sequence case here.
|
539
|
867 |
|
567
|
868 |
When we have
|
|
869 |
\[
|
|
870 |
(s_1, r_1) \rightarrow v_1 \;\, and \;\,
|
601
|
871 |
(s_2, r_2) \rightarrow v_2 \;\, and \;\,
|
567
|
872 |
\nexists s_3 \; s_4. s_3 \neq [] \land s_3 @ s_4 = s_2 \land
|
|
873 |
s_1@ s_3 \in L \; r_1 \land s_4 \in L \; r_2
|
|
874 |
\]
|
|
875 |
we know that the last condition
|
|
876 |
excludes the possibility of a
|
|
877 |
string $s_1'$ longer than $s_1$ such that
|
|
878 |
\[
|
|
879 |
(s_1', r_1) \rightarrow v_1' \;\;
|
|
880 |
and\;\; (s_2', r_2) \rightarrow v_2'\;\; and \;\;s_1' @s_2' = s
|
|
881 |
\]
|
|
882 |
hold.
|
|
883 |
A shorter string $s_1''$ with $s_2''$ satisfying
|
|
884 |
\[
|
|
885 |
(s_1'', r_1) \rightarrow v_1''
|
|
886 |
\;\;and\;\; (s_2'', r_2) \rightarrow v_2'' \;\;and \;\;s_1'' @s_2'' = s
|
|
887 |
\]
|
|
888 |
cannot possibly form a $\POSIX$ value either, because
|
637
|
889 |
by definition, there is a candidate
|
|
890 |
with a longer initial string
|
567
|
891 |
$s_1$. Therefore, we know that the POSIX
|
|
892 |
value $\Seq \; a \; b$ for $r_1 \cdot r_2$ matching
|
|
893 |
$s$ must have the
|
|
894 |
property that
|
|
895 |
\[
|
|
896 |
|a| = s_1 \;\; and \;\; |b| = s_2.
|
|
897 |
\]
|
|
898 |
The goal is to prove that $a = v_1 $ and $b = v_2$.
|
|
899 |
If we have some other POSIX values $v_{10}$ and $v_{20}$ such that
|
|
900 |
$(s_1, r_1) \rightarrow v_{10}$ and $(s_2, r_2) \rightarrow v_{20}$ hold,
|
|
901 |
then by induction hypothesis $v_{10} = v_1$ and $v_{20}= v_2$,
|
|
902 |
which means this "other" $\POSIX$ value $\Seq(v_{10}, v_{20})$
|
539
|
903 |
is the same as $\Seq(v_1, v_2)$.
|
|
904 |
\end{proof}
|
567
|
905 |
\noindent
|
637
|
906 |
We have now defined what a POSIX value is and shown that it is unique.
|
|
907 |
The problem is to generate
|
567
|
908 |
such a value in a lexing algorithm using derivatives.
|
538
|
909 |
|
|
910 |
\subsection{Sulzmann and Lu's Injection-based Lexing Algorithm}
|
|
911 |
|
567
|
912 |
Sulzmann and Lu extended Brzozowski's
|
|
913 |
derivative-based matching
|
622
|
914 |
to a lexing algorithm by a second phase
|
567
|
915 |
after the initial phase of successive derivatives.
|
|
916 |
This second phase generates a POSIX value
|
|
917 |
if the regular expression matches the string.
|
638
|
918 |
The algorithm uses two functions called $\inj$ and $\mkeps$.
|
622
|
919 |
The function $\mkeps$ constructs a POSIX value from the last
|
567
|
920 |
derivative $r_n$:
|
538
|
921 |
\begin{ceqn}
|
|
922 |
\begin{equation}\label{graph:mkeps}
|
|
923 |
\begin{tikzcd}
|
567
|
924 |
r_0 \arrow[r, "\backslash c_0"] & r_1 \arrow[r, "\backslash c_1"] & r_2 \arrow[r, dashed, "\ldots"] & r_n \arrow[d, "mkeps" description] \\
|
538
|
925 |
& & & v_n
|
|
926 |
\end{tikzcd}
|
|
927 |
\end{equation}
|
|
928 |
\end{ceqn}
|
567
|
929 |
\noindent
|
|
930 |
In the above diagram, again we assume that
|
|
931 |
the input string $s$ is made of $n$ characters
|
622
|
932 |
$c_0c_1 \ldots c_{n-1}$
|
|
933 |
The last derivative operation
|
|
934 |
$\backslash c_{n-1}$ generates the derivative $r_n$, for which
|
|
935 |
$\mkeps$ produces the value $v_n$. This value
|
|
936 |
tells us how the empty string is matched by the (nullable)
|
|
937 |
regular expression $r_n$, in a POSIX way.
|
567
|
938 |
The definition of $\mkeps$ is
|
538
|
939 |
\begin{center}
|
|
940 |
\begin{tabular}{lcl}
|
564
|
941 |
$\mkeps \; \ONE$ & $\dn$ & $\Empty$ \\
|
567
|
942 |
$\mkeps \; (r_{1}+r_{2})$ & $\dn$
|
|
943 |
& $\textit{if}\; (\nullable \; r_{1}) \;\,
|
|
944 |
\textit{then}\;\, \Left \; (\mkeps \; r_{1})$\\
|
|
945 |
& & $\phantom{if}\; \textit{else}\;\, \Right \;(\mkeps \; r_{2})$\\
|
|
946 |
$\mkeps \; (r_1 \cdot r_2)$ & $\dn$ & $\Seq\;(\mkeps\;r_1)\;(\mkeps \; r_2)$\\
|
564
|
947 |
$\mkeps \; r^* $ & $\dn$ & $\Stars\;[]$
|
538
|
948 |
\end{tabular}
|
|
949 |
\end{center}
|
|
950 |
|
|
951 |
|
|
952 |
\noindent
|
622
|
953 |
The function prefers the left child $r_1$ of $r_1 + r_2$
|
567
|
954 |
to match an empty string if there is a choice.
|
622
|
955 |
When there is a star to match the empty string,
|
538
|
956 |
we give the $\Stars$ constructor an empty list, meaning
|
567
|
957 |
no iteration is taken.
|
622
|
958 |
The result of $\mkeps$ on a $\nullable$ $r$
|
|
959 |
is a POSIX value for $r$ and the empty string:
|
567
|
960 |
\begin{lemma}\label{mePosix}
|
638
|
961 |
$\nullable\; r \implies (r, []) \rightarrow (\mkeps\; r)$
|
567
|
962 |
\end{lemma}
|
|
963 |
\begin{proof}
|
622
|
964 |
By induction on $r$.
|
567
|
965 |
\end{proof}
|
|
966 |
\noindent
|
622
|
967 |
After the $\mkeps$-call, Sulzmann and Lu inject back the characters one by one
|
567
|
968 |
in reverse order as they were chopped off in the derivative phase.
|
637
|
969 |
The function for this is called $\inj$. This function
|
622
|
970 |
operates on values, unlike $\backslash$ which operates on regular expressions.
|
567
|
971 |
In the diagram below, $v_i$ stands for the (POSIX) value
|
|
972 |
for how the regular expression
|
|
973 |
$r_i$ matches the string $s_i$ consisting of the last $n-i$ characters
|
|
974 |
of $s$ (i.e. $s_i = c_i \ldots c_{n-1}$ ) from the previous lexical value $v_{i+1}$.
|
538
|
975 |
After injecting back $n$ characters, we get the lexical value for how $r_0$
|
|
976 |
matches $s$.
|
601
|
977 |
\begin{figure}[H]
|
|
978 |
\begin{center}
|
538
|
979 |
\begin{ceqn}
|
|
980 |
\begin{tikzcd}
|
567
|
981 |
r_0 \arrow[r, dashed] \arrow[d]& r_i \arrow[r, "\backslash c_i"] \arrow[d] & r_{i+1} \arrow[r, dashed] \arrow[d] & r_n \arrow[d, "mkeps" description] \\
|
|
982 |
v_0 \arrow[u] & v_i \arrow[l, dashed] & v_{i+1} \arrow[l,"inj_{r_i} c_i"] & v_n \arrow[l, dashed]
|
538
|
983 |
\end{tikzcd}
|
|
984 |
\end{ceqn}
|
601
|
985 |
\end{center}
|
|
986 |
\caption{The two-phase lexing algorithm by Sulzmann and Lu \cite{AusafDyckhoffUrban2016},
|
|
987 |
matching the regular expression $r_0$ and string of the form $[c_0, c_1, \ldots, c_{n-1}]$.
|
|
988 |
The first phase involves taking successive derivatives w.r.t the characters $c_0$,
|
|
989 |
$c_1$, and so on. These are the same operations as they have appeared in the matcher
|
|
990 |
\ref{matcher}. When the final derivative regular expression is nullable (contains the empty string),
|
637
|
991 |
then the second phase starts. First, $\mkeps$ generates a POSIX value which tells us how $r_n$ matches
|
|
992 |
the empty string, by always selecting the leftmost
|
|
993 |
nullable regular expression. After that, $\inj$ ``injects'' back the character in reverse order as they
|
601
|
994 |
appeared in the string, always preserving POSIXness.}\label{graph:inj}
|
|
995 |
\end{figure}
|
538
|
996 |
\noindent
|
623
|
997 |
The function $\textit{inj}$ as defined by Sulzmann and Lu
|
|
998 |
takes three arguments: a regular
|
567
|
999 |
expression ${r_{i}}$, before the character is chopped off,
|
623
|
1000 |
a character ${c_{i}}$ (the character we want to inject back) and
|
567
|
1001 |
the third argument $v_{i+1}$ the value we want to inject into.
|
568
|
1002 |
The result of an application
|
|
1003 |
$\inj \; r_i \; c_i \; v_{i+1}$ is a new value $v_i$ such that
|
|
1004 |
\[
|
|
1005 |
(s_i, r_i) \rightarrow v_i
|
|
1006 |
\]
|
|
1007 |
holds.
|
567
|
1008 |
The definition of $\textit{inj}$ is as follows:
|
538
|
1009 |
\begin{center}
|
568
|
1010 |
\begin{tabular}{l@{\hspace{1mm}}c@{\hspace{5mm}}l}
|
|
1011 |
$\textit{inj}\;(c)\;c\,Empty$ & $\dn$ & $\Char\,c$\\
|
|
1012 |
$\textit{inj}\;(r_1 + r_2)\;c\; (\Left\; v)$ & $\dn$ & $\Left \; (\textit{inj}\; r_1 \; c\,v)$\\
|
|
1013 |
$\textit{inj}\;(r_1 + r_2)\,c\; (\Right\;v)$ & $\dn$ & $\Right \; (\textit{inj}\;r_2\;c \; v)$\\
|
|
1014 |
$\textit{inj}\;(r_1 \cdot r_2)\; c\;(\Seq \; v_1 \; v_2)$ & $\dn$ &
|
|
1015 |
$\Seq \; (\textit{inj}\;r_1\;c\;v_1) \; v_2$\\
|
|
1016 |
$\textit{inj}\;(r_1 \cdot r_2)\; c\;(\Left \; (\Seq \; v_1\;v_2) )$ &
|
|
1017 |
$\dn$ & $\Seq \; (\textit{inj}\,r_1\,c\,v_1)\; v_2$\\
|
|
1018 |
$\textit{inj}\;(r_1 \cdot r_2)\; c\; (\Right\; v)$ & $\dn$ & $\Seq\; (\textit{mkeps}\; r_1) \; (\textit{inj} \; r_2\;c\;v)$\\
|
|
1019 |
$\textit{inj}\;(r^*)\; c \; (\Seq \; v\; (\Stars\;vs))$ & $\dn$ & $\Stars\;\,((\textit{inj}\;r\;c\;v)\,::\,vs)$\\
|
538
|
1020 |
\end{tabular}
|
|
1021 |
\end{center}
|
|
1022 |
|
|
1023 |
\noindent
|
623
|
1024 |
The function recurses on
|
568
|
1025 |
the shape of regular
|
637
|
1026 |
expressions and values.
|
568
|
1027 |
Intuitively, each clause analyses
|
|
1028 |
how $r_i$ could have transformed when being
|
|
1029 |
derived by $c$, identifying which subpart
|
|
1030 |
of $v_{i+1}$ has the ``hole''
|
|
1031 |
to inject the character back into.
|
|
1032 |
Once the character is
|
|
1033 |
injected back to that sub-value;
|
637
|
1034 |
$\inj$ assembles all parts
|
568
|
1035 |
to form a new value.
|
|
1036 |
|
|
1037 |
For instance, the last clause is an
|
|
1038 |
injection into a sequence value $v_{i+1}$
|
|
1039 |
whose second child
|
637
|
1040 |
value is a star and the shape of the
|
568
|
1041 |
regular expression $r_i$ before injection
|
|
1042 |
is a star.
|
|
1043 |
We therefore know
|
|
1044 |
the derivative
|
|
1045 |
starts on a star and ends as a sequence:
|
|
1046 |
\[
|
|
1047 |
(r^*) \backslash c \longrightarrow r\backslash c \cdot r^*
|
|
1048 |
\]
|
|
1049 |
during which an iteration of the star
|
|
1050 |
had just been unfolded, giving the below
|
|
1051 |
value inhabitation relation:
|
|
1052 |
\[
|
|
1053 |
\vdash \Seq \; v \; (\Stars \; vs) : (r\backslash c) \cdot r^*.
|
|
1054 |
\]
|
|
1055 |
The value list $vs$ corresponds to
|
|
1056 |
matched star iterations,
|
|
1057 |
and the ``hole'' lies in $v$ because
|
|
1058 |
\[
|
|
1059 |
\vdash v: r\backslash c.
|
|
1060 |
\]
|
|
1061 |
Finally,
|
|
1062 |
$\inj \; r \;c \; v$ is prepended
|
637
|
1063 |
to the previous list of iterations and then
|
568
|
1064 |
wrapped under the $\Stars$
|
|
1065 |
constructor, giving us $\Stars \; ((\inj \; r \; c \; v) ::vs)$.
|
538
|
1066 |
|
568
|
1067 |
Recall that lemma
|
623
|
1068 |
\ref{mePosix} tells us that
|
|
1069 |
$\mkeps$ always generates the POSIX value.
|
|
1070 |
The function $\inj$ preserves the POSIXness, provided
|
|
1071 |
the value before injection is POSIX, namely
|
568
|
1072 |
\begin{lemma}\label{injPosix}
|
623
|
1073 |
If$(r \backslash c, s) \rightarrow v $,
|
|
1074 |
then $(r, c :: s) \rightarrow (\inj r \; c\; v)$.
|
568
|
1075 |
\end{lemma}
|
|
1076 |
\begin{proof}
|
|
1077 |
By induction on $r$.
|
623
|
1078 |
The non-trivial cases are sequence and star.
|
|
1079 |
When $r = a \cdot b$, there can be
|
568
|
1080 |
three cases for the value $v$ satisfying $\vdash v:a\backslash c$.
|
|
1081 |
We give the reasoning why $\inj \; r \; c \; v$ is POSIX in each
|
|
1082 |
case.
|
|
1083 |
\begin{itemize}
|
|
1084 |
\item
|
|
1085 |
$v = \Seq \; v_a \; v_b$.\\
|
|
1086 |
The ``not nullable'' clause of the $\inj$ function is taken:
|
|
1087 |
\begin{center}
|
|
1088 |
\begin{tabular}{lcl}
|
|
1089 |
$\inj \; r \; c \; v$ & $=$ & $ \inj \;\; (a \cdot b) \;\; c \;\; (\Seq \; v_a \; v_b) $\\
|
|
1090 |
& $=$ & $\Seq \; (\inj \;a \; c \; v_a) \; v_b$
|
|
1091 |
\end{tabular}
|
|
1092 |
\end{center}
|
|
1093 |
We know that there exists a unique pair of
|
637
|
1094 |
$s_a$ and $s_b$ satisfying
|
568
|
1095 |
$(a \backslash c, s_a) \rightarrow v_a$,
|
|
1096 |
$(b , s_b) \rightarrow v_b$, and
|
|
1097 |
$\nexists s_3 \; s_4. s_3 \neq [] \land s_a @ s_3 \in
|
|
1098 |
L \; (a\backslash c) \land
|
|
1099 |
s_4 \in L \; b$.
|
|
1100 |
The last condition gives us
|
|
1101 |
$\nexists s_3 \; s_4. s_3 \neq [] \land (c :: s_a )@ s_3 \in
|
|
1102 |
L \; a \land
|
|
1103 |
s_4 \in L \; b$.
|
|
1104 |
By induction hypothesis, $(a, c::s_a) \rightarrow \inj \; a \; c \; v_a $ holds,
|
|
1105 |
and this gives us
|
|
1106 |
\[
|
|
1107 |
(a\cdot b, (c::s_a)@s_b) \rightarrow \Seq \; (\inj \; a\;c \;v_a) \; v_b.
|
|
1108 |
\]
|
|
1109 |
\item
|
|
1110 |
$v = \Left \; (\Seq \; v_a \; v_b)$\\
|
|
1111 |
The argument is almost identical to the above case,
|
|
1112 |
except that a different clause of $\inj$ is taken:
|
|
1113 |
\begin{center}
|
|
1114 |
\begin{tabular}{lcl}
|
|
1115 |
$\inj \; r \; c \; v$ & $=$ & $ \inj \;\; (a \cdot b) \;\; c \;\; (\Left \; (\Seq \; v_a \; v_b)) $\\
|
|
1116 |
& $=$ & $\Seq \; (\inj \;a \; c \; v_a) \; v_b$
|
|
1117 |
\end{tabular}
|
|
1118 |
\end{center}
|
637
|
1119 |
With similar reasoning,
|
538
|
1120 |
|
568
|
1121 |
\[
|
|
1122 |
(a\cdot b, (c::s_a)@s_b) \rightarrow \Seq \; (\inj \; a\;c \;v_a) \; v_b.
|
|
1123 |
\]
|
|
1124 |
again holds.
|
|
1125 |
\item
|
|
1126 |
$v = \Right \; v_b$\\
|
|
1127 |
Again the injection result would be
|
|
1128 |
\begin{center}
|
|
1129 |
\begin{tabular}{lcl}
|
|
1130 |
$\inj \; r \; c \; v$ & $=$ & $ \inj \;\; (a \cdot b) \;\; c \;\; \Right \; (v_b) $\\
|
|
1131 |
& $=$ & $\Seq \; (\mkeps \; a) \; (\inj \;b \; c\; v_b)$
|
|
1132 |
\end{tabular}
|
|
1133 |
\end{center}
|
|
1134 |
We know that $a$ must be nullable,
|
|
1135 |
allowing us to call $\mkeps$ and get
|
|
1136 |
\[
|
|
1137 |
(a, []) \rightarrow \mkeps \; a.
|
|
1138 |
\]
|
637
|
1139 |
Also, by inductive hypothesis
|
568
|
1140 |
\[
|
|
1141 |
(b, c::s) \rightarrow \inj\; b \; c \; v_b
|
|
1142 |
\]
|
|
1143 |
holds.
|
|
1144 |
In addition, as
|
|
1145 |
$\Right \;v_b$ instead of $\Left \ldots$ is
|
|
1146 |
the POSIX value for $v$, it must be the case
|
|
1147 |
that $s \notin L \;( (a\backslash c)\cdot b)$.
|
|
1148 |
This tells us that
|
|
1149 |
\[
|
|
1150 |
\nexists s_3 \; s_4.
|
|
1151 |
s_3 @s_4 = s \land s_3 \in L \; (a\backslash c)
|
|
1152 |
\land s_4 \in L \; b
|
|
1153 |
\]
|
|
1154 |
which translates to
|
|
1155 |
\[
|
|
1156 |
\nexists s_3 \; s_4. \; s_3 \neq [] \land
|
|
1157 |
s_3 @s_4 = c::s \land s_3 \in L \; a
|
|
1158 |
\land s_4 \in L \; b.
|
|
1159 |
\]
|
637
|
1160 |
(Which says there cannot be a longer
|
568
|
1161 |
initial split for $s$ other than the empty string.)
|
|
1162 |
Therefore we have $\Seq \; (\mkeps \; a) \;(\inj \;b \; c\; v_b)$
|
|
1163 |
as the POSIX value for $a\cdot b$.
|
|
1164 |
\end{itemize}
|
|
1165 |
The star case can be proven similarly.
|
|
1166 |
\end{proof}
|
|
1167 |
\noindent
|
623
|
1168 |
Putting all together, Sulzmann and Lu obtained the following algorithm
|
|
1169 |
outlined in the diagram \ref{graph:inj}:
|
538
|
1170 |
\begin{center}
|
539
|
1171 |
\begin{tabular}{lcl}
|
568
|
1172 |
$\lexer \; r \; [] $ & $=$ & $\textit{if} \; (\nullable \; r)\; \textit{then}\; \Some(\mkeps \; r) \; \textit{else} \; \None$\\
|
|
1173 |
$\lexer \; r \;c::s$ & $=$ & $\textit{case}\; (\lexer \; (r\backslash c) \; s) \;\textit{of}\; $\\
|
|
1174 |
& & $\quad \phantom{\mid}\; \None \implies \None$\\
|
|
1175 |
& & $\quad \mid \Some(v) \implies \Some(\inj \; r\; c\; v)$
|
538
|
1176 |
\end{tabular}
|
|
1177 |
\end{center}
|
568
|
1178 |
\noindent
|
623
|
1179 |
The central property of the $\lexer$ is that it gives the correct result
|
|
1180 |
according to
|
|
1181 |
POSIX rules.
|
573
|
1182 |
\begin{theorem}\label{lexerCorrectness}
|
568
|
1183 |
The $\lexer$ based on derivatives and injections is correct:
|
|
1184 |
\begin{center}
|
|
1185 |
\begin{tabular}{lcl}
|
|
1186 |
$\lexer \; r \; s = \Some(v)$ & $ \Longleftrightarrow$ & $ (r, \; s) \rightarrow v$\\
|
|
1187 |
$\lexer \;r \; s = \None $ & $\Longleftrightarrow$ & $ \neg(\exists v. (r, s) \rightarrow v)$
|
|
1188 |
\end{tabular}
|
|
1189 |
\end{center}
|
|
1190 |
\end{theorem}
|
|
1191 |
\begin{proof}
|
623
|
1192 |
By induction on $s$. $r$ generalising over an arbitrary regular expression.
|
637
|
1193 |
The $[]$ case is proven by an application of lemma \ref{mePosix}, and the inductive case
|
568
|
1194 |
by lemma \ref{injPosix}.
|
|
1195 |
\end{proof}
|
538
|
1196 |
\noindent
|
623
|
1197 |
As we did earlier in this chapter with the matcher, one can
|
|
1198 |
introduce simplification on the regular expression in each derivative step.
|
637
|
1199 |
However, due to lexing, one needs to do a backward phase (w.r.t the forward derivative phase)
|
|
1200 |
and ensure that
|
|
1201 |
the values align with the regular expression at each step.
|
539
|
1202 |
Therefore one has to
|
538
|
1203 |
be careful not to break the correctness, as the injection
|
623
|
1204 |
function heavily relies on the structure of
|
|
1205 |
the regular expressions and values being aligned.
|
|
1206 |
This can be achieved by recording some extra rectification functions
|
637
|
1207 |
during the derivatives step and applying these rectifications in
|
538
|
1208 |
each run during the injection phase.
|
568
|
1209 |
With extra care
|
623
|
1210 |
one can show that POSIXness will not be affected
|
|
1211 |
by the simplifications listed here \cite{AusafDyckhoffUrban2016}.
|
|
1212 |
\begin{center}
|
|
1213 |
\begin{tabular}{lcl}
|
|
1214 |
$\simp \; r_1 \cdot r_2 $ & $ \dn$ &
|
|
1215 |
$(\simp \; r_1, \simp \; r_2) \; \textit{match}$\\
|
|
1216 |
& & $\quad \case \; (\ZERO, \_) \Rightarrow \ZERO$\\
|
|
1217 |
& & $\quad \case \; (\_, \ZERO) \Rightarrow \ZERO$\\
|
|
1218 |
& & $\quad \case \; (\ONE, r_2') \Rightarrow r_2'$\\
|
|
1219 |
& & $\quad \case \; (r_1', \ONE) \Rightarrow r_1'$\\
|
|
1220 |
& & $\quad \case \; (r_1', r_2') \Rightarrow r_1'\cdot r_2'$\\
|
|
1221 |
$\simp \; r_1 + r_2$ & $\dn$ & $(\simp \; r_1, \simp \; r_2) \textit{match}$\\
|
|
1222 |
& & $\quad \; \case \; (\ZERO, r_2') \Rightarrow r_2'$\\
|
|
1223 |
& & $\quad \; \case \; (r_1', \ZERO) \Rightarrow r_1'$\\
|
|
1224 |
& & $\quad \; \case \; (r_1', r_2') \Rightarrow r_1' + r_2'$\\
|
|
1225 |
$\simp \; r$ & $\dn$ & $r\quad\quad (otherwise)$
|
|
1226 |
|
|
1227 |
\end{tabular}
|
|
1228 |
\end{center}
|
538
|
1229 |
|
637
|
1230 |
However, one can still end up
|
|
1231 |
with exploding derivatives,
|
|
1232 |
even with the simple-minded simplification rules allowed
|
|
1233 |
in an injection-based lexer.
|
|
1234 |
\section{A Case Requiring More Aggressive Simplifications}
|
539
|
1235 |
For example, when starting with the regular
|
585
|
1236 |
expression $(a^* \cdot a^*)^*$ and building just over
|
|
1237 |
a dozen successive derivatives
|
539
|
1238 |
w.r.t.~the character $a$, one obtains a derivative regular expression
|
585
|
1239 |
with millions of nodes (when viewed as a tree)
|
637
|
1240 |
even with the mentioned simplifications.
|
585
|
1241 |
\begin{figure}[H]
|
601
|
1242 |
\begin{center}
|
539
|
1243 |
\begin{tikzpicture}
|
|
1244 |
\begin{axis}[
|
|
1245 |
xlabel={$n$},
|
|
1246 |
ylabel={size},
|
585
|
1247 |
legend entries={Simple-Minded Simp, Naive Matcher},
|
539
|
1248 |
legend pos=north west,
|
|
1249 |
legend cell align=left]
|
|
1250 |
\addplot[red,mark=*, mark options={fill=white}] table {BetterWaterloo.data};
|
585
|
1251 |
\addplot[blue,mark=*, mark options={fill=white}] table {BetterWaterloo1.data};
|
539
|
1252 |
\end{axis}
|
|
1253 |
\end{tikzpicture}
|
601
|
1254 |
\end{center}
|
539
|
1255 |
\caption{Size of $(a^*\cdot a^*)^*$ against $\protect\underbrace{aa\ldots a}_\text{n \textit{a}s}$}
|
|
1256 |
\end{figure}\label{fig:BetterWaterloo}
|
|
1257 |
|
568
|
1258 |
That is because Sulzmann and Lu's
|
|
1259 |
injection-based lexing algorithm keeps a lot of
|
541
|
1260 |
"useless" values that will not be used.
|
539
|
1261 |
These different ways of matching will grow exponentially with the string length.
|
623
|
1262 |
Consider the case
|
568
|
1263 |
\[
|
|
1264 |
r= (a^*\cdot a^*)^* \quad and \quad
|
|
1265 |
s=\underbrace{aa\ldots a}_\text{n \textit{a}s}
|
|
1266 |
\]
|
|
1267 |
as an example.
|
|
1268 |
This is a highly ambiguous regular expression, with
|
|
1269 |
many ways to split up the string into multiple segments for
|
637
|
1270 |
different star iterations,
|
573
|
1271 |
and for each segment
|
|
1272 |
multiple ways of splitting between
|
568
|
1273 |
the two $a^*$ sub-expressions.
|
573
|
1274 |
When $n$ is equal to $1$, there are two lexical values for
|
|
1275 |
the match:
|
|
1276 |
\[
|
623
|
1277 |
\Stars \; [\Seq \; (\Stars \; [\Char \; a])\; (\Stars \; [])] \quad (v1)
|
573
|
1278 |
\]
|
|
1279 |
and
|
|
1280 |
\[
|
623
|
1281 |
\Stars \; [\Seq \; (\Stars \; [])\; (\Stars \; [\Char \; a])] \quad (v2)
|
573
|
1282 |
\]
|
|
1283 |
The derivative of $\derssimp \;s \; r$ is
|
|
1284 |
\[
|
|
1285 |
(a^*a^* + a^*)\cdot(a^*a^*)^*.
|
|
1286 |
\]
|
|
1287 |
The $a^*a^*$ and $a^*$ in the first child of the above sequence
|
|
1288 |
correspond to value 1 and value 2, respectively.
|
|
1289 |
When $n=2$, the number goes up to 7:
|
|
1290 |
\[
|
|
1291 |
\Stars \; [\Seq \; (\Stars \; [\Char \; a, \Char \; a])\; (\Stars \; [])]
|
|
1292 |
\]
|
623
|
1293 |
|
573
|
1294 |
\[
|
|
1295 |
\Stars \; [\Seq \; (\Stars \; [\Char \; a])\; (\Stars \; [\Char \; a])]
|
|
1296 |
\]
|
623
|
1297 |
|
573
|
1298 |
\[
|
|
1299 |
\Stars \; [\Seq \; (\Stars \; [])\; (\Stars \; [\Char \; a, \Char \; a])]
|
|
1300 |
\]
|
623
|
1301 |
|
573
|
1302 |
\[
|
|
1303 |
\Stars \; [\Seq \; (\Stars \; [\Char \; a])\; (\Stars \; []), \Seq \; (\Stars \; [\Char\;a])\; (\Stars\; []) ]
|
|
1304 |
\]
|
623
|
1305 |
|
573
|
1306 |
\[
|
|
1307 |
\Stars \; [\Seq \; (\Stars \; [\Char \; a])\; (\Stars \; []),
|
|
1308 |
\Seq \; (\Stars \; [])\; (\Stars \; [\Char \; a])
|
|
1309 |
]
|
|
1310 |
\]
|
623
|
1311 |
|
573
|
1312 |
\[
|
|
1313 |
\Stars \; [
|
|
1314 |
\Seq \; (\Stars \; [])\; (\Stars \; [\Char \; a]),
|
|
1315 |
\Seq \; (\Stars \; [])\; (\Stars \; [\Char \; a])
|
|
1316 |
]
|
|
1317 |
\]
|
|
1318 |
and
|
|
1319 |
\[
|
|
1320 |
\Stars \; [
|
|
1321 |
\Seq \; (\Stars \; [])\; (\Stars \; [\Char \; a]),
|
|
1322 |
\Seq \; (\Stars \; [\Char \; a])\; (\Stars \; [])
|
|
1323 |
]
|
|
1324 |
\]
|
638
|
1325 |
And $\derssimp \; aa \; (a^*a^*)^*$ is
|
573
|
1326 |
\[
|
|
1327 |
((a^*a^* + a^*)+a^*)\cdot(a^*a^*)^* +
|
|
1328 |
(a^*a^* + a^*)\cdot(a^*a^*)^*.
|
|
1329 |
\]
|
|
1330 |
which removes two out of the seven terms corresponding to the
|
|
1331 |
seven distinct lexical values.
|
|
1332 |
|
|
1333 |
It is not surprising that there are exponentially many
|
|
1334 |
distinct lexical values that cannot be eliminated by
|
|
1335 |
the simple-minded simplification of $\derssimp$.
|
568
|
1336 |
A lexer without a good enough strategy to
|
|
1337 |
deduplicate will naturally
|
623
|
1338 |
have an exponential runtime on highly
|
637
|
1339 |
ambiguous regular expressions because there
|
623
|
1340 |
are exponentially many matches.
|
|
1341 |
For this particular example, it seems
|
|
1342 |
that the number of distinct matches growth
|
|
1343 |
speed is proportional to $(2n)!/(n!(n+1)!)$ ($n$ being the input length).
|
538
|
1344 |
|
573
|
1345 |
On the other hand, the
|
|
1346 |
$\POSIX$ value for $r= (a^*\cdot a^*)^*$ and
|
|
1347 |
$s=\underbrace{aa\ldots a}_\text{n \textit{a}s}$ is
|
|
1348 |
\[
|
|
1349 |
\Stars\,
|
637
|
1350 |
[\Seq \; (\Stars\,[\underbrace{\Char(a),\ldots,\Char(a)}_\text{n iterations}]), \Stars\,[]].
|
573
|
1351 |
\]
|
637
|
1352 |
At any moment, the subterms in a regular expression
|
|
1353 |
that will potentially result in a POSIX value is only
|
573
|
1354 |
a minority among the many other terms,
|
638
|
1355 |
and one can remove the ones that are not possible to
|
573
|
1356 |
be POSIX.
|
|
1357 |
In the above example,
|
579
|
1358 |
\begin{equation}\label{eqn:growth2}
|
573
|
1359 |
((a^*a^* + \underbrace{a^*}_\text{A})+\underbrace{a^*}_\text{duplicate of A})\cdot(a^*a^*)^* +
|
|
1360 |
\underbrace{(a^*a^* + a^*)\cdot(a^*a^*)^*}_\text{further simp removes this}.
|
579
|
1361 |
\end{equation}
|
573
|
1362 |
can be further simplified by
|
|
1363 |
removing the underlined term first,
|
|
1364 |
which would open up possibilities
|
|
1365 |
of further simplification that removes the
|
|
1366 |
underbraced part.
|
|
1367 |
The result would be
|
|
1368 |
\[
|
|
1369 |
(\underbrace{a^*a^*}_\text{term 1} + \underbrace{a^*}_\text{term 2})\cdot(a^*a^*)^*.
|
|
1370 |
\]
|
|
1371 |
with corresponding values
|
|
1372 |
\begin{center}
|
|
1373 |
\begin{tabular}{lr}
|
|
1374 |
$\Stars \; [\Seq \; (\Stars \; [\Char \; a, \Char \; a])\; (\Stars \; [])]$ & $(\text{term 1})$\\
|
|
1375 |
$\Stars \; [\Seq \; (\Stars \; [\Char \; a])\; (\Stars \; [\Char \; a])] $ & $(\text{term 2})$
|
|
1376 |
\end{tabular}
|
|
1377 |
\end{center}
|
637
|
1378 |
Other terms with an underlying value, such as
|
573
|
1379 |
\[
|
|
1380 |
\Stars \; [\Seq \; (\Stars \; [])\; (\Stars \; [\Char \; a, \Char \; a])]
|
|
1381 |
\]
|
638
|
1382 |
do not to contribute a POSIX lexical value,
|
|
1383 |
and therefore can be thrown away.
|
538
|
1384 |
|
623
|
1385 |
Ausaf et al. \cite{AusafDyckhoffUrban2016}
|
639
|
1386 |
have come up with some simplification steps,
|
|
1387 |
and incorporated the simplification into $\lexer$.
|
|
1388 |
They call this lexer $\textit{lexer}_{simp}$ and proved that
|
|
1389 |
\[
|
|
1390 |
\lexer \; r\; s = \textit{lexer}_{simp} \; r \; s
|
|
1391 |
\]
|
|
1392 |
The function $\textit{lexer}_{simp}$
|
|
1393 |
involves some fiddly manipulation of value rectification,
|
|
1394 |
which we omit here.
|
|
1395 |
however those steps
|
638
|
1396 |
are not yet sufficiently strong, to achieve the above effects.
|
637
|
1397 |
And even with these relatively mild simplifications, the proof
|
|
1398 |
is already quite a bit more complicated than the theorem \ref{lexerCorrectness}.
|
638
|
1399 |
One would need to prove something like this:
|
573
|
1400 |
\[
|
|
1401 |
\textit{If}\; (\textit{snd} \; (\textit{simp} \; r\backslash c), s) \rightarrow v \;\;
|
|
1402 |
\textit{then}\;\; (r, c::s) \rightarrow
|
637
|
1403 |
\inj\;\, r\, \;c \;\, ((\textit{fst} \; (\textit{simp} \; r \backslash c))\; v).
|
573
|
1404 |
\]
|
|
1405 |
instead of the simple lemma \ref{injPosix}, where now $\textit{simp}$
|
|
1406 |
not only has to return a simplified regular expression,
|
|
1407 |
but also what specific simplifications
|
638
|
1408 |
have been done as a function on values
|
573
|
1409 |
showing how one can transform the value
|
|
1410 |
underlying the simplified regular expression
|
|
1411 |
to the unsimplified one.
|
|
1412 |
|
623
|
1413 |
We therefore choose a slightly different approach
|
|
1414 |
also described by Sulzmann and Lu to
|
573
|
1415 |
get better simplifications, which uses
|
|
1416 |
some augmented data structures compared to
|
|
1417 |
plain regular expressions.
|
|
1418 |
We call them \emph{annotated}
|
|
1419 |
regular expressions.
|
|
1420 |
With annotated regular expressions,
|
|
1421 |
we can avoid creating the intermediate values $v_1,\ldots v_n$ and a
|
|
1422 |
second phase altogether.
|
|
1423 |
We introduce this new datatype and the
|
|
1424 |
corresponding algorithm in the next chapter.
|
538
|
1425 |
|
|
1426 |
|
|
1427 |
|
|
1428 |
|