94
|
1 |
\documentclass[a4paper,UKenglish]{lipics}
|
|
2 |
\usepackage{graphic}
|
|
3 |
\usepackage{data}
|
|
4 |
\usepackage{tikz-cd}
|
114
|
5 |
\usepackage{tikz}
|
|
6 |
\usetikzlibrary{graphs}
|
|
7 |
\usetikzlibrary{graphdrawing}
|
|
8 |
\usegdlibrary{trees}
|
94
|
9 |
%\usepackage{algorithm}
|
|
10 |
\usepackage{amsmath}
|
110
|
11 |
\usepackage{xcolor}
|
94
|
12 |
\usepackage[noend]{algpseudocode}
|
|
13 |
\usepackage{enumitem}
|
|
14 |
\usepackage{nccmath}
|
113
|
15 |
\usepackage{soul}
|
94
|
16 |
|
|
17 |
\definecolor{darkblue}{rgb}{0,0,0.6}
|
|
18 |
\hypersetup{colorlinks=true,allcolors=darkblue}
|
|
19 |
\newcommand{\comment}[1]%
|
|
20 |
{{\color{red}$\Rightarrow$}\marginpar{\raggedright\small{\bf\color{red}#1}}}
|
|
21 |
|
|
22 |
% \documentclass{article}
|
|
23 |
%\usepackage[utf8]{inputenc}
|
|
24 |
%\usepackage[english]{babel}
|
|
25 |
%\usepackage{listings}
|
|
26 |
% \usepackage{amsthm}
|
|
27 |
%\usepackage{hyperref}
|
|
28 |
% \usepackage[margin=0.5in]{geometry}
|
|
29 |
%\usepackage{pmboxdraw}
|
|
30 |
|
|
31 |
\title{POSIX Regular Expression Matching and Lexing}
|
|
32 |
\author{Chengsong Tan}
|
|
33 |
\affil{King's College London\\
|
|
34 |
London, UK\\
|
|
35 |
\texttt{chengsong.tan@kcl.ac.uk}}
|
|
36 |
\authorrunning{Chengsong Tan}
|
|
37 |
\Copyright{Chengsong Tan}
|
|
38 |
|
|
39 |
\newcommand{\dn}{\stackrel{\mbox{\scriptsize def}}{=}}%
|
|
40 |
\newcommand{\ZERO}{\mbox{\bf 0}}
|
|
41 |
\newcommand{\ONE}{\mbox{\bf 1}}
|
101
|
42 |
\def\erase{\textit{erase}}
|
94
|
43 |
\def\bders{\textit{bders}}
|
|
44 |
\def\lexer{\mathit{lexer}}
|
|
45 |
\def\blexer{\textit{blexer}}
|
107
|
46 |
\def\fuse{\textit{fuse}}
|
|
47 |
\def\flatten{\textit{flatten}}
|
|
48 |
\def\map{\textit{map}}
|
94
|
49 |
\def\blexers{\mathit{blexer\_simp}}
|
95
|
50 |
\def\simp{\mathit{simp}}
|
94
|
51 |
\def\mkeps{\mathit{mkeps}}
|
|
52 |
\def\bmkeps{\textit{bmkeps}}
|
|
53 |
\def\inj{\mathit{inj}}
|
|
54 |
\def\Empty{\mathit{Empty}}
|
|
55 |
\def\Left{\mathit{Left}}
|
|
56 |
\def\Right{\mathit{Right}}
|
|
57 |
\def\Stars{\mathit{Stars}}
|
|
58 |
\def\Char{\mathit{Char}}
|
|
59 |
\def\Seq{\mathit{Seq}}
|
|
60 |
\def\Der{\mathit{Der}}
|
|
61 |
\def\nullable{\mathit{nullable}}
|
|
62 |
\def\Z{\mathit{Z}}
|
|
63 |
\def\S{\mathit{S}}
|
|
64 |
\def\flex{\textit{flex}}
|
|
65 |
\def\rup{r^\uparrow}
|
|
66 |
\def\retrieve{\textit{retrieve}}
|
|
67 |
\def\AALTS{\textit{AALTS}}
|
|
68 |
\def\AONE{\textit{AONE}}
|
|
69 |
%\theoremstyle{theorem}
|
|
70 |
%\newtheorem{theorem}{Theorem}
|
|
71 |
%\theoremstyle{lemma}
|
|
72 |
%\newtheorem{lemma}{Lemma}
|
|
73 |
%\newcommand{\lemmaautorefname}{Lemma}
|
|
74 |
%\theoremstyle{definition}
|
|
75 |
%\newtheorem{definition}{Definition}
|
|
76 |
\algnewcommand\algorithmicswitch{\textbf{switch}}
|
|
77 |
\algnewcommand\algorithmiccase{\textbf{case}}
|
|
78 |
\algnewcommand\algorithmicassert{\texttt{assert}}
|
|
79 |
\algnewcommand\Assert[1]{\State \algorithmicassert(#1)}%
|
|
80 |
% New "environments"
|
|
81 |
\algdef{SE}[SWITCH]{Switch}{EndSwitch}[1]{\algorithmicswitch\ #1\ \algorithmicdo}{\algorithmicend\ \algorithmicswitch}%
|
|
82 |
\algdef{SE}[CASE]{Case}{EndCase}[1]{\algorithmiccase\ #1}{\algorithmicend\ \algorithmiccase}%
|
|
83 |
\algtext*{EndSwitch}%
|
|
84 |
\algtext*{EndCase}%
|
|
85 |
|
|
86 |
|
|
87 |
\begin{document}
|
|
88 |
|
|
89 |
\maketitle
|
|
90 |
|
|
91 |
\begin{abstract}
|
|
92 |
Brzozowski introduced in 1964 a beautifully simple algorithm for
|
|
93 |
regular expression matching based on the notion of derivatives of
|
|
94 |
regular expressions. In 2014, Sulzmann and Lu extended this
|
|
95 |
algorithm to not just give a YES/NO answer for whether or not a
|
|
96 |
regular expression matches a string, but in case it does also
|
|
97 |
answers with \emph{how} it matches the string. This is important for
|
|
98 |
applications such as lexing (tokenising a string). The problem is to
|
|
99 |
make the algorithm by Sulzmann and Lu fast on all inputs without
|
100
|
100 |
breaking its correctness. Being fast depends on a complete set of
|
|
101 |
simplification rules, some of which
|
|
102 |
have been put forward by Sulzmann and Lu. We have extended their
|
105
|
103 |
rules in order to obtain a tight bound on the size of regular expressions.
|
|
104 |
We have tested these extended rules, but have not
|
|
105 |
formally established their correctness. We have also not yet looked
|
100
|
106 |
at extended regular expressions, such as bounded repetitions,
|
94
|
107 |
negation and back-references.
|
|
108 |
\end{abstract}
|
|
109 |
|
126
|
110 |
|
|
111 |
\section{Introduction}
|
129
|
112 |
%Regular expressions' derivatives, which have received
|
|
113 |
%renewed interest in the new millenium, is a beautiful....
|
126
|
114 |
While we believe derivatives of regular expressions, written
|
|
115 |
$r\backslash s$, are a beautiful concept (in terms of ease of
|
|
116 |
implementing them in functional programming languages and in terms of
|
|
117 |
reasoning about them formally), they have one major drawback: every
|
|
118 |
derivative step can make regular expressions grow drastically in
|
|
119 |
size. This in turn has negative effect on the runtime of the
|
|
120 |
corresponding lexing algorithms. Consider for example the regular
|
|
121 |
expression $(a+aa)^*$ and the short string $aaaaaaaaaaaa$. The
|
|
122 |
corresponding derivative contains already 8668 nodes where we assume
|
|
123 |
the derivative is given as a tree. The reason for the poor runtime of
|
|
124 |
the derivative-based lexing algorithms is that they need to traverse
|
|
125 |
such trees over and over again. The solution is to find a complete set
|
|
126 |
of simplification rules that keep the sizes of derivatives uniformly
|
|
127 |
small.
|
|
128 |
|
128
|
129 |
This has been partially addressed by the function $\blexer_{simp}$,
|
|
130 |
which after the simplification the $(a+aa)^*$ example's 8000 nodes will be
|
|
131 |
reduced to just 6 and stays constant in each derivative step.
|
|
132 |
The part that still needs more work is the correctness proof of this
|
|
133 |
function, namely,
|
|
134 |
\begin{equation}\label{mainthm}
|
|
135 |
\blexers \; r \; s = \blexer \;r\;s
|
|
136 |
\end{equation}
|
|
137 |
|
|
138 |
\noindent
|
|
139 |
and this is what this report is mainly about. A condensed
|
|
140 |
version of the last report will be provided in the next section
|
|
141 |
to help the reader understand the report, and the attempts
|
|
142 |
on the problem will follow.
|
|
143 |
|
126
|
144 |
|
107
|
145 |
\section{Recapitulation of Concepts From the Last Report}
|
108
|
146 |
|
|
147 |
\subsection*{Regular Expressions and Derivatives}
|
107
|
148 |
Suppose (basic) regular expressions are given by the following grammar:
|
108
|
149 |
|
107
|
150 |
\[ r ::= \ZERO \mid \ONE
|
|
151 |
\mid c
|
|
152 |
\mid r_1 \cdot r_2
|
|
153 |
\mid r_1 + r_2
|
|
154 |
\mid r^*
|
|
155 |
\]
|
|
156 |
|
|
157 |
\noindent
|
108
|
158 |
The ingenious contribution of Brzozowski is the notion of \emph{derivatives} of
|
|
159 |
regular expressions, written~$\_ \backslash \_$. It uses the auxiliary notion of
|
|
160 |
$\nullable$ defined below.
|
107
|
161 |
|
|
162 |
\begin{center}
|
|
163 |
\begin{tabular}{lcl}
|
|
164 |
$\nullable(\ZERO)$ & $\dn$ & $\mathit{false}$ \\
|
|
165 |
$\nullable(\ONE)$ & $\dn$ & $\mathit{true}$ \\
|
|
166 |
$\nullable(c)$ & $\dn$ & $\mathit{false}$ \\
|
|
167 |
$\nullable(r_1 + r_2)$ & $\dn$ & $\nullable(r_1) \vee \nullable(r_2)$ \\
|
|
168 |
$\nullable(r_1\cdot r_2)$ & $\dn$ & $\nullable(r_1) \wedge \nullable(r_2)$ \\
|
|
169 |
$\nullable(r^*)$ & $\dn$ & $\mathit{true}$ \\
|
|
170 |
\end{tabular}
|
|
171 |
\end{center}
|
|
172 |
|
|
173 |
\begin{center}
|
|
174 |
\begin{tabular}{lcl}
|
|
175 |
$\ZERO \backslash c$ & $\dn$ & $\ZERO$\\
|
|
176 |
$\ONE \backslash c$ & $\dn$ & $\ZERO$\\
|
|
177 |
$d \backslash c$ & $\dn$ &
|
|
178 |
$\mathit{if} \;c = d\;\mathit{then}\;\ONE\;\mathit{else}\;\ZERO$\\
|
|
179 |
$(r_1 + r_2)\backslash c$ & $\dn$ & $r_1 \backslash c \,+\, r_2 \backslash c$\\
|
|
180 |
$(r_1 \cdot r_2)\backslash c$ & $\dn$ & $\mathit{if} \, nullable(r_1)$\\
|
|
181 |
& & $\mathit{then}\;(r_1\backslash c) \cdot r_2 \,+\, r_2\backslash c$\\
|
|
182 |
& & $\mathit{else}\;(r_1\backslash c) \cdot r_2$\\
|
|
183 |
$(r^*)\backslash c$ & $\dn$ & $(r\backslash c) \cdot r^*$\\
|
|
184 |
\end{tabular}
|
|
185 |
\end{center}
|
130
|
186 |
\noindent
|
|
187 |
And defines how a regular expression evolves into
|
|
188 |
a new regular expression after all the string it contains
|
|
189 |
is chopped off a certain head character $c$.
|
107
|
190 |
|
|
191 |
The main property of the derivative operation is that
|
|
192 |
|
|
193 |
\begin{center}
|
|
194 |
$c\!::\!s \in L(r)$ holds
|
|
195 |
if and only if $s \in L(r\backslash c)$.
|
|
196 |
\end{center}
|
|
197 |
|
|
198 |
\noindent
|
108
|
199 |
We can generalise the derivative operation shown above for single characters
|
|
200 |
to strings as follows:
|
107
|
201 |
|
|
202 |
\begin{center}
|
|
203 |
\begin{tabular}{lcl}
|
|
204 |
$r \backslash (c\!::\!s) $ & $\dn$ & $(r \backslash c) \backslash s$ \\
|
|
205 |
$r \backslash [\,] $ & $\dn$ & $r$
|
|
206 |
\end{tabular}
|
|
207 |
\end{center}
|
|
208 |
|
|
209 |
\noindent
|
108
|
210 |
and then define Brzozowski's regular-expression matching algorithm as:
|
|
211 |
|
107
|
212 |
\[
|
|
213 |
match\;s\;r \;\dn\; nullable(r\backslash s)
|
|
214 |
\]
|
|
215 |
|
|
216 |
\noindent
|
130
|
217 |
Assuming the a string is given as a sequence of characters, say $c_0c_1..c_n$,
|
108
|
218 |
this algorithm presented graphically is as follows:
|
|
219 |
|
107
|
220 |
\begin{equation}\label{graph:*}
|
|
221 |
\begin{tikzcd}
|
|
222 |
r_0 \arrow[r, "\backslash c_0"] & r_1 \arrow[r, "\backslash c_1"] & r_2 \arrow[r, dashed] & r_n \arrow[r,"\textit{nullable}?"] & \;\textrm{YES}/\textrm{NO}
|
|
223 |
\end{tikzcd}
|
|
224 |
\end{equation}
|
|
225 |
|
|
226 |
\noindent
|
|
227 |
where we start with a regular expression $r_0$, build successive
|
|
228 |
derivatives until we exhaust the string and then use \textit{nullable}
|
|
229 |
to test whether the result can match the empty string. It can be
|
|
230 |
relatively easily shown that this matcher is correct (that is given
|
|
231 |
an $s = c_0...c_{n-1}$ and an $r_0$, it generates YES if and only if $s \in L(r_0)$).
|
|
232 |
|
|
233 |
|
108
|
234 |
\subsection*{Values and the Lexing Algorithm by Sulzmann and Lu}
|
107
|
235 |
|
|
236 |
One limitation of Brzozowski's algorithm is that it only produces a
|
|
237 |
YES/NO answer for whether a string is being matched by a regular
|
|
238 |
expression. Sulzmann and Lu~\cite{Sulzmann2014} extended this algorithm
|
|
239 |
to allow generation of an actual matching, called a \emph{value} or
|
|
240 |
sometimes also \emph{lexical value}. These values and regular
|
|
241 |
expressions correspond to each other as illustrated in the following
|
|
242 |
table:
|
|
243 |
|
|
244 |
|
|
245 |
\begin{center}
|
|
246 |
\begin{tabular}{c@{\hspace{20mm}}c}
|
|
247 |
\begin{tabular}{@{}rrl@{}}
|
|
248 |
\multicolumn{3}{@{}l}{\textbf{Regular Expressions}}\medskip\\
|
|
249 |
$r$ & $::=$ & $\ZERO$\\
|
|
250 |
& $\mid$ & $\ONE$ \\
|
|
251 |
& $\mid$ & $c$ \\
|
|
252 |
& $\mid$ & $r_1 \cdot r_2$\\
|
|
253 |
& $\mid$ & $r_1 + r_2$ \\
|
|
254 |
\\
|
|
255 |
& $\mid$ & $r^*$ \\
|
|
256 |
\end{tabular}
|
|
257 |
&
|
|
258 |
\begin{tabular}{@{\hspace{0mm}}rrl@{}}
|
|
259 |
\multicolumn{3}{@{}l}{\textbf{Values}}\medskip\\
|
|
260 |
$v$ & $::=$ & \\
|
|
261 |
& & $\Empty$ \\
|
|
262 |
& $\mid$ & $\Char(c)$ \\
|
|
263 |
& $\mid$ & $\Seq\,v_1\, v_2$\\
|
|
264 |
& $\mid$ & $\Left(v)$ \\
|
|
265 |
& $\mid$ & $\Right(v)$ \\
|
|
266 |
& $\mid$ & $\Stars\,[v_1,\ldots\,v_n]$ \\
|
|
267 |
\end{tabular}
|
|
268 |
\end{tabular}
|
|
269 |
\end{center}
|
|
270 |
|
|
271 |
\noindent
|
|
272 |
The contribution of Sulzmann and Lu is an extension of Brzozowski's
|
|
273 |
algorithm by a second phase (the first phase being building successive
|
|
274 |
derivatives---see \eqref{graph:*}). In this second phase, a POSIX value
|
|
275 |
is generated in case the regular expression matches the string.
|
|
276 |
Pictorially, the Sulzmann and Lu algorithm is as follows:
|
|
277 |
|
|
278 |
\begin{ceqn}
|
|
279 |
\begin{equation}\label{graph:2}
|
|
280 |
\begin{tikzcd}
|
|
281 |
r_0 \arrow[r, "\backslash c_0"] \arrow[d] & r_1 \arrow[r, "\backslash c_1"] \arrow[d] & r_2 \arrow[r, dashed] \arrow[d] & r_n \arrow[d, "mkeps" description] \\
|
|
282 |
v_0 & v_1 \arrow[l,"inj_{r_0} c_0"] & v_2 \arrow[l, "inj_{r_1} c_1"] & v_n \arrow[l, dashed]
|
|
283 |
\end{tikzcd}
|
|
284 |
\end{equation}
|
|
285 |
\end{ceqn}
|
|
286 |
|
|
287 |
\noindent
|
|
288 |
For convenience, we shall employ the following notations: the regular
|
|
289 |
expression we start with is $r_0$, and the given string $s$ is composed
|
|
290 |
of characters $c_0 c_1 \ldots c_{n-1}$. In the first phase from the
|
|
291 |
left to right, we build the derivatives $r_1$, $r_2$, \ldots according
|
|
292 |
to the characters $c_0$, $c_1$ until we exhaust the string and obtain
|
|
293 |
the derivative $r_n$. We test whether this derivative is
|
|
294 |
$\textit{nullable}$ or not. If not, we know the string does not match
|
|
295 |
$r$ and no value needs to be generated. If yes, we start building the
|
|
296 |
values incrementally by \emph{injecting} back the characters into the
|
|
297 |
earlier values $v_n, \ldots, v_0$. This is the second phase of the
|
|
298 |
algorithm from the right to left. For the first value $v_n$, we call the
|
|
299 |
function $\textit{mkeps}$, which builds the lexical value
|
|
300 |
for how the empty string has been matched by the (nullable) regular
|
|
301 |
expression $r_n$. This function is defined as
|
|
302 |
|
|
303 |
\begin{center}
|
|
304 |
\begin{tabular}{lcl}
|
|
305 |
$\mkeps(\ONE)$ & $\dn$ & $\Empty$ \\
|
|
306 |
$\mkeps(r_{1}+r_{2})$ & $\dn$
|
|
307 |
& \textit{if} $\nullable(r_{1})$\\
|
|
308 |
& & \textit{then} $\Left(\mkeps(r_{1}))$\\
|
|
309 |
& & \textit{else} $\Right(\mkeps(r_{2}))$\\
|
|
310 |
$\mkeps(r_1\cdot r_2)$ & $\dn$ & $\Seq\,(\mkeps\,r_1)\,(\mkeps\,r_2)$\\
|
|
311 |
$mkeps(r^*)$ & $\dn$ & $\Stars\,[]$
|
|
312 |
\end{tabular}
|
|
313 |
\end{center}
|
|
314 |
|
|
315 |
|
|
316 |
\noindent
|
|
317 |
After the $\mkeps$-call, we inject back the characters one by one in order to build
|
|
318 |
the lexical value $v_i$ for how the regex $r_i$ matches the string $s_i$
|
|
319 |
($s_i = c_i \ldots c_{n-1}$ ) from the previous lexical value $v_{i+1}$.
|
|
320 |
After injecting back $n$ characters, we get the lexical value for how $r_0$
|
|
321 |
matches $s$. For this Sulzmann and Lu defined a function that reverses
|
|
322 |
the ``chopping off'' of characters during the derivative phase. The
|
|
323 |
corresponding function is called \emph{injection}, written
|
|
324 |
$\textit{inj}$; it takes three arguments: the first one is a regular
|
|
325 |
expression ${r_{i-1}}$, before the character is chopped off, the second
|
|
326 |
is a character ${c_{i-1}}$, the character we want to inject and the
|
|
327 |
third argument is the value ${v_i}$, into which one wants to inject the
|
|
328 |
character (it corresponds to the regular expression after the character
|
|
329 |
has been chopped off). The result of this function is a new value. The
|
|
330 |
definition of $\textit{inj}$ is as follows:
|
|
331 |
|
|
332 |
\begin{center}
|
|
333 |
\begin{tabular}{l@{\hspace{1mm}}c@{\hspace{1mm}}l}
|
|
334 |
$\textit{inj}\,(c)\,c\,Empty$ & $\dn$ & $Char\,c$\\
|
|
335 |
$\textit{inj}\,(r_1 + r_2)\,c\,\Left(v)$ & $\dn$ & $\Left(\textit{inj}\,r_1\,c\,v)$\\
|
|
336 |
$\textit{inj}\,(r_1 + r_2)\,c\,Right(v)$ & $\dn$ & $Right(\textit{inj}\,r_2\,c\,v)$\\
|
|
337 |
$\textit{inj}\,(r_1 \cdot r_2)\,c\,Seq(v_1,v_2)$ & $\dn$ & $Seq(\textit{inj}\,r_1\,c\,v_1,v_2)$\\
|
|
338 |
$\textit{inj}\,(r_1 \cdot r_2)\,c\,\Left(Seq(v_1,v_2))$ & $\dn$ & $Seq(\textit{inj}\,r_1\,c\,v_1,v_2)$\\
|
|
339 |
$\textit{inj}\,(r_1 \cdot r_2)\,c\,Right(v)$ & $\dn$ & $Seq(\textit{mkeps}(r_1),\textit{inj}\,r_2\,c\,v)$\\
|
|
340 |
$\textit{inj}\,(r^*)\,c\,Seq(v,Stars\,vs)$ & $\dn$ & $Stars((\textit{inj}\,r\,c\,v)\,::\,vs)$\\
|
|
341 |
\end{tabular}
|
|
342 |
\end{center}
|
|
343 |
|
|
344 |
\noindent This definition is by recursion on the ``shape'' of regular
|
|
345 |
expressions and values.
|
|
346 |
|
|
347 |
|
108
|
348 |
\subsection*{Simplification of Regular Expressions}
|
107
|
349 |
|
|
350 |
The main drawback of building successive derivatives according
|
|
351 |
to Brzozowski's definition is that they can grow very quickly in size.
|
|
352 |
This is mainly due to the fact that the derivative operation generates
|
|
353 |
often ``useless'' $\ZERO$s and $\ONE$s in derivatives. As a result, if
|
|
354 |
implemented naively both algorithms by Brzozowski and by Sulzmann and Lu
|
|
355 |
are excruciatingly slow. For example when starting with the regular
|
|
356 |
expression $(a + aa)^*$ and building 12 successive derivatives
|
|
357 |
w.r.t.~the character $a$, one obtains a derivative regular expression
|
|
358 |
with more than 8000 nodes (when viewed as a tree). Operations like
|
|
359 |
$\textit{der}$ and $\nullable$ need to traverse such trees and
|
|
360 |
consequently the bigger the size of the derivative the slower the
|
|
361 |
algorithm.
|
|
362 |
|
|
363 |
Fortunately, one can simplify regular expressions after each derivative
|
|
364 |
step. Various simplifications of regular expressions are possible, such
|
|
365 |
as the simplification of $\ZERO + r$, $r + \ZERO$, $\ONE\cdot r$, $r
|
|
366 |
\cdot \ONE$, and $r + r$ to just $r$. These simplifications do not
|
|
367 |
affect the answer for whether a regular expression matches a string or
|
|
368 |
not, but fortunately also do not affect the POSIX strategy of how
|
|
369 |
regular expressions match strings---although the latter is much harder
|
|
370 |
to establish. Some initial results in this regard have been
|
|
371 |
obtained in \cite{AusafDyckhoffUrban2016}.
|
|
372 |
|
|
373 |
If we want the size of derivatives in Sulzmann and Lu's algorithm to
|
|
374 |
stay below this bound, we would need more aggressive simplifications.
|
|
375 |
Essentially we need to delete useless $\ZERO$s and $\ONE$s, as well as
|
|
376 |
deleting duplicates whenever possible. For example, the parentheses in
|
108
|
377 |
$(a+b) \cdot c + b\cdot c$ can be opened up to get $a\cdot c + b \cdot c + b
|
107
|
378 |
\cdot c$, and then simplified to just $a \cdot c + b \cdot c$. Another
|
|
379 |
example is simplifying $(a^*+a) + (a^*+ \ONE) + (a +\ONE)$ to just
|
108
|
380 |
$a^*+a+\ONE$. Adding these more aggressive simplification rules help us
|
107
|
381 |
to achieve the same size bound as that of the partial derivatives.
|
|
382 |
|
130
|
383 |
|
|
384 |
Suppose we apply simplification after each derivative step, and view
|
|
385 |
these two operations as an atomic one: $a \backslash_{simp}\,c \dn
|
|
386 |
\textit{simp}(a \backslash c)$. Then we can use the previous natural
|
|
387 |
extension from derivative w.r.t.~character to derivative
|
|
388 |
w.r.t.~string:%\comment{simp in the [] case?}
|
|
389 |
|
|
390 |
\begin{center}
|
|
391 |
\begin{tabular}{lcl}
|
|
392 |
$r \backslash_{simp} (c\!::\!s) $ & $\dn$ & $(r \backslash_{simp}\, c) \backslash_{simp}\, s$ \\
|
|
393 |
$r \backslash_{simp} [\,] $ & $\dn$ & $r$
|
|
394 |
\end{tabular}
|
|
395 |
\end{center}
|
|
396 |
|
|
397 |
\noindent
|
|
398 |
we obtain an optimised version of the algorithm:
|
|
399 |
|
|
400 |
\begin{center}
|
|
401 |
\begin{tabular}{lcl}
|
|
402 |
$\textit{blexer\_simp}\;r\,s$ & $\dn$ &
|
|
403 |
$\textit{let}\;a = (r^\uparrow)\backslash_{simp}\, s\;\textit{in}$\\
|
|
404 |
& & $\;\;\textit{if}\; \textit{bnullable}(a)$\\
|
|
405 |
& & $\;\;\textit{then}\;\textit{decode}\,(\textit{bmkeps}\,a)\,r$\\
|
|
406 |
& & $\;\;\textit{else}\;\textit{None}$
|
|
407 |
\end{tabular}
|
|
408 |
\end{center}
|
|
409 |
|
|
410 |
\noindent
|
|
411 |
This algorithm keeps the regular expression size small, for example,
|
|
412 |
with this simplification our previous $(a + aa)^*$ example's 8000 nodes
|
|
413 |
will be reduced to just 6 and stays constant, no matter how long the
|
|
414 |
input string is.
|
|
415 |
|
|
416 |
|
107
|
417 |
In order to implement the idea of ``spilling out alternatives'' and to
|
108
|
418 |
make them compatible with the $\textit{inj}$-mechanism, we use
|
|
419 |
\emph{bitcodes}. They were first introduced by Sulzmann and Lu.
|
|
420 |
Here bits and bitcodes (lists of bits) are defined as:
|
107
|
421 |
|
|
422 |
\begin{center}
|
114
|
423 |
$b ::= 1 \mid 0 \qquad
|
130
|
424 |
bs ::= [] \mid b::bs
|
107
|
425 |
$
|
|
426 |
\end{center}
|
|
427 |
|
|
428 |
\noindent
|
114
|
429 |
The $1$ and $0$ are not in bold in order to avoid
|
107
|
430 |
confusion with the regular expressions $\ZERO$ and $\ONE$. Bitcodes (or
|
130
|
431 |
bit-lists) can be used to encode values (or potentially incomplete values) in a
|
107
|
432 |
compact form. This can be straightforwardly seen in the following
|
|
433 |
coding function from values to bitcodes:
|
|
434 |
|
|
435 |
\begin{center}
|
|
436 |
\begin{tabular}{lcl}
|
|
437 |
$\textit{code}(\Empty)$ & $\dn$ & $[]$\\
|
|
438 |
$\textit{code}(\Char\,c)$ & $\dn$ & $[]$\\
|
114
|
439 |
$\textit{code}(\Left\,v)$ & $\dn$ & $0 :: code(v)$\\
|
|
440 |
$\textit{code}(\Right\,v)$ & $\dn$ & $1 :: code(v)$\\
|
107
|
441 |
$\textit{code}(\Seq\,v_1\,v_2)$ & $\dn$ & $code(v_1) \,@\, code(v_2)$\\
|
114
|
442 |
$\textit{code}(\Stars\,[])$ & $\dn$ & $[0]$\\
|
|
443 |
$\textit{code}(\Stars\,(v\!::\!vs))$ & $\dn$ & $1 :: code(v) \;@\;
|
107
|
444 |
code(\Stars\,vs)$
|
|
445 |
\end{tabular}
|
|
446 |
\end{center}
|
|
447 |
|
|
448 |
\noindent
|
|
449 |
Here $\textit{code}$ encodes a value into a bitcodes by converting
|
114
|
450 |
$\Left$ into $0$, $\Right$ into $1$, and marks the start of a non-empty
|
|
451 |
star iteration by $1$. The border where a local star terminates
|
|
452 |
is marked by $0$. This coding is lossy, as it throws away the information about
|
107
|
453 |
characters, and also does not encode the ``boundary'' between two
|
|
454 |
sequence values. Moreover, with only the bitcode we cannot even tell
|
114
|
455 |
whether the $1$s and $0$s are for $\Left/\Right$ or $\Stars$. The
|
107
|
456 |
reason for choosing this compact way of storing information is that the
|
|
457 |
relatively small size of bits can be easily manipulated and ``moved
|
|
458 |
around'' in a regular expression. In order to recover values, we will
|
|
459 |
need the corresponding regular expression as an extra information. This
|
|
460 |
means the decoding function is defined as:
|
|
461 |
|
|
462 |
|
|
463 |
%\begin{definition}[Bitdecoding of Values]\mbox{}
|
|
464 |
\begin{center}
|
|
465 |
\begin{tabular}{@{}l@{\hspace{1mm}}c@{\hspace{1mm}}l@{}}
|
|
466 |
$\textit{decode}'\,bs\,(\ONE)$ & $\dn$ & $(\Empty, bs)$\\
|
|
467 |
$\textit{decode}'\,bs\,(c)$ & $\dn$ & $(\Char\,c, bs)$\\
|
115
|
468 |
$\textit{decode}'\,(0\!::\!bs)\;(r_1 + r_2)$ & $\dn$ &
|
107
|
469 |
$\textit{let}\,(v, bs_1) = \textit{decode}'\,bs\,r_1\;\textit{in}\;
|
|
470 |
(\Left\,v, bs_1)$\\
|
115
|
471 |
$\textit{decode}'\,(1\!::\!bs)\;(r_1 + r_2)$ & $\dn$ &
|
107
|
472 |
$\textit{let}\,(v, bs_1) = \textit{decode}'\,bs\,r_2\;\textit{in}\;
|
|
473 |
(\Right\,v, bs_1)$\\
|
|
474 |
$\textit{decode}'\,bs\;(r_1\cdot r_2)$ & $\dn$ &
|
|
475 |
$\textit{let}\,(v_1, bs_1) = \textit{decode}'\,bs\,r_1\;\textit{in}$\\
|
|
476 |
& & $\textit{let}\,(v_2, bs_2) = \textit{decode}'\,bs_1\,r_2$\\
|
|
477 |
& & \hspace{35mm}$\textit{in}\;(\Seq\,v_1\,v_2, bs_2)$\\
|
115
|
478 |
$\textit{decode}'\,(0\!::\!bs)\,(r^*)$ & $\dn$ & $(\Stars\,[], bs)$\\
|
|
479 |
$\textit{decode}'\,(1\!::\!bs)\,(r^*)$ & $\dn$ &
|
107
|
480 |
$\textit{let}\,(v, bs_1) = \textit{decode}'\,bs\,r\;\textit{in}$\\
|
|
481 |
& & $\textit{let}\,(\Stars\,vs, bs_2) = \textit{decode}'\,bs_1\,r^*$\\
|
|
482 |
& & \hspace{35mm}$\textit{in}\;(\Stars\,v\!::\!vs, bs_2)$\bigskip\\
|
|
483 |
|
|
484 |
$\textit{decode}\,bs\,r$ & $\dn$ &
|
|
485 |
$\textit{let}\,(v, bs') = \textit{decode}'\,bs\,r\;\textit{in}$\\
|
|
486 |
& & $\textit{if}\;bs' = []\;\textit{then}\;\textit{Some}\,v\;
|
|
487 |
\textit{else}\;\textit{None}$
|
|
488 |
\end{tabular}
|
|
489 |
\end{center}
|
|
490 |
%\end{definition}
|
|
491 |
|
|
492 |
Sulzmann and Lu's integrated the bitcodes into regular expressions to
|
|
493 |
create annotated regular expressions \cite{Sulzmann2014}.
|
|
494 |
\emph{Annotated regular expressions} are defined by the following
|
|
495 |
grammar:%\comment{ALTS should have an $as$ in the definitions, not just $a_1$ and $a_2$}
|
|
496 |
|
|
497 |
\begin{center}
|
|
498 |
\begin{tabular}{lcl}
|
115
|
499 |
$\textit{a}$ & $::=$ & $\ZERO$\\
|
|
500 |
& $\mid$ & $_{bs}\ONE$\\
|
|
501 |
& $\mid$ & $_{bs}{\bf c}$\\
|
|
502 |
& $\mid$ & $_{bs}\oplus\,as$\\
|
|
503 |
& $\mid$ & $_{bs}a_1\cdot a_2$\\
|
|
504 |
& $\mid$ & $_{bs}a^*$
|
107
|
505 |
\end{tabular}
|
|
506 |
\end{center}
|
|
507 |
%(in \textit{ALTS})
|
|
508 |
|
|
509 |
\noindent
|
|
510 |
where $bs$ stands for bitcodes, $a$ for $\bold{a}$nnotated regular
|
|
511 |
expressions and $as$ for a list of annotated regular expressions.
|
116
|
512 |
The alternative constructor($\oplus$) has been generalized to
|
107
|
513 |
accept a list of annotated regular expressions rather than just 2.
|
|
514 |
We will show that these bitcodes encode information about
|
|
515 |
the (POSIX) value that should be generated by the Sulzmann and Lu
|
|
516 |
algorithm.
|
|
517 |
|
|
518 |
|
|
519 |
To do lexing using annotated regular expressions, we shall first
|
|
520 |
transform the usual (un-annotated) regular expressions into annotated
|
|
521 |
regular expressions. This operation is called \emph{internalisation} and
|
|
522 |
defined as follows:
|
|
523 |
|
|
524 |
%\begin{definition}
|
|
525 |
\begin{center}
|
|
526 |
\begin{tabular}{lcl}
|
116
|
527 |
$(\ZERO)^\uparrow$ & $\dn$ & $\ZERO$\\
|
|
528 |
$(\ONE)^\uparrow$ & $\dn$ & $_{[]}\ONE$\\
|
|
529 |
$(c)^\uparrow$ & $\dn$ & $_{[]}{\bf c}$\\
|
107
|
530 |
$(r_1 + r_2)^\uparrow$ & $\dn$ &
|
116
|
531 |
$_{[]}\oplus[\textit{fuse}\,[0]\,r_1^\uparrow,\,
|
|
532 |
\textit{fuse}\,[1]\,r_2^\uparrow]$\\
|
107
|
533 |
$(r_1\cdot r_2)^\uparrow$ & $\dn$ &
|
116
|
534 |
$_{[]}r_1^\uparrow \cdot r_2^\uparrow$\\
|
107
|
535 |
$(r^*)^\uparrow$ & $\dn$ &
|
116
|
536 |
$_{[]}(r^\uparrow)^*$\\
|
107
|
537 |
\end{tabular}
|
|
538 |
\end{center}
|
|
539 |
%\end{definition}
|
|
540 |
|
|
541 |
\noindent
|
|
542 |
We use up arrows here to indicate that the basic un-annotated regular
|
|
543 |
expressions are ``lifted up'' into something slightly more complex. In the
|
|
544 |
fourth clause, $\textit{fuse}$ is an auxiliary function that helps to
|
|
545 |
attach bits to the front of an annotated regular expression. Its
|
|
546 |
definition is as follows:
|
|
547 |
|
|
548 |
\begin{center}
|
|
549 |
\begin{tabular}{lcl}
|
117
|
550 |
$\textit{fuse}\;bs \; \ZERO$ & $\dn$ & $\ZERO$\\
|
|
551 |
$\textit{fuse}\;bs\; _{bs'}\ONE$ & $\dn$ &
|
|
552 |
$_{bs @ bs'}\ONE$\\
|
|
553 |
$\textit{fuse}\;bs\;_{bs'}{\bf c}$ & $\dn$ &
|
|
554 |
$_{bs@bs'}{\bf c}$\\
|
|
555 |
$\textit{fuse}\;bs\,_{bs'}\oplus\textit{as}$ & $\dn$ &
|
|
556 |
$_{bs@bs'}\oplus\textit{as}$\\
|
|
557 |
$\textit{fuse}\;bs\; _{bs'}a_1\cdot a_2$ & $\dn$ &
|
|
558 |
$_{bs@bs'}a_1 \cdot a_2$\\
|
|
559 |
$\textit{fuse}\;bs\,_{bs'}a^*$ & $\dn$ &
|
|
560 |
$_{bs @ bs'}a^*$
|
107
|
561 |
\end{tabular}
|
|
562 |
\end{center}
|
|
563 |
|
|
564 |
\noindent
|
|
565 |
After internalising the regular expression, we perform successive
|
|
566 |
derivative operations on the annotated regular expressions. This
|
|
567 |
derivative operation is the same as what we had previously for the
|
|
568 |
basic regular expressions, except that we beed to take care of
|
|
569 |
the bitcodes:
|
|
570 |
|
109
|
571 |
|
|
572 |
\iffalse
|
107
|
573 |
%\begin{definition}{bder}
|
|
574 |
\begin{center}
|
|
575 |
\begin{tabular}{@{}lcl@{}}
|
|
576 |
$(\textit{ZERO})\,\backslash c$ & $\dn$ & $\textit{ZERO}$\\
|
|
577 |
$(\textit{ONE}\;bs)\,\backslash c$ & $\dn$ & $\textit{ZERO}$\\
|
|
578 |
$(\textit{CHAR}\;bs\,d)\,\backslash c$ & $\dn$ &
|
|
579 |
$\textit{if}\;c=d\; \;\textit{then}\;
|
|
580 |
\textit{ONE}\;bs\;\textit{else}\;\textit{ZERO}$\\
|
|
581 |
$(\textit{ALTS}\;bs\,as)\,\backslash c$ & $\dn$ &
|
|
582 |
$\textit{ALTS}\;bs\,(as.map(\backslash c))$\\
|
|
583 |
$(\textit{SEQ}\;bs\,a_1\,a_2)\,\backslash c$ & $\dn$ &
|
|
584 |
$\textit{if}\;\textit{bnullable}\,a_1$\\
|
|
585 |
& &$\textit{then}\;\textit{ALTS}\,bs\,List((\textit{SEQ}\,[]\,(a_1\,\backslash c)\,a_2),$\\
|
|
586 |
& &$\phantom{\textit{then}\;\textit{ALTS}\,bs\,}(\textit{fuse}\,(\textit{bmkeps}\,a_1)\,(a_2\,\backslash c)))$\\
|
|
587 |
& &$\textit{else}\;\textit{SEQ}\,bs\,(a_1\,\backslash c)\,a_2$\\
|
|
588 |
$(\textit{STAR}\,bs\,a)\,\backslash c$ & $\dn$ &
|
|
589 |
$\textit{SEQ}\;bs\,(\textit{fuse}\, [\Z] (r\,\backslash c))\,
|
|
590 |
(\textit{STAR}\,[]\,r)$
|
|
591 |
\end{tabular}
|
|
592 |
\end{center}
|
|
593 |
%\end{definition}
|
|
594 |
|
109
|
595 |
\begin{center}
|
|
596 |
\begin{tabular}{@{}lcl@{}}
|
|
597 |
$(\textit{ZERO})\,\backslash c$ & $\dn$ & $\textit{ZERO}$\\
|
|
598 |
$(_{bs}\textit{ONE})\,\backslash c$ & $\dn$ & $\textit{ZERO}$\\
|
|
599 |
$(_{bs}\textit{CHAR}\;d)\,\backslash c$ & $\dn$ &
|
|
600 |
$\textit{if}\;c=d\; \;\textit{then}\;
|
|
601 |
_{bs}\textit{ONE}\;\textit{else}\;\textit{ZERO}$\\
|
118
|
602 |
$(_{bs}\textit{ALTS}\;\textit{as})\,\backslash c$ & $\dn$ &
|
|
603 |
$_{bs}\textit{ALTS}\;(\textit{as}.\textit{map}(\backslash c))$\\
|
109
|
604 |
$(_{bs}\textit{SEQ}\;a_1\,a_2)\,\backslash c$ & $\dn$ &
|
|
605 |
$\textit{if}\;\textit{bnullable}\,a_1$\\
|
|
606 |
& &$\textit{then}\;_{bs}\textit{ALTS}\,List((_{[]}\textit{SEQ}\,(a_1\,\backslash c)\,a_2),$\\
|
|
607 |
& &$\phantom{\textit{then}\;_{bs}\textit{ALTS}\,}(\textit{fuse}\,(\textit{bmkeps}\,a_1)\,(a_2\,\backslash c)))$\\
|
|
608 |
& &$\textit{else}\;_{bs}\textit{SEQ}\,(a_1\,\backslash c)\,a_2$\\
|
|
609 |
$(_{bs}\textit{STAR}\,a)\,\backslash c$ & $\dn$ &
|
118
|
610 |
$_{bs}\textit{SEQ}\;(\textit{fuse}\, [0] \; r\,\backslash c )\,
|
109
|
611 |
(_{bs}\textit{STAR}\,[]\,r)$
|
|
612 |
\end{tabular}
|
|
613 |
\end{center}
|
|
614 |
%\end{definition}
|
|
615 |
\fi
|
|
616 |
|
|
617 |
\begin{center}
|
|
618 |
\begin{tabular}{@{}lcl@{}}
|
|
619 |
$(\ZERO)\,\backslash c$ & $\dn$ & $\ZERO$\\
|
|
620 |
$(_{bs}\ONE)\,\backslash c$ & $\dn$ & $\ZERO$\\
|
|
621 |
$(_{bs}{\bf d})\,\backslash c$ & $\dn$ &
|
|
622 |
$\textit{if}\;c=d\; \;\textit{then}\;
|
|
623 |
_{bs}\ONE\;\textit{else}\;\ZERO$\\
|
118
|
624 |
$(_{bs}\oplus \;\textit{as})\,\backslash c$ & $\dn$ &
|
|
625 |
$_{bs}\oplus\;(\textit{as.map}(\backslash c))$\\
|
109
|
626 |
$(_{bs}\;a_1\cdot a_2)\,\backslash c$ & $\dn$ &
|
|
627 |
$\textit{if}\;\textit{bnullable}\,a_1$\\
|
|
628 |
& &$\textit{then}\;_{bs}\oplus\,[(_{[]}\,(a_1\,\backslash c)\cdot\,a_2),$\\
|
|
629 |
& &$\phantom{\textit{then},\;_{bs}\oplus\,}(\textit{fuse}\,(\textit{bmkeps}\,a_1)\,(a_2\,\backslash c))]$\\
|
|
630 |
& &$\textit{else}\;_{bs}\,(a_1\,\backslash c)\cdot a_2$\\
|
|
631 |
$(_{bs}a^*)\,\backslash c$ & $\dn$ &
|
119
|
632 |
$_{bs}(\textit{fuse}\, [0] \; r\,\backslash c)\cdot
|
109
|
633 |
(_{[]}r^*))$
|
|
634 |
\end{tabular}
|
|
635 |
\end{center}
|
|
636 |
|
|
637 |
%\end{definition}
|
107
|
638 |
\noindent
|
119
|
639 |
For instance, when we do derivative of $_{bs}a^*$ with respect to c,
|
|
640 |
we need to unfold it into a sequence,
|
|
641 |
and attach an additional bit $0$ to the front of $r \backslash c$
|
118
|
642 |
to indicate that there is one more star iteration. Also the sequence clause
|
107
|
643 |
is more subtle---when $a_1$ is $\textit{bnullable}$ (here
|
|
644 |
\textit{bnullable} is exactly the same as $\textit{nullable}$, except
|
|
645 |
that it is for annotated regular expressions, therefore we omit the
|
118
|
646 |
definition). Assume that $\textit{bmkeps}$ correctly extracts the bitcode for how
|
107
|
647 |
$a_1$ matches the string prior to character $c$ (more on this later),
|
118
|
648 |
then the right branch of alternative, which is $\textit{fuse} \; \bmkeps \; a_1 (a_2
|
107
|
649 |
\backslash c)$ will collapse the regular expression $a_1$(as it has
|
|
650 |
already been fully matched) and store the parsing information at the
|
|
651 |
head of the regular expression $a_2 \backslash c$ by fusing to it. The
|
118
|
652 |
bitsequence $\textit{bs}$, which was initially attached to the
|
|
653 |
first element of the sequence $a_1 \cdot a_2$, has
|
|
654 |
now been elevated to the top-level of $\oplus$, as this information will be
|
|
655 |
needed whichever way the sequence is matched---no matter whether $c$ belongs
|
107
|
656 |
to $a_1$ or $ a_2$. After building these derivatives and maintaining all
|
|
657 |
the lexing information, we complete the lexing by collecting the
|
|
658 |
bitcodes using a generalised version of the $\textit{mkeps}$ function
|
|
659 |
for annotated regular expressions, called $\textit{bmkeps}$:
|
|
660 |
|
|
661 |
|
|
662 |
%\begin{definition}[\textit{bmkeps}]\mbox{}
|
|
663 |
\begin{center}
|
|
664 |
\begin{tabular}{lcl}
|
119
|
665 |
$\textit{bmkeps}\,(_{bs}\ONE)$ & $\dn$ & $bs$\\
|
|
666 |
$\textit{bmkeps}\,(_{bs}\oplus a::\textit{as})$ & $\dn$ &
|
107
|
667 |
$\textit{if}\;\textit{bnullable}\,a$\\
|
|
668 |
& &$\textit{then}\;bs\,@\,\textit{bmkeps}\,a$\\
|
121
|
669 |
& &$\textit{else}\;bs\,@\,\textit{bmkeps}\,(_{bs}\oplus \textit{as})$\\
|
120
|
670 |
$\textit{bmkeps}\,(_{bs} a_1 \cdot a_2)$ & $\dn$ &
|
107
|
671 |
$bs \,@\,\textit{bmkeps}\,a_1\,@\, \textit{bmkeps}\,a_2$\\
|
119
|
672 |
$\textit{bmkeps}\,(_{bs}a^*)$ & $\dn$ &
|
121
|
673 |
$bs \,@\, [0]$
|
107
|
674 |
\end{tabular}
|
|
675 |
\end{center}
|
|
676 |
%\end{definition}
|
|
677 |
|
|
678 |
\noindent
|
|
679 |
This function completes the value information by travelling along the
|
|
680 |
path of the regular expression that corresponds to a POSIX value and
|
|
681 |
collecting all the bitcodes, and using $S$ to indicate the end of star
|
|
682 |
iterations. If we take the bitcodes produced by $\textit{bmkeps}$ and
|
|
683 |
decode them, we get the value we expect. The corresponding lexing
|
|
684 |
algorithm looks as follows:
|
|
685 |
|
|
686 |
\begin{center}
|
|
687 |
\begin{tabular}{lcl}
|
|
688 |
$\textit{blexer}\;r\,s$ & $\dn$ &
|
|
689 |
$\textit{let}\;a = (r^\uparrow)\backslash s\;\textit{in}$\\
|
|
690 |
& & $\;\;\textit{if}\; \textit{bnullable}(a)$\\
|
|
691 |
& & $\;\;\textit{then}\;\textit{decode}\,(\textit{bmkeps}\,a)\,r$\\
|
|
692 |
& & $\;\;\textit{else}\;\textit{None}$
|
|
693 |
\end{tabular}
|
|
694 |
\end{center}
|
|
695 |
|
|
696 |
\noindent
|
|
697 |
In this definition $\_\backslash s$ is the generalisation of the derivative
|
|
698 |
operation from characters to strings (just like the derivatives for un-annotated
|
|
699 |
regular expressions).
|
|
700 |
|
108
|
701 |
|
|
702 |
\subsection*{Our Simplification Rules}
|
|
703 |
|
107
|
704 |
The main point of the bitcodes and annotated regular expressions is that
|
|
705 |
we can apply rather aggressive (in terms of size) simplification rules
|
|
706 |
in order to keep derivatives small. We have developed such
|
|
707 |
``aggressive'' simplification rules and generated test data that show
|
|
708 |
that the expected bound can be achieved. Obviously we could only
|
|
709 |
partially cover the search space as there are infinitely many regular
|
|
710 |
expressions and strings.
|
|
711 |
|
|
712 |
One modification we introduced is to allow a list of annotated regular
|
121
|
713 |
expressions in the $\oplus$ constructor. This allows us to not just
|
107
|
714 |
delete unnecessary $\ZERO$s and $\ONE$s from regular expressions, but
|
|
715 |
also unnecessary ``copies'' of regular expressions (very similar to
|
|
716 |
simplifying $r + r$ to just $r$, but in a more general setting). Another
|
|
717 |
modification is that we use simplification rules inspired by Antimirov's
|
|
718 |
work on partial derivatives. They maintain the idea that only the first
|
|
719 |
``copy'' of a regular expression in an alternative contributes to the
|
|
720 |
calculation of a POSIX value. All subsequent copies can be pruned away from
|
|
721 |
the regular expression. A recursive definition of our simplification function
|
|
722 |
that looks somewhat similar to our Scala code is given below:
|
|
723 |
%\comment{Use $\ZERO$, $\ONE$ and so on.
|
|
724 |
%Is it $ALTS$ or $ALTS$?}\\
|
|
725 |
|
|
726 |
\begin{center}
|
|
727 |
\begin{tabular}{@{}lcl@{}}
|
|
728 |
|
121
|
729 |
$\textit{simp} \; (_{bs}a_1\cdot a_2)$ & $\dn$ & $ (\textit{simp} \; a_1, \textit{simp} \; a_2) \; \textit{match} $ \\
|
107
|
730 |
&&$\quad\textit{case} \; (\ZERO, \_) \Rightarrow \ZERO$ \\
|
|
731 |
&&$\quad\textit{case} \; (\_, \ZERO) \Rightarrow \ZERO$ \\
|
|
732 |
&&$\quad\textit{case} \; (\ONE, a_2') \Rightarrow \textit{fuse} \; bs \; a_2'$ \\
|
|
733 |
&&$\quad\textit{case} \; (a_1', \ONE) \Rightarrow \textit{fuse} \; bs \; a_1'$ \\
|
121
|
734 |
&&$\quad\textit{case} \; (a_1', a_2') \Rightarrow _{bs}a_1' \cdot a_2'$ \\
|
107
|
735 |
|
121
|
736 |
$\textit{simp} \; (_{bs}\oplus \textit{as})$ & $\dn$ & $\textit{distinct}( \textit{flatten} ( \textit{map simp as})) \; \textit{match} $ \\
|
107
|
737 |
&&$\quad\textit{case} \; [] \Rightarrow \ZERO$ \\
|
|
738 |
&&$\quad\textit{case} \; a :: [] \Rightarrow \textit{fuse bs a}$ \\
|
121
|
739 |
&&$\quad\textit{case} \; as' \Rightarrow _{bs}\oplus \textit{as'}$\\
|
107
|
740 |
|
|
741 |
$\textit{simp} \; a$ & $\dn$ & $\textit{a} \qquad \textit{otherwise}$
|
|
742 |
\end{tabular}
|
|
743 |
\end{center}
|
|
744 |
|
|
745 |
\noindent
|
|
746 |
The simplification does a pattern matching on the regular expression.
|
|
747 |
When it detected that the regular expression is an alternative or
|
|
748 |
sequence, it will try to simplify its children regular expressions
|
|
749 |
recursively and then see if one of the children turn into $\ZERO$ or
|
|
750 |
$\ONE$, which might trigger further simplification at the current level.
|
121
|
751 |
The most involved part is the $\oplus$ clause, where we use two
|
107
|
752 |
auxiliary functions $\textit{flatten}$ and $\textit{distinct}$ to open up nested
|
121
|
753 |
alternatives and reduce as many duplicates as possible. Function
|
107
|
754 |
$\textit{distinct}$ keeps the first occurring copy only and remove all later ones
|
121
|
755 |
when detected duplicates. Function $\textit{flatten}$ opens up nested $\oplus$s.
|
107
|
756 |
Its recursive definition is given below:
|
|
757 |
|
|
758 |
\begin{center}
|
|
759 |
\begin{tabular}{@{}lcl@{}}
|
121
|
760 |
$\textit{flatten} \; (_{bs}\oplus \textit{as}) :: \textit{as'}$ & $\dn$ & $(\textit{map} \;
|
107
|
761 |
(\textit{fuse}\;bs)\; \textit{as}) \; @ \; \textit{flatten} \; as' $ \\
|
121
|
762 |
$\textit{flatten} \; \ZERO :: as'$ & $\dn$ & $ \textit{flatten} \; \textit{as'} $ \\
|
|
763 |
$\textit{flatten} \; a :: as'$ & $\dn$ & $a :: \textit{flatten} \; \textit{as'}$ \quad(otherwise)
|
107
|
764 |
\end{tabular}
|
|
765 |
\end{center}
|
|
766 |
|
|
767 |
\noindent
|
|
768 |
Here $\textit{flatten}$ behaves like the traditional functional programming flatten
|
|
769 |
function, except that it also removes $\ZERO$s. Or in terms of regular expressions, it
|
|
770 |
removes parentheses, for example changing $a+(b+c)$ into $a+b+c$.
|
|
771 |
|
|
772 |
|
|
773 |
|
|
774 |
|
126
|
775 |
\section{Current Work and Progress}
|
105
|
776 |
For reasons beyond this report, it turns out that a complete set of
|
|
777 |
simplification rules depends on values being encoded as
|
|
778 |
bitsequences.\footnote{Values are the results the lexing algorithms
|
|
779 |
generate; they encode how a regular expression matched a string.} We
|
|
780 |
already know that the lexing algorithm using bitsequences but
|
|
781 |
\emph{without} simplification is correct, albeilt horribly
|
106
|
782 |
slow. Therefore in the past 6 months I was trying to prove that the
|
105
|
783 |
algorithm using bitsequences plus our simplification rules is
|
106
|
784 |
also correct. Formally this amounts to show that
|
100
|
785 |
|
|
786 |
\begin{equation}\label{mainthm}
|
|
787 |
\blexers \; r \; s = \blexer \;r\;s
|
|
788 |
\end{equation}
|
|
789 |
|
94
|
790 |
\noindent
|
105
|
791 |
whereby $\blexers$ simplifies (makes derivatives smaller) in each
|
|
792 |
step, whereas with $\blexer$ the size can grow exponentially. This
|
106
|
793 |
would be an important milestone for my thesis, because we already
|
105
|
794 |
have a very good idea how to establish that our set our simplification
|
|
795 |
rules keeps the size of derivativs below a relatively tight bound.
|
100
|
796 |
|
106
|
797 |
In order to prove the main theorem in \eqref{mainthm}, we need to prove that the
|
|
798 |
two functions produce the same output. The definition of these two functions
|
100
|
799 |
is shown below.
|
|
800 |
|
94
|
801 |
\begin{center}
|
|
802 |
\begin{tabular}{lcl}
|
|
803 |
$\textit{blexer}\;r\,s$ & $\dn$ &
|
|
804 |
$\textit{let}\;a = (r^\uparrow)\backslash s\;\textit{in}$\\
|
|
805 |
& & $\;\;\textit{if}\; \textit{bnullable}(a)$\\
|
|
806 |
& & $\;\;\textit{then}\;\textit{decode}\,(\textit{bmkeps}\,a)\,r$\\
|
|
807 |
& & $\;\;\textit{else}\;\textit{None}$
|
|
808 |
\end{tabular}
|
|
809 |
\end{center}
|
|
810 |
|
100
|
811 |
\begin{center}
|
94
|
812 |
\begin{tabular}{lcl}
|
100
|
813 |
$\blexers \; r \, s$ &$\dn$ &
|
|
814 |
$\textit{let} \; a = (r^\uparrow)\backslash_{simp}\, s\; \textit{in}$\\
|
|
815 |
& & $\; \; \textit{if} \; \textit{bnullable}(a)$\\
|
|
816 |
& & $\; \; \textit{then} \; \textit{decode}\,(\textit{bmkeps}\,a)\,r$\\
|
|
817 |
& & $\;\; \textit{else}\;\textit{None}$
|
94
|
818 |
\end{tabular}
|
|
819 |
\end{center}
|
|
820 |
\noindent
|
105
|
821 |
In these definitions $(r^\uparrow)$ is a kind of coding function that
|
|
822 |
is the same in each case, similarly the decode and the \textit{bmkeps}
|
106
|
823 |
are functions that are the same in each case. Our main
|
|
824 |
theorem~\eqref{mainthm} therefore boils down to proving the following
|
|
825 |
two propositions (depending on which branch the if-else clause
|
|
826 |
takes). They establish how the derivatives \emph{with} simplification
|
|
827 |
do not change the computed result:
|
94
|
828 |
|
|
829 |
\begin{itemize}
|
105
|
830 |
\item{(a)} If a string $s$ is in the language of $L(r)$, then \\
|
100
|
831 |
$\textit{bmkeps} (r^\uparrow)\backslash_{simp}\,s = \textit{bmkeps} (r^\uparrow)\backslash s$,\\
|
105
|
832 |
\item{(b)} If a string $s$ is in the language $L(r)$, then
|
100
|
833 |
$\rup \backslash_{simp} \,s$ is not nullable.
|
94
|
834 |
\end{itemize}
|
100
|
835 |
|
94
|
836 |
\noindent
|
106
|
837 |
We have already proved the second part in Isabelle. This is actually
|
105
|
838 |
not too difficult because we can show that simplification does not
|
|
839 |
change the language of simplified regular expressions.
|
100
|
840 |
|
105
|
841 |
If we can prove the first part, that is the bitsequence algorithm with
|
|
842 |
simplification produces the same result as the one without
|
|
843 |
simplification, then we are done. Unfortunately that part requires
|
|
844 |
more effort, because simplification does not only need to \emph{not}
|
|
845 |
change the language, but also not change the value (that is the
|
|
846 |
computed result).
|
100
|
847 |
|
105
|
848 |
%\bigskip\noindent\rule[1.5ex]{\linewidth}{5pt}
|
|
849 |
%Do you want to keep this? You essentially want to say that the old
|
|
850 |
%method used retrieve, which unfortunately cannot be adopted to
|
|
851 |
%the simplification rules. You could just say that and give an example.
|
|
852 |
%However you have to think about how you give the example....nobody knows
|
|
853 |
%about AZERO etc yet. Maybe it might be better to use normal regexes
|
|
854 |
%like $a + aa$, but annotate bitsequences as subscript like $_1(_0a + _1aa)$.
|
104
|
855 |
|
105
|
856 |
%\bigskip\noindent\rule[1.5ex]{\linewidth}{5pt}
|
|
857 |
%REPLY:\\
|
|
858 |
%Yes, I am essentially saying that the old method
|
|
859 |
%cannot be adopted without adjustments.
|
|
860 |
%But this does not mean we should skip
|
|
861 |
%the proof of the bit-coded algorithm
|
|
862 |
%as it is still the main direction we are looking into
|
|
863 |
%to prove things. We are trying to modify
|
|
864 |
%the old proof to suit our needs, but not give
|
|
865 |
%up it totally, that is why i believe the old
|
|
866 |
%proof is fundamental in understanding
|
|
867 |
%what we are doing in the past 6 months.
|
|
868 |
%\bigskip\noindent\rule[1.5ex]{\linewidth}{5pt}
|
100
|
869 |
|
106
|
870 |
\subsubsection*{Existing Proof}
|
100
|
871 |
|
104
|
872 |
For this we have started with looking at the original proof that
|
105
|
873 |
established that the bitsequence algorrithm produces the same result
|
|
874 |
as the algorithm not using bitsequences. Formally this proof
|
|
875 |
established
|
100
|
876 |
|
105
|
877 |
\begin{equation}\label{lexer}
|
|
878 |
\blexer \; (r^\uparrow) s = \lexer \;r \;s
|
|
879 |
\end{equation}
|
|
880 |
|
|
881 |
%\noindent
|
|
882 |
%might provide us insight into proving
|
|
883 |
%\begin{center}
|
|
884 |
%$\blexer \; r^\uparrow \;s = \blexers \; r^\uparrow \;s$
|
|
885 |
%\end{center}
|
104
|
886 |
|
94
|
887 |
\noindent
|
106
|
888 |
The proof uses two ``tricks''. One is that it uses a \flex-function
|
104
|
889 |
|
94
|
890 |
\begin{center}
|
|
891 |
\begin{tabular}{lcl}
|
|
892 |
$\textit{flex} \;r\; f\; (c\!::\!s) $ & $\dn$ & $\textit{flex} \; (r\backslash c) \;(\lambda v. f (inj \; r \; c \; v)) \;s$ \\
|
|
893 |
$\textit{flex} \;r\; f\; [\,] $ & $\dn$ & $f$
|
|
894 |
\end{tabular}
|
|
895 |
\end{center}
|
104
|
896 |
|
94
|
897 |
\noindent
|
106
|
898 |
and then proves for the right-hand side in \eqref{lexer}
|
104
|
899 |
|
|
900 |
\begin{center}
|
106
|
901 |
$\lexer \;r\; s = \flex \;\textit{id} \; r\;s \;(\mkeps \; (r\backslash s))$
|
104
|
902 |
\end{center}.
|
|
903 |
|
|
904 |
|
106
|
905 |
|
104
|
906 |
|
|
907 |
\noindent
|
|
908 |
The $\flex$-function essentially does lexing by
|
105
|
909 |
stacking up injection functions while doing derivatives.
|
|
910 |
|
94
|
911 |
explicitly showing the order of characters being
|
|
912 |
injected back in each step.
|
|
913 |
With $\flex$ we can write $\lexer$ this way:
|
106
|
914 |
|
94
|
915 |
\begin{center}
|
|
916 |
$\lexer \;r\; s = \flex \;id \; r\;s \;(\mkeps r\backslash s)$
|
|
917 |
\end{center}
|
106
|
918 |
|
|
919 |
%\noindent
|
|
920 |
%$\flex$ focuses on the injections instead of the derivatives ,
|
|
921 |
%compared to the original definition of $\lexer$, which puts equal
|
|
922 |
%amount of emphasis on injection and derivative with respect to each
|
|
923 |
%character:
|
|
924 |
|
|
925 |
%\begin{center}
|
|
926 |
%\begin{tabular}{lcl}
|
|
927 |
%$\textit{lexer} \; r\; (c\!::\!s) $ & $\dn$ & $\textit{case} \; \lexer \; (r\backslash c) \;s \; %\textit{of}$ \\
|
|
928 |
% & & $\textit{None} \; \Longrightarrow \; \textit{None}$\\
|
|
929 |
% & & $\textbar \; v \; \Longrightarrow \; \inj \; r\;c\;v$\\
|
|
930 |
%$\textit{lexer} \; r\; [\,] $ & $\dn$ & $\textit{if} \; \nullable (r) \; \textit{then} \; \mkeps% (r) \; \textit{else} \;None$
|
|
931 |
%\end{tabular}
|
|
932 |
%\end{center}
|
|
933 |
|
94
|
934 |
\noindent
|
106
|
935 |
The crux in the existing proof is how $\flex$ relates to injection, namely
|
|
936 |
|
94
|
937 |
\begin{center}
|
|
938 |
$\flex \; r \; id \; (s@[c]) \; v = \flex \; r \; id \; s \; (inj \; (r\backslash s) \; c\; v)$.
|
|
939 |
\end{center}
|
106
|
940 |
|
94
|
941 |
\noindent
|
106
|
942 |
This property allows one to rewrite an induction hypothesis like
|
|
943 |
|
94
|
944 |
\begin{center}
|
|
945 |
$ \flex \; r\; id\; (s@[c])\; v = \textit{decode} \;( \textit{retrieve}\; (\rup \backslash s) \; (\inj \; (r\backslash s) \;c\;v)\;) r$
|
|
946 |
\end{center}
|
106
|
947 |
|
107
|
948 |
|
|
949 |
\subsubsection{Retrieve Function}
|
|
950 |
The crucial point is to find the
|
|
951 |
$\textit{POSIX}$ information of a regular expression and how it is modified,
|
|
952 |
augmented and propagated
|
|
953 |
during simplification in parallel with the regular expression that
|
|
954 |
has not been simplified in the subsequent derivative operations. To aid this,
|
|
955 |
we use the helper function retrieve described by Sulzmann and Lu:
|
|
956 |
\begin{center}
|
|
957 |
\begin{tabular}{@{}l@{\hspace{2mm}}c@{\hspace{2mm}}l@{}}
|
110
|
958 |
$\textit{retrieve}\,(_{bs}\ONE)\,\Empty$ & $\dn$ & $bs$\\
|
|
959 |
$\textit{retrieve}\,(_{bs}{\bf c})\,(\Char\,d)$ & $\dn$ & $bs$\\
|
121
|
960 |
$\textit{retrieve}\,(_{bs}\oplus a::as)\,(\Left\,v)$ & $\dn$ &
|
107
|
961 |
$bs \,@\, \textit{retrieve}\,a\,v$\\
|
121
|
962 |
$\textit{retrieve}\,(_{bs}\oplus a::as)\,(\Right\,v)$ & $\dn$ &
|
|
963 |
$\textit{bs} \,@\, \textit{retrieve}\,(_{[]}\oplus as)\,v$\\
|
|
964 |
$\textit{retrieve}\,(_{bs}a_1\cdot a_2)\,(\Seq\,v_1\,v_2)$ & $\dn$ &
|
107
|
965 |
$bs \,@\,\textit{retrieve}\,a_1\,v_1\,@\, \textit{retrieve}\,a_2\,v_2$\\
|
121
|
966 |
$\textit{retrieve}\,(_{bs}a^*)\,(\Stars\,[])$ & $\dn$ &
|
|
967 |
$bs \,@\, [0]$\\
|
|
968 |
$\textit{retrieve}\,(_{bs}a^*)\,(\Stars\,(v\!::\!vs))$ & $\dn$ &\\
|
107
|
969 |
\multicolumn{3}{l}{
|
121
|
970 |
\hspace{3cm}$bs \,@\, [1] \,@\, \textit{retrieve}\,a\,v\,@\,
|
|
971 |
\textit{retrieve}\,(_{[]}a^*)\,(\Stars\,vs)$}\\
|
107
|
972 |
\end{tabular}
|
|
973 |
\end{center}
|
|
974 |
%\comment{Did not read further}\\
|
|
975 |
This function assembles the bitcode
|
|
976 |
%that corresponds to a lexical value for how
|
|
977 |
%the current derivative matches the suffix of the string(the characters that
|
|
978 |
%have not yet appeared, but will appear as the successive derivatives go on.
|
|
979 |
%How do we get this "future" information? By the value $v$, which is
|
|
980 |
%computed by a pass of the algorithm that uses
|
|
981 |
%$inj$ as described in the previous section).
|
|
982 |
using information from both the derivative regular expression and the
|
|
983 |
value. Sulzmann and Lu poroposed this function, but did not prove
|
|
984 |
anything about it. Ausaf and Urban used it to connect the bitcoded
|
|
985 |
algorithm to the older algorithm by the following equation:
|
|
986 |
|
|
987 |
\begin{center} $inj \;a\; c \; v = \textit{decode} \; (\textit{retrieve}\;
|
|
988 |
(r^\uparrow)\backslash_{simp} \,c)\,v)$
|
|
989 |
\end{center}
|
|
990 |
|
|
991 |
\noindent
|
|
992 |
whereby $r^\uparrow$ stands for the internalised version of $r$. Ausaf
|
|
993 |
and Urban also used this fact to prove the correctness of bitcoded
|
|
994 |
algorithm without simplification. Our purpose of using this, however,
|
|
995 |
is to establish
|
|
996 |
|
|
997 |
\begin{center}
|
|
998 |
$ \textit{retrieve} \;
|
|
999 |
a \; v \;=\; \textit{retrieve} \; (\textit{simp}\,a) \; v'.$
|
|
1000 |
\end{center}
|
|
1001 |
The idea is that using $v'$, a simplified version of $v$ that had gone
|
|
1002 |
through the same simplification step as $\textit{simp}(a)$, we are able
|
|
1003 |
to extract the bitcode that gives the same parsing information as the
|
|
1004 |
unsimplified one. However, we noticed that constructing such a $v'$
|
|
1005 |
from $v$ is not so straightforward. The point of this is that we might
|
|
1006 |
be able to finally bridge the gap by proving
|
|
1007 |
|
94
|
1008 |
\noindent
|
|
1009 |
By using a property of retrieve we have the $\textit{RHS}$ of the above equality is
|
|
1010 |
$decode (retrieve (r^\uparrow \backslash(s @ [c])) v) r$, and this gives the
|
|
1011 |
main lemma result:
|
106
|
1012 |
|
94
|
1013 |
\begin{center}
|
|
1014 |
$ \flex \;r\; id \; (s@[c]) \; v =\textit{decode}(\textit{retrieve} (\rup \backslash (s@[c])) \;v) r$
|
|
1015 |
\end{center}
|
106
|
1016 |
|
|
1017 |
|
|
1018 |
|
|
1019 |
|
94
|
1020 |
\noindent
|
|
1021 |
To use this lemma result for our
|
|
1022 |
correctness proof, simply replace the $v$ in the
|
|
1023 |
$\textit{RHS}$ of the above equality with
|
|
1024 |
$\mkeps\;(r\backslash (s@[c]))$, and apply the lemma that
|
|
1025 |
|
|
1026 |
\begin{center}
|
|
1027 |
$\textit{decode} \; \bmkeps \; \rup \; r = \textit{decode} \; (\textit{retrieve} \; \rup \; \mkeps(r)) \;r$
|
|
1028 |
\end{center}
|
|
1029 |
\noindent
|
|
1030 |
We get the correctness of our bit-coded algorithm:
|
|
1031 |
\begin{center}
|
|
1032 |
$\flex \;r\; id \; s \; (\mkeps \; r\backslash s) = \textit{decode} \; \bmkeps \; \rup\backslash s \; r$
|
|
1033 |
\end{center}
|
|
1034 |
\noindent
|
|
1035 |
The bridge between the above chain of equalities
|
|
1036 |
is the use of $\retrieve$,
|
|
1037 |
if we want to use a similar technique for the
|
|
1038 |
simplified version of algorithm,
|
|
1039 |
we face the problem that in the above
|
|
1040 |
equalities,
|
|
1041 |
$\retrieve \; a \; v$ is not always defined.
|
|
1042 |
for example,
|
100
|
1043 |
$\retrieve \; _0(_1a+_0a) \; \Left(\Empty)$
|
101
|
1044 |
is defined, but not $\retrieve \; (_{01}a) \;\Left(\Empty)$,
|
94
|
1045 |
though we can extract the same POSIX
|
|
1046 |
bits from the two annotated regular expressions.
|
95
|
1047 |
The latter might occur when we try to retrieve from
|
|
1048 |
a simplified regular expression using the same value
|
|
1049 |
as the unsimplified one.
|
|
1050 |
This is because $\Left(\Empty)$ corresponds to
|
101
|
1051 |
the regular expression structure $\ONE+r_2$ instead of
|
|
1052 |
$\ONE$.
|
94
|
1053 |
That means, if we
|
|
1054 |
want to prove that
|
|
1055 |
\begin{center}
|
|
1056 |
$\textit{decode} \; \bmkeps \; \rup\backslash s \; r = \textit{decode} \; \bmkeps \; \rup\backslash_{simp} s \; r$
|
|
1057 |
\end{center}
|
|
1058 |
\noindent
|
|
1059 |
holds by using $\retrieve$,
|
|
1060 |
we probably need to prove an equality like below:
|
|
1061 |
\begin{center}
|
|
1062 |
%$\retrieve \; \rup\backslash_{simp} s \; \mkeps(r\backslash_{simp} s)=\textit{retrieve} \; \rup\backslash s \; \mkeps(r\backslash s)$
|
101
|
1063 |
$\retrieve \; \rup\backslash_{simp} s \; \mkeps(f(r\backslash s))=\textit{retrieve} \; \rup\backslash s \; \mkeps(r\backslash s)$
|
94
|
1064 |
\end{center}
|
|
1065 |
\noindent
|
101
|
1066 |
$f$ rectifies $r\backslash s$ so the value $\mkeps(f(r\backslash s))$ becomes
|
|
1067 |
something simpler
|
94
|
1068 |
to make the retrieve function defined.\\
|
107
|
1069 |
\subsubsection{Ways to Rectify Value}
|
95
|
1070 |
One way to do this is to prove the following:
|
|
1071 |
\begin{center}
|
|
1072 |
$\retrieve \; \rup\backslash_{simp} s \; \mkeps(\simp(r\backslash s))=\textit{retrieve} \; \rup\backslash s \; \mkeps(r\backslash s)$
|
|
1073 |
\end{center}
|
|
1074 |
\noindent
|
101
|
1075 |
The reason why we choose $\simp$ as $f$ is because
|
|
1076 |
$\rup\backslash_{simp} \, s$ and $\simp(\rup\backslash \, s)$
|
|
1077 |
have the same shape:
|
|
1078 |
\begin{center}
|
|
1079 |
$\erase (\rup\backslash_{simp} \, s) = \erase(\simp(\rup\backslash s))$
|
|
1080 |
\end{center}
|
|
1081 |
|
|
1082 |
\noindent
|
|
1083 |
$\erase$ in the above equality means to remove the bit-codes
|
|
1084 |
in an annotated regular expression and only keep the original
|
|
1085 |
regular expression(just like "erasing" the bits). Its definition is omitted.
|
|
1086 |
$\rup\backslash_{simp} \, s$ and $\simp(\rup\backslash s)$
|
|
1087 |
are very closely related, but not identical.
|
107
|
1088 |
\subsubsection{Example for $\rup\backslash_{simp} \, s \neq \simp(\rup\backslash s)$}
|
101
|
1089 |
For example, let $r$ be the regular expression
|
|
1090 |
$(a+b)(a+a*)$ and $s$ be the string $aa$, then
|
103
|
1091 |
both $\erase (\rup\backslash_{simp} \, s)$ and $\erase (\simp (\rup\backslash s))$
|
|
1092 |
are $\ONE + a^*$. However, without $\erase$
|
101
|
1093 |
\begin{center}
|
|
1094 |
$\rup\backslash_{simp} \, s$ is equal to $_0(_0\ONE +_{11}a^*)$
|
|
1095 |
\end{center}
|
|
1096 |
\noindent
|
|
1097 |
whereas
|
|
1098 |
\begin{center}
|
103
|
1099 |
$\simp(\rup\backslash s)$ is equal to $(_{00}\ONE +_{011}a^*)$
|
101
|
1100 |
\end{center}
|
|
1101 |
\noindent
|
107
|
1102 |
(For the sake of visual simplicity, we use numbers to denote the bits
|
103
|
1103 |
in bitcodes as we have previously defined for annotated
|
|
1104 |
regular expressions. $\S$ is replaced by
|
107
|
1105 |
subscript $_1$ and $\Z$ by $_0$.)
|
103
|
1106 |
|
107
|
1107 |
What makes the difference?
|
|
1108 |
|
|
1109 |
%Two "rules" might be inferred from the above example.
|
103
|
1110 |
|
107
|
1111 |
%First, after erasing the bits the two regular expressions
|
|
1112 |
%are exactly the same: both become $1+a^*$. Here the
|
|
1113 |
%function $\simp$ exhibits the "one in the end equals many times
|
|
1114 |
%at the front"
|
|
1115 |
%property: one simplification in the end causes the
|
|
1116 |
%same regular expression structure as
|
|
1117 |
%successive simplifications done alongside derivatives.
|
|
1118 |
%$\rup\backslash_{simp} \, s$ unfolds to
|
|
1119 |
%$\simp((\simp(r\backslash a))\backslash a)$
|
|
1120 |
%and $\simp(\rup\backslash s)$ unfolds to
|
|
1121 |
%$\simp((r\backslash a)\backslash a)$. The one simplification
|
|
1122 |
%in the latter causes the resulting regular expression to
|
|
1123 |
%become $1+a^*$, exactly the same as the former with
|
|
1124 |
%two simplifications.
|
103
|
1125 |
|
107
|
1126 |
%Second, the bit-codes are different, but they are essentially
|
|
1127 |
%the same: if we push the outmost bits ${\bf_0}(_0\ONE +_{11}a^*)$ of $\rup\backslash_{simp} \, s$
|
|
1128 |
%inside then we get $(_{00}\ONE +_{011}a^*)$, exactly the
|
|
1129 |
%same as that of $\rup\backslash \, s$. And this difference
|
|
1130 |
%does not matter when we try to apply $\bmkeps$ or $\retrieve$
|
|
1131 |
%to it. This seems a good news if we want to use $\retrieve$
|
|
1132 |
%to prove things.
|
103
|
1133 |
|
107
|
1134 |
%If we look into the difference above, we could see that the
|
|
1135 |
%difference is not fundamental: the bits are just being moved
|
|
1136 |
%around in a way that does not hurt the correctness.
|
103
|
1137 |
During the first derivative operation,
|
|
1138 |
$\rup\backslash a=(_0\ONE + \ZERO)(_0a + _1a^*)$ is
|
107
|
1139 |
in the form of a sequence regular expression with
|
|
1140 |
two components, the first
|
|
1141 |
one $\ONE + \ZERO$ being nullable.
|
103
|
1142 |
Recall the simplification function definition:
|
|
1143 |
\begin{center}
|
|
1144 |
\begin{tabular}{@{}lcl@{}}
|
|
1145 |
|
|
1146 |
$\textit{simp} \; (\textit{SEQ}\;bs\,a_1\,a_2)$ & $\dn$ & $ (\textit{simp} \; a_1, \textit{simp} \; a_2) \; \textit{match} $ \\
|
|
1147 |
&&$\quad\textit{case} \; (\ZERO, \_) \Rightarrow \ZERO$ \\
|
|
1148 |
&&$\quad\textit{case} \; (\_, \ZERO) \Rightarrow \ZERO$ \\
|
|
1149 |
&&$\quad\textit{case} \; (\ONE, a_2') \Rightarrow \textit{fuse} \; bs \; a_2'$ \\
|
|
1150 |
&&$\quad\textit{case} \; (a_1', \ONE) \Rightarrow \textit{fuse} \; bs \; a_1'$ \\
|
|
1151 |
&&$\quad\textit{case} \; (a_1', a_2') \Rightarrow \textit{SEQ} \; bs \; a_1' \; a_2'$ \\
|
|
1152 |
|
|
1153 |
$\textit{simp} \; (\textit{ALTS}\;bs\,as)$ & $\dn$ & $\textit{distinct}( \textit{flatten} ( \textit{map simp as})) \; \textit{match} $ \\
|
|
1154 |
&&$\quad\textit{case} \; [] \Rightarrow \ZERO$ \\
|
|
1155 |
&&$\quad\textit{case} \; a :: [] \Rightarrow \textit{fuse bs a}$ \\
|
|
1156 |
&&$\quad\textit{case} \; as' \Rightarrow \textit{ALTS}\;bs\;as'$\\
|
|
1157 |
|
|
1158 |
$\textit{simp} \; a$ & $\dn$ & $\textit{a} \qquad \textit{otherwise}$
|
|
1159 |
\end{tabular}
|
|
1160 |
\end{center}
|
|
1161 |
|
|
1162 |
\noindent
|
107
|
1163 |
|
|
1164 |
and the difinition of $\flatten$:
|
|
1165 |
\begin{center}
|
|
1166 |
\begin{tabular}{c c c}
|
|
1167 |
$\flatten \; []$ & $\dn$ & $[]$\\
|
|
1168 |
$\flatten \; \ZERO::rs$ & $\dn$ & $rs$\\
|
|
1169 |
$\flatten \;(_{\textit{bs}_1}\oplus \textit{rs}_1 ::rs)$ & $\dn$ & $(\map \, (\fuse \, \textit{bs}_1) \,\textit{rs}_1) ::: \flatten(rs)$\\
|
|
1170 |
$\flatten \; r :: rs$ & $\dn$ & $r::\flatten(rs)$
|
|
1171 |
\end{tabular}
|
|
1172 |
\end{center}
|
|
1173 |
|
|
1174 |
\noindent
|
|
1175 |
If we call $\simp$ on $\rup\backslash a$, just as $\backslash_{simp}$
|
103
|
1176 |
requires, then we would go throught the third clause of
|
|
1177 |
the sequence case:$\quad\textit{case} \; (\ONE, a_2') \Rightarrow \textit{fuse} \; bs \; a_2'$.
|
107
|
1178 |
The $\ZERO$ of $(_0\ONE + \ZERO)$ is thrown away
|
|
1179 |
by $\flatten$ and
|
|
1180 |
$_0\ONE$ merged into $(_0a + _1a^*)$ by simply
|
103
|
1181 |
putting its bits($_0$) to the front of the second component:
|
|
1182 |
${\bf_0}(_0a + _1a^*)$.
|
|
1183 |
After a second derivative operation,
|
|
1184 |
namely, $(_0(_0a + _1a^*))\backslash a$, we get
|
|
1185 |
$
|
|
1186 |
_0(_0 \ONE + _1(_1\ONE \cdot a^*))
|
|
1187 |
$, and this simplifies to $_0(_0 \ONE + _{11} a^*)$
|
|
1188 |
by the third clause of the alternative case:
|
|
1189 |
$\quad\textit{case} \; as' \Rightarrow \textit{ALTS}\;bs\;as'$.
|
107
|
1190 |
The outmost bit $_0$ stays with
|
|
1191 |
the outmost regular expression, rather than being fused to
|
|
1192 |
its child regular expressions, as what we will later see happens
|
|
1193 |
to $\simp(\rup\backslash \, s)$.
|
|
1194 |
If we choose to not simplify in the midst of derivative operations,
|
|
1195 |
but only do it at the end after the string has been exhausted,
|
|
1196 |
namely, $\simp(\rup\backslash \, s)=\simp((\rup\backslash a)\backslash a)$,
|
|
1197 |
then at the {\bf second} derivative of
|
|
1198 |
$(\rup\backslash a)\bf{\backslash a}$
|
|
1199 |
we will go throught the clause of $\backslash$:
|
|
1200 |
\begin{center}
|
|
1201 |
\begin{tabular}{lcl}
|
|
1202 |
$(\textit{SEQ}\;bs\,a_1\,a_2)\,\backslash c$ & $\dn$ &
|
|
1203 |
$(when \; \textit{bnullable}\,a_1)$\\
|
|
1204 |
& &$\textit{ALTS}\,bs\,List(\;\;(\textit{SEQ}\,[]\,(a_1\,\backslash c)\,a_2),$\\
|
|
1205 |
& &$(\textit{fuse}\,(\textit{bmkeps}\,a_1)\,(a_2\,\backslash c))\;\;)$\\
|
|
1206 |
\end{tabular}
|
|
1207 |
\end{center}
|
|
1208 |
|
|
1209 |
because
|
|
1210 |
$\rup\backslash a = (_0\ONE + \ZERO)(_0a + _1a^*)$
|
|
1211 |
is a sequence
|
|
1212 |
with the first component being nullable
|
|
1213 |
(unsimplified, unlike the first round of running$\backslash_{simp}$).
|
103
|
1214 |
Therefore $((_0\ONE + \ZERO)(_0a + _1a^*))\backslash a$ splits into
|
|
1215 |
$([(\ZERO + \ZERO)\cdot(_0a + _1a^*)] + _0( _0\ONE + _1[_1\ONE \cdot a^*]))$.
|
|
1216 |
After these two successive derivatives without simplification,
|
|
1217 |
we apply $\simp$ to this regular expression, which goes through
|
107
|
1218 |
the alternative clause, and each component of
|
|
1219 |
$([(\ZERO + \ZERO)\cdot(_0a + _1a^*)] + _0( _0\ONE + _1[_1\ONE \cdot a^*]))$
|
|
1220 |
will be simplified, giving us the list:$[\ZERO, _0(_0\ONE + _{11}a^*)]$
|
|
1221 |
This list is then "flattened"--$\ZERO$ will be
|
|
1222 |
thrown away by $\textit{flatten}$; $ _0(_0\ONE + _{11}a^*)$
|
|
1223 |
is opened up to make the list consisting of two separate elements
|
|
1224 |
$_{00}\ONE$ and $_{011}a^*$, note that $flatten$
|
|
1225 |
$\fuse$s the bit(s) $_0$ to the front of $_0\ONE $ and $_{11}a^*$.
|
122
|
1226 |
The order of simplification, which impacts the order that alternatives
|
|
1227 |
are opened up, causes
|
107
|
1228 |
the bits to be moved differently.
|
|
1229 |
|
|
1230 |
\subsubsection{A Failed Attempt To Remedy the Problem Above}
|
111
|
1231 |
A simple class of regular expression and string
|
|
1232 |
pairs $(r, s)$ can be deduced from the above example
|
|
1233 |
which trigger the difference between
|
107
|
1234 |
$\rup\backslash_{simp} \, s$
|
|
1235 |
and $\simp(\rup\backslash s)$:
|
111
|
1236 |
\begin{center}
|
|
1237 |
\begin{tabular}{lcl}
|
|
1238 |
$D =\{ (r_1 \cdot r_2,\; [c_1c_2]) \mid $ & $\simp(r_2) = r_2, \simp(r_1 \backslash c_1) = \ONE,$\\
|
|
1239 |
$r_1 \; not \; \nullable, c_2 \in L(r_2),$ & $\exists \textit{rs},\textit{bs}.\; r_2 \backslash c_2 = _{bs}{\oplus rs}$\\
|
|
1240 |
$\exists \textit{rs}_1. \; \simp(r_2 \backslash c_2) = _{bs}{\oplus \textit{rs}_1}$ & $and \;\simp(r_1 \backslash [c_1c_2]) = \ZERO\}$\\
|
|
1241 |
\end{tabular}
|
|
1242 |
\end{center}
|
|
1243 |
We take a pair $(r, \;s)$ from the set $D$.
|
|
1244 |
|
|
1245 |
Now we compute ${\bf \rup \backslash_{simp} s}$, we get:
|
110
|
1246 |
\begin{center}
|
|
1247 |
\begin{tabular}{lcl}
|
|
1248 |
$(r_1\cdot r_2)\backslash_{simp} \, [c_1c_2]$ & $= \simp\left[ \big(\simp\left[ \left( r_1\cdot r_2 \right) \backslash c_1\right] \big)\backslash c_2\right]$\\
|
|
1249 |
& $= \simp\left[ \big(\simp \left[ \left(r_1 \backslash c_1\right) \cdot r_2 \right] \big) \backslash c_2 \right]$\\
|
111
|
1250 |
& $= \simp \left[ (\fuse \; \bmkeps(r_1\backslash c_1) \; \simp(r_2) ) \backslash c_2 \right]$,\\
|
|
1251 |
& $= \simp \left[ (\fuse \; \bmkeps(r_1\backslash c_1) \; r_2 ) \backslash c_2 \right]$,
|
110
|
1252 |
\end{tabular}
|
|
1253 |
\end{center}
|
|
1254 |
\noindent
|
|
1255 |
from the definition of $D$ we know $r_1 \backslash c_1$ is nullable, therefore
|
|
1256 |
$\bmkeps(r_1\backslash c_1)$ returns a bitcode, we shall call it
|
111
|
1257 |
$\textit{bs}_2$.
|
|
1258 |
The above term can be rewritten as
|
|
1259 |
\begin{center}
|
|
1260 |
$ \simp \left[ \fuse \; \textit{bs}_2\; r_2 \backslash c_2 \right]$,
|
|
1261 |
\end{center}
|
|
1262 |
which is equal to
|
110
|
1263 |
\begin{center}
|
111
|
1264 |
$\simp \left[ \fuse \; \textit{bs}_2 \; _{bs}{\oplus rs} \right]$\\
|
|
1265 |
$=\simp \left[ \; _{bs_2++bs}{\oplus rs} \right]$\\
|
|
1266 |
$= \; _{bs_2++bs}{\oplus \textit{rs}_1} $
|
|
1267 |
\end{center}
|
|
1268 |
\noindent
|
|
1269 |
by using the properties from the set $D$ again
|
|
1270 |
and again(The reason why we set so many conditions
|
|
1271 |
that the pair $(r,s)$ need to satisfy is because we can
|
|
1272 |
rewrite them easily to construct the difference.)
|
|
1273 |
|
|
1274 |
Now we compute ${\bf \simp(\rup \backslash s)}$:
|
|
1275 |
\begin{center}
|
|
1276 |
$\simp \big[(r_1\cdot r_2) \backslash [c_1c_2] \big]= \simp \left[ ((r_1 \cdot r_2 )\backslash c_1) \backslash c_2 \right]$
|
110
|
1277 |
\end{center}
|
111
|
1278 |
\noindent
|
|
1279 |
Again, using the properties above, we obtain
|
|
1280 |
the following chain of equalities:
|
110
|
1281 |
\begin{center}
|
111
|
1282 |
$\simp(\rup \backslash s)= \simp \left[ ((r_1 \cdot r_2 )\backslash c_1) \backslash c_2 \right]= \simp\left[ \left(r_1 \backslash c_1\right) \cdot r_2 \big) \backslash c_2 \right]$\\
|
|
1283 |
$= \simp \left[ \oplus[\big( \left(r_1 \backslash c_1\right) \backslash c_2 \big) \cdot r_2 \; , \; \fuse \; (\bmkeps \;r_1\backslash c_1) \; r_2 \backslash c_2 ] \right]$,
|
|
1284 |
\end{center}
|
|
1285 |
\noindent
|
|
1286 |
as before, we call the bitcode returned by
|
|
1287 |
$\bmkeps(r_1\backslash c_1)$ as
|
|
1288 |
$\textit{bs}_2$.
|
|
1289 |
Also, $\simp(r_2 \backslash c_2)$ is
|
|
1290 |
$_{bs}\oplus \textit{rs}_1$,
|
|
1291 |
and $( \left(r_1 \backslash c_1\right) \backslash c_2 \cdot r_2)$
|
|
1292 |
simplifies to $\ZERO$,
|
|
1293 |
so the above term can be expanded as
|
|
1294 |
\begin{center}
|
|
1295 |
\begin{tabular}{l}
|
|
1296 |
$\textit{distinct}(\flatten[\ZERO\;, \; _{\textit{bs}_2++\textit{bs}}\oplus \textit{rs}_1] ) \; \textit{match} $ \\
|
|
1297 |
$\textit{case} \; [] \Rightarrow \ZERO$ \\
|
|
1298 |
$\textit{case} \; a :: [] \Rightarrow \textit{\fuse \; \textit{bs} a}$ \\
|
|
1299 |
$\textit{case} \; as' \Rightarrow _{[]}\oplus as'$\\
|
110
|
1300 |
\end{tabular}
|
|
1301 |
\end{center}
|
|
1302 |
\noindent
|
111
|
1303 |
Applying the definition of $\flatten$, we get
|
|
1304 |
\begin{center}
|
|
1305 |
$_{[]}\oplus (\textit{map} \; \fuse (\textit{bs}_2 ++ bs) rs_1)$
|
|
1306 |
\end{center}
|
|
1307 |
\noindent
|
|
1308 |
compared to the result
|
110
|
1309 |
\begin{center}
|
111
|
1310 |
$ \; _{bs_2++bs}{\oplus \textit{rs}_1} $
|
110
|
1311 |
\end{center}
|
111
|
1312 |
\noindent
|
|
1313 |
Note how these two regular expressions only
|
|
1314 |
differ in terms of the position of the bits
|
|
1315 |
$\textit{bs}_2++\textit{bs}$. They are the same otherwise.
|
|
1316 |
What caused this difference to happen?
|
|
1317 |
The culprit is the $\flatten$ function, which spills
|
|
1318 |
out the bitcodes in the inner alternatives when
|
|
1319 |
there exists an outer alternative.
|
|
1320 |
Note how the absence of simplification
|
|
1321 |
caused $\simp(\rup \backslash s)$ to
|
|
1322 |
generate the nested alternatives structure:
|
|
1323 |
\begin{center}
|
|
1324 |
$ \oplus[\ZERO \;, \; _{bs}\oplus \textit{rs} ]$
|
|
1325 |
\end{center}
|
|
1326 |
and this will always trigger the $\flatten$ to
|
112
|
1327 |
spill out the inner alternative's bitcode $\textit{bs}$,
|
111
|
1328 |
whereas when
|
|
1329 |
simplification is done along the way,
|
|
1330 |
the structure of nested alternatives is never created(we can
|
|
1331 |
actually prove that simplification function never allows nested
|
|
1332 |
alternatives to happen, more on this later).
|
110
|
1333 |
|
113
|
1334 |
How about we do not allow the function $\simp$
|
|
1335 |
to fuse out the bits when it is unnecessary?
|
|
1336 |
Like, for the above regular expression, we might
|
|
1337 |
just delete the outer layer of alternative
|
|
1338 |
\begin{center}
|
|
1339 |
\st{$ {\oplus[\ZERO \;,}$} $_{bs}\oplus \textit{rs}$ \st{$]$}
|
|
1340 |
\end{center}
|
|
1341 |
and get $_{bs}\oplus \textit{rs}$ instead, without
|
|
1342 |
fusing the bits $\textit{bs}$ inside to every element
|
|
1343 |
of $\textit{rs}$.
|
|
1344 |
This idea can be realized by making the following
|
|
1345 |
changes to the $\simp$-function:
|
|
1346 |
\begin{center}
|
|
1347 |
\begin{tabular}{@{}lcl@{}}
|
|
1348 |
|
114
|
1349 |
$\textit{simp}' \; (_{\textit{bs}}(a_1 \cdot a_2))$ & $\dn$ & $\textit{as} \; \simp \; \textit{was} \; \textit{before} $ \\
|
113
|
1350 |
|
114
|
1351 |
$\textit{simp}' \; (_{bs}\oplus as)$ & $\dn$ & \st{$\textit{distinct}( \textit{flatten} ( \textit{map simp as})) \; \textit{match} $} \\
|
|
1352 |
&&\st{$\quad\textit{case} \; [] \Rightarrow \ZERO$} \\
|
|
1353 |
&&\st{$\quad\textit{case} \; a :: [] \Rightarrow \textit{fuse bs a}$} \\
|
|
1354 |
&&\st{$\quad\textit{case} \; as' \Rightarrow \textit{ALTS}\;bs\;as'$}\\
|
|
1355 |
&&$\textit{if}(\textit{hollowAlternatives}( \textit{map \; simp \; as}))$\\
|
|
1356 |
&&$\textit{then} \; \fuse \; \textit{bs}\; \textit{extractAlt}(\textit{map} \; \simp \; \textit{as} )$\\
|
|
1357 |
&&$\textit{else} \; \simp(_{bs} \oplus \textit{as})$\\
|
|
1358 |
|
113
|
1359 |
|
114
|
1360 |
$\textit{simp}' \; a$ & $\dn$ & $\textit{a} \qquad \textit{otherwise}$
|
113
|
1361 |
\end{tabular}
|
|
1362 |
\end{center}
|
|
1363 |
|
|
1364 |
\noindent
|
114
|
1365 |
given the definition of $\textit{hollowAlternatives}$ and $\textit{extractAlt}$ :
|
|
1366 |
\begin{center}
|
|
1367 |
$\textit{hollowAlternatives}( \textit{rs}) \dn
|
|
1368 |
\exists r = (_{\textit{bs}_1}\oplus \textit{rs}_1) \in \textit{rs}. \forall r' \in \textit{rs}, \;
|
|
1369 |
\textit{either} \; r' = \ZERO \; \textit{or} \; r' = r $
|
|
1370 |
$\textit{extractAlt}( \textit{rs}) \dn \textit{if}\big(
|
|
1371 |
\exists r = (_{\textit{bs}_1}\oplus \textit{rs}_1) \in \textit{rs}. \forall r' \in \textit{rs}, \;
|
|
1372 |
\textit{either} \; r' = \ZERO \; \textit{or} \; r' = r \big)\; \textit{then} \; \textit{return} \; r$
|
|
1373 |
\end{center}
|
|
1374 |
\noindent
|
|
1375 |
Basically, $\textit{hollowAlternatives}$ captures the feature of
|
|
1376 |
a list of regular expression of the shape
|
|
1377 |
\begin{center}
|
|
1378 |
$ \oplus[\ZERO \;, \; _{bs}\oplus \textit{rs} ]$
|
|
1379 |
\end{center}
|
|
1380 |
and this means we can simply elevate the
|
|
1381 |
inner regular expression $_{bs}\oplus \textit{rs}$
|
|
1382 |
to the outmost
|
|
1383 |
and throw away the useless $\ZERO$s and
|
|
1384 |
the outer $\oplus$ wrapper.
|
|
1385 |
Using this new definition of simp,
|
|
1386 |
under the example where $r$ is the regular expression
|
|
1387 |
$(a+b)(a+a*)$ and $s$ is the string $aa$
|
|
1388 |
the problem of $\rup\backslash_{simp} \, s \neq \simp(\rup\backslash s)$
|
|
1389 |
is resolved.
|
113
|
1390 |
|
114
|
1391 |
Unfortunately this causes new problems:
|
|
1392 |
for the counterexample where
|
|
1393 |
\begin{center}
|
|
1394 |
$r$ is the regular expression
|
|
1395 |
$(ab+(a^*+aa))$ and $s$ is the string $aa$
|
|
1396 |
\end{center}
|
122
|
1397 |
|
|
1398 |
\noindent
|
|
1399 |
$\rup\backslash_{simp} \, s$ is equal to
|
125
|
1400 |
$ _1(_{011}a^* + _1\ONE) $ whereas
|
|
1401 |
$ \simp(\rup\backslash s) = (_{1011}a^* + _{11}\ONE)$.
|
|
1402 |
This discrepancy does not appear for the old
|
114
|
1403 |
version of $\simp$.
|
125
|
1404 |
|
|
1405 |
Why?
|
|
1406 |
|
|
1407 |
During the first derivative operation,
|
|
1408 |
\begin{center}
|
|
1409 |
$\rup\backslash a=( _0[ \ONE\cdot {\bf b}] + _1( _0[ _1\ONE \cdot {\bf a}^*] + [ \ONE \cdot {\bf a}]) )$,
|
|
1410 |
\end{center}
|
|
1411 |
\noindent
|
|
1412 |
the second derivative gives us
|
|
1413 |
\begin{center}
|
|
1414 |
$\rup\backslash a=(_0( [\ZERO\cdot {\bf b}] + 0) + _1( _0( [\ZERO\cdot {\bf a}^*] + _1[ _1\ONE \cdot {\bf a}^*]) + _1( [\ZERO \cdot {\bf a}] + \ONE) ))$,
|
|
1415 |
\end{center}
|
|
1416 |
|
|
1417 |
\noindent
|
|
1418 |
and this simplifies to
|
|
1419 |
\begin{center}
|
|
1420 |
$ _1(_{011}{\bf a}^* + _1\ONE) $
|
|
1421 |
\end{center}
|
|
1422 |
|
|
1423 |
If, after the first derivative we apply simplification we get
|
|
1424 |
$(_0{\bf b} + _{101}{\bf a}^* + _{11}{\bf a} )$,
|
|
1425 |
and we do another derivative, getting
|
|
1426 |
$(\ZERO + (_{101}(\ONE \cdot _1{\bf a}^*)+_{11}\ONE)$,
|
|
1427 |
which simplifies to
|
|
1428 |
\begin{center}
|
|
1429 |
$ (_{1011}a^* + _{11}\ONE) $
|
|
1430 |
\end{center}
|
|
1431 |
|
|
1432 |
|
|
1433 |
|
|
1434 |
|
|
1435 |
|
122
|
1436 |
We have changed the algorithm to suppress the old
|
|
1437 |
counterexample, but this gives rise to new counterexamples.
|
114
|
1438 |
This dilemma causes this amendment not a successful
|
|
1439 |
attempt to make $\rup\backslash_{simp} \, s = \simp(\rup\backslash s)$
|
|
1440 |
under every possible regular expression and string.
|
112
|
1441 |
\subsection{Properties of the Function $\simp$}
|
|
1442 |
|
|
1443 |
We have proved in Isabelle quite a few properties
|
|
1444 |
of the $\simp$-function, which helps the proof to go forward
|
|
1445 |
and we list them here to aid comprehension.
|
|
1446 |
|
|
1447 |
To start, we need a bit of auxiliary notations,
|
|
1448 |
which is quite basic and is only written here
|
|
1449 |
for clarity.
|
113
|
1450 |
|
|
1451 |
$\textit{sub}(r)$ computes the set of the
|
|
1452 |
sub-regular expression of $r$:
|
|
1453 |
\begin{center}
|
|
1454 |
$\textit{sub}(\ONE) \dn \{\ONE\}$\\
|
|
1455 |
$\textit{sub}(r_1 \cdot r_2) \dn \textit{sub}(r_1) \cup \textit{sub}(r_2) \cup \{r_1 \cdot r_2\}$\\
|
112
|
1456 |
$\textit{sub}(r_1 + r_2) \dn \textit{sub}(r_1) \cup \textit{sub}(r_2) \cup \{r_1+r_2\}$\\
|
113
|
1457 |
\end{center}
|
112
|
1458 |
$\textit{good}(r) \dn r \neq \ZERO \land \\
|
|
1459 |
\forall r' \in \textit{sub}(r), \textit{if} \; r' = _{bs_1}\oplus(rs_1), \;
|
|
1460 |
\textit{then} \nexists r'' \in \textit{rs}_1 \; s.t.\;
|
|
1461 |
r'' = _{bs_2}\oplus \textit{rs}_2 $
|
|
1462 |
|
|
1463 |
The properties are mainly the ones below:
|
|
1464 |
\begin{itemize}
|
|
1465 |
\item
|
|
1466 |
\begin{center}
|
|
1467 |
$\simp(\simp(r)) = \simp(r)$
|
|
1468 |
\end{center}
|
|
1469 |
\item
|
|
1470 |
\begin{center}
|
|
1471 |
$\textit{if} r = \simp(r') \textit{then} \; \textit{good}(r) $
|
|
1472 |
\end{center}
|
|
1473 |
\end{itemize}
|
114
|
1474 |
\subsection{the Contains relation}
|
|
1475 |
$\retrieve$ is a too strong relation in that
|
|
1476 |
it only extracts one bitcode instead of a set of them.
|
|
1477 |
Therefore we try to define another relation(predicate)
|
|
1478 |
to capture the fact the regular expression has bits
|
|
1479 |
being moved around but still has all the bits needed.
|
|
1480 |
The contains symbol, written$\gg$, is a relation that
|
|
1481 |
takes two arguments in an infix form
|
|
1482 |
and returns a truth value.
|
112
|
1483 |
|
114
|
1484 |
|
|
1485 |
In other words, from the set of regular expression and
|
|
1486 |
bitcode pairs
|
|
1487 |
$\textit{RV} = \{(r, v) \mid r \text{r is a regular expression, v is a value}\}$,
|
|
1488 |
those that satisfy the following requirements are in the set
|
|
1489 |
$\textit{RV}_Contains$.
|
|
1490 |
Unlike the $\retrieve$
|
|
1491 |
function, which takes two arguments $r$ and $v$ and
|
|
1492 |
produces an only answer $\textit{bs}$, it takes only
|
|
1493 |
one argument $r$ and returns a set of bitcodes that
|
|
1494 |
can be generated by $r$.
|
|
1495 |
\begin{center}
|
|
1496 |
\begin{tabular}{llclll}
|
|
1497 |
& & & $_{bs}\ONE$ & $\gg$ & $\textit{bs}$\\
|
|
1498 |
& & & $_{bs}{\bf c}$ & $\gg$ & $\textit{bs}$\\
|
|
1499 |
$\textit{if} \; r_1 \gg \textit{bs}_1$ & $r_2 \; \gg \textit{bs}_2$
|
|
1500 |
& $\textit{then}$ &
|
|
1501 |
$_{bs}{r_1 \cdot r_2}$ &
|
|
1502 |
$\gg$ &
|
|
1503 |
$\textit{bs} @ \textit{bs}_1 @ \textit{bs}_2$\\
|
|
1504 |
|
|
1505 |
$\textit{if} \; r \gg \textit{bs}_1$ & & $\textit{then}$ &
|
|
1506 |
$_{bs}{\oplus(r :: \textit{rs}})$ &
|
|
1507 |
$\gg$ &
|
|
1508 |
$\textit{bs} @ \textit{bs}_1 $\\
|
|
1509 |
|
|
1510 |
$\textit{if} \; _{bs}(\oplus \textit{rs}) \gg \textit{bs} @ \textit{bs}_1$ & & $\textit{then}$ &
|
|
1511 |
$_{bs}{\oplus(r :: \textit{rs}})$ &
|
|
1512 |
$\gg$ &
|
|
1513 |
$\textit{bs} @ \textit{bs}_1 $\\
|
|
1514 |
|
|
1515 |
$\textit{if} \; r \gg \textit{bs}_1\; \textit{and}$ & $_{bs}r^* \gg \textit{bs} @ \textit{bs}_2$ & $\textit{then}$ &
|
|
1516 |
$_{bs}r^* $ &
|
|
1517 |
$\gg$ &
|
|
1518 |
$\textit{bs} @ [0] @ \textit{bs}_1@ \textit{bs}_2 $\\
|
|
1519 |
|
|
1520 |
& & & $_{bs}r^*$ & $\gg$ & $\textit{bs} @ [1]$\\
|
|
1521 |
\end{tabular}
|
|
1522 |
\end{center}
|
|
1523 |
It is a predicate in the sense that given
|
|
1524 |
a regular expression and a bitcode, it
|
|
1525 |
returns true or false, depending on whether
|
|
1526 |
or not the regular expression can actually produce that
|
|
1527 |
value. If the predicates returns a true, then
|
|
1528 |
we say that the regular expression $r$ contains
|
|
1529 |
the bitcode $\textit{bs}$, written
|
|
1530 |
$r \gg \textit{bs}$.
|
|
1531 |
The $\gg$ operator with the
|
|
1532 |
regular expression $r$ may also be seen as a
|
|
1533 |
machine that does a derivative of regular expressions
|
|
1534 |
on all strings simultaneously, taking
|
|
1535 |
the bits by going throught the regular expression tree
|
|
1536 |
structure in a depth first manner, regardless of whether
|
|
1537 |
the part being traversed is nullable or not.
|
|
1538 |
It put all possible bits that can be produced on such a traversal
|
|
1539 |
into a set.
|
|
1540 |
For example, if we are given the regular expression
|
|
1541 |
$((a+b)(c+d))^*$, the tree structure may be written as
|
|
1542 |
\begin{center}
|
|
1543 |
\begin{tikzpicture}
|
|
1544 |
\tikz[tree layout]\graph[nodes={draw, circle}] {
|
|
1545 |
* ->
|
|
1546 |
{@-> {
|
|
1547 |
{+1 ->
|
|
1548 |
{a , b}
|
|
1549 |
},
|
|
1550 |
{+ ->
|
|
1551 |
{c , d }
|
|
1552 |
}
|
|
1553 |
}
|
|
1554 |
}
|
|
1555 |
};
|
|
1556 |
\end{tikzpicture}
|
|
1557 |
\end{center}
|
|
1558 |
\subsection{the $\textit{ders}_2$ Function}
|
|
1559 |
If we want to prove the result
|
|
1560 |
\begin{center}
|
|
1561 |
$ \textit{blexer}\_{simp}(r, \; s) = \textit{blexer}(r, \; s)$
|
|
1562 |
\end{center}
|
|
1563 |
inductively
|
|
1564 |
on the structure of the regular expression,
|
|
1565 |
then we need to induct on the case $r_1 \cdot r_2$,
|
|
1566 |
it can be good if we could express $(r_1 \cdot r_2) \backslash s$
|
|
1567 |
in terms of $r_1 \backslash s$ and $r_2 \backslash s$,
|
|
1568 |
and this naturally induces the $ders2$ function,
|
|
1569 |
which does a "convolution" on $r_1$ and $r_2$ using the string
|
|
1570 |
$s$.
|
|
1571 |
It is based on the observation that the derivative of $r_1 \cdot r_2$
|
|
1572 |
with respect to a string $s$ can actually be written in an "explicit form"
|
|
1573 |
composed of $r_1$'s derivative of $s$ and $r_2$'s derivative of $s$.
|
|
1574 |
This can be illustrated in the following procedure execution
|
|
1575 |
\begin{center}
|
|
1576 |
$ (r_1 \cdot r_2) \backslash [c_1c_2] = (\textit{if} \; \nullable(r_1)\; \textit{then} \; ((r_1 \backslash c_1) \cdot r_2 + r_2 \backslash c_1) \; \textit{else} \; (r_1\backslash c_1) \cdot r_2) \backslash c_2$
|
|
1577 |
\end{center}
|
|
1578 |
which can also be written in a "convoluted sum"
|
|
1579 |
format:
|
|
1580 |
\begin{center}
|
|
1581 |
$ (r_1 \cdot r_2) \backslash [c_1c_2] = \sum{r_1 \backslash s_i \cdot r_2 \backslash s_j}$
|
|
1582 |
\end{center}
|
|
1583 |
In a more serious manner, we should write
|
|
1584 |
\begin{center}
|
|
1585 |
$ (r_1 \cdot r_2) \backslash [c_1c_2] = \sum{r_1 \backslash s_i \cdot r_2 \backslash s_j}$
|
|
1586 |
\end{center}
|
|
1587 |
Note this differentiates from the previous form in the sense that
|
|
1588 |
it calculates the results $r_1\backslash s_i , r_2 \backslash s_j$ first and then glue them together
|
|
1589 |
through nested alternatives whereas the $r_1 \cdot r_2 \backslash s$ procedure,
|
|
1590 |
used by algorithm $\lexer$, can only produce each component of the
|
|
1591 |
resulting alternatives regular expression altogether rather than
|
|
1592 |
generating each of the children nodes one by one
|
|
1593 |
n a single recursive call that is only for generating that
|
|
1594 |
very expression itself.
|
|
1595 |
We have this
|
|
1596 |
\section{Conclusion}
|
|
1597 |
Under the exhaustive tests we believe the main
|
|
1598 |
result holds, yet a proof still seems elusive.
|
|
1599 |
We have tried out different approaches, and
|
|
1600 |
found a lot of properties of the function $\simp$.
|
|
1601 |
The counterexamples where $\rup\backslash_{simp} \, s \neq \simp(\rup\backslash s)$
|
|
1602 |
are also valuable in the sense that
|
|
1603 |
we get to know better why they are not equal and what
|
|
1604 |
are the subtle differences between a
|
|
1605 |
nested simplified regular expression and a
|
|
1606 |
regular expression that is simplified at the final moment.
|
|
1607 |
We are almost there, but a last step is needed to make the proof work.
|
|
1608 |
Hopefully in the next few weeks we will be able to find one.
|
110
|
1609 |
%CONSTRUCTION SITE HERE
|
101
|
1610 |
that is to say, despite the bits are being moved around on the regular expression
|
|
1611 |
(difference in bits), the structure of the (unannotated)regular expression
|
|
1612 |
after one simplification is exactly the same after the
|
|
1613 |
same sequence of derivative operations
|
|
1614 |
regardless of whether we did simplification
|
|
1615 |
along the way.
|
107
|
1616 |
One way would be to give a function that calls
|
110
|
1617 |
|
107
|
1618 |
fuse is the culprit: it causes the order in which alternatives
|
|
1619 |
are opened up to be remembered and finally the difference
|
|
1620 |
appear in $\simp(\rup \backslash s)$ and $\rup \backslash{simp} \,s$.
|
|
1621 |
but we have to use them as they are essential in the simplification:
|
|
1622 |
flatten needs them.
|
|
1623 |
|
|
1624 |
|
|
1625 |
|
101
|
1626 |
However, without erase the above equality does not hold:
|
|
1627 |
for the regular expression
|
|
1628 |
$(a+b)(a+a*)$,
|
|
1629 |
if we do derivative with respect to string $aa$,
|
114
|
1630 |
we get
|
103
|
1631 |
|
109
|
1632 |
\subsection{Another Proof Strategy}
|
101
|
1633 |
sdddddr does not equal sdsdsdsr sometimes.\\
|
|
1634 |
For example,
|
|
1635 |
|
|
1636 |
This equicalence class method might still have the potential of proving this,
|
|
1637 |
but not yet
|
|
1638 |
i parallelly tried another method of using retrieve\\
|
|
1639 |
|
|
1640 |
|
94
|
1641 |
The vsimp function, defined as follows
|
|
1642 |
tries to simplify the value in lockstep with
|
|
1643 |
regular expression:\\
|
|
1644 |
|
|
1645 |
|
|
1646 |
The problem here is that
|
|
1647 |
|
|
1648 |
we used retrieve for the key induction:
|
|
1649 |
$decode (retrieve (r\backslash (s @ [c])) v) r $
|
|
1650 |
$decode (retrieve (r\backslash s) (inj (r\backslash s) c v)) r$
|
|
1651 |
Here, decode recovers a value that corresponds to a match(possibly partial)
|
|
1652 |
from bits, and the bits are extracted by retrieve,
|
|
1653 |
and the key value $v$ that guides retrieve is
|
|
1654 |
$mkeps r\backslash s$, $inj r c (mkeps r\backslash s)$, $inj (inj (v))$, ......
|
|
1655 |
if we can
|
|
1656 |
the problem is that
|
|
1657 |
need vsiimp to make a value that is suitable for decoding
|
|
1658 |
$Some(flex rid(s@[c])v) = Some(flex rids(inj (r\backslash s)cv))$
|
|
1659 |
another way that christian came up with that might circumvent the
|
|
1660 |
prblem of finding suitable value is by not stating the visimp
|
|
1661 |
function but include all possible value in a set that a regex is able to produce,
|
|
1662 |
and proving that both r and sr are able to produce the bits that correspond the POSIX value
|
|
1663 |
|
|
1664 |
produced by feeding the same initial regular expression $r$ and string $s$ to the
|
|
1665 |
two functions $ders$ and $ders\_simp$.
|
|
1666 |
The reason why
|
|
1667 |
Namely, if $bmkeps( r_1) = bmkeps(r_2)$, then we
|
|
1668 |
|
|
1669 |
|
|
1670 |
If we define the equivalence relation $\sim_{m\epsilon}$ between two regular expressions
|
|
1671 |
$r_1$ and $r_2$as follows:
|
|
1672 |
$r_1 \sim_{m\epsilon} r_2 \iff bmkeps(r_1)= bmkeps(r_2)$
|
|
1673 |
(in other words, they $r1$ and $r2$ produce the same output under the function $bmkeps$.)
|
|
1674 |
Then the first goal
|
|
1675 |
might be restated as
|
|
1676 |
$(r^\uparrow)\backslash_{simp}\, s \sim_{m\epsilon} (r^\uparrow)\backslash s$.
|
|
1677 |
I tried to establish an equivalence relation between the regular experssions
|
|
1678 |
like dddr dddsr,.....
|
|
1679 |
but right now i am only able to establish dsr and dr, using structural induction on r.
|
|
1680 |
Those involve multiple derivative operations are harder to prove.
|
|
1681 |
Two attempts have been made:
|
|
1682 |
(1)induction on the number of der operations(or in other words, the length of the string s),
|
|
1683 |
the inductive hypothesis was initially specified as
|
|
1684 |
"For an arbitrary regular expression r,
|
|
1685 |
For all string s in the language of r whose length do not exceed
|
|
1686 |
the number n, ders s r me derssimp s r"
|
|
1687 |
and the proof goal may be stated as
|
|
1688 |
"For an arbitrary regular expression r,
|
|
1689 |
For all string s in the language of r whose length do not exceed
|
|
1690 |
the number n+1, ders s r me derssimp s r"
|
|
1691 |
the problem here is that although we can easily break down
|
|
1692 |
a string s of length n+1 into s1@list(c), it is not that easy
|
|
1693 |
to use the i.h. as a stepping stone to prove anything because s1 may well be not
|
|
1694 |
in the language L(r). This inhibits us from obtaining the fact that
|
|
1695 |
ders s1 r me derssimps s1 r.
|
|
1696 |
Further exploration is needed to amend this hypothesis so it includes the
|
|
1697 |
situation when s1 is not nullable.
|
|
1698 |
For example, what information(bits?
|
|
1699 |
values?) can be extracted
|
|
1700 |
from the regular expression ders(s1,r) so that we can compute or predict the possible
|
|
1701 |
result of bmkeps after another derivative operation. What function f can used to
|
|
1702 |
carry out the task? The possible way of exploration can be
|
|
1703 |
more directly perceived throught the graph below:
|
|
1704 |
find a function
|
|
1705 |
f
|
|
1706 |
such that
|
|
1707 |
f(bders s1 r)
|
|
1708 |
= re1
|
|
1709 |
f(bderss s1 r)
|
|
1710 |
= re2
|
|
1711 |
bmkeps(bders s r) = g(re1,c)
|
|
1712 |
bmkeps(bderssimp s r) = g(re2,c)
|
|
1713 |
and g(re1,c) = g(re2,c)
|
|
1714 |
The inductive hypothesis would be
|
|
1715 |
"For all strings s1 of length <= n,
|
|
1716 |
f(bders s1 r)
|
|
1717 |
= re1
|
|
1718 |
f(bderss s1 r)
|
|
1719 |
= re2"
|
|
1720 |
proving this would be a lemma for the main proof:
|
|
1721 |
the main proof would be
|
|
1722 |
"
|
|
1723 |
bmkeps(bders s r) = g(re1,c)
|
|
1724 |
bmkeps(bderssimp s r) = g(re2,c)
|
|
1725 |
for s = s1@c
|
|
1726 |
"
|
|
1727 |
and f need to be a recursive property for the lemma to be proved:
|
|
1728 |
it needs to store not only the "after one char nullable info",
|
|
1729 |
but also the "after two char nullable info",
|
|
1730 |
and so on so that it is able to predict what f will compute after a derivative operation,
|
|
1731 |
in other words, it needs to be "infinitely recursive"\\
|
|
1732 |
To prove the lemma, in other words, to get
|
|
1733 |
"For all strings s1 of length <= n+1,
|
|
1734 |
f(bders s1 r)
|
|
1735 |
= re3
|
|
1736 |
f(bderss s1 r)
|
|
1737 |
= re4"\\
|
|
1738 |
from\\
|
|
1739 |
"For all strings s1 of length <= n,
|
|
1740 |
f(bders s1 r)
|
|
1741 |
= re1
|
|
1742 |
f(bderss s1 r)
|
|
1743 |
= re2"\\
|
|
1744 |
it might be best to construct an auxiliary function h such that\\
|
|
1745 |
h(re1, c) = re3\\
|
|
1746 |
h(re2, c) = re4\\
|
|
1747 |
and re3 = f(bder c (bders s1 r))\\
|
|
1748 |
re4 = f(simp(bder c (bderss s1 r)))
|
|
1749 |
The key point here is that we are not satisfied with what bders s r will produce under
|
|
1750 |
bmkeps, but also how it will perform after a derivative operation and then bmkeps, and two
|
|
1751 |
derivative operations and so on. In essence, we are preserving the regular expression
|
|
1752 |
itself under the function f, in a less compact way than the regluar expression: we are
|
|
1753 |
not just recording but also interpreting what the regular expression matches.
|
|
1754 |
In other words, we need to prove the properties of bderss s r beyond the bmkeps result,
|
|
1755 |
i.e., not just the nullable ones, but also those containing remaining characters.\\
|
|
1756 |
(2)we observed the fact that
|
|
1757 |
erase sdddddr= erase sdsdsdsr
|
|
1758 |
that is to say, despite the bits are being moved around on the regular expression
|
|
1759 |
(difference in bits), the structure of the (unannotated)regular expression
|
|
1760 |
after one simplification is exactly the same after the
|
|
1761 |
same sequence of derivative operations
|
|
1762 |
regardless of whether we did simplification
|
|
1763 |
along the way.
|
|
1764 |
However, without erase the above equality does not hold:
|
|
1765 |
for the regular expression
|
|
1766 |
$(a+b)(a+a*)$,
|
|
1767 |
if we do derivative with respect to string $aa$,
|
|
1768 |
we get
|
|
1769 |
%TODO
|
|
1770 |
sdddddr does not equal sdsdsdsr sometimes.\\
|
|
1771 |
For example,
|
|
1772 |
|
|
1773 |
This equicalence class method might still have the potential of proving this,
|
|
1774 |
but not yet
|
|
1775 |
i parallelly tried another method of using retrieve\\
|
|
1776 |
|
|
1777 |
|
|
1778 |
|
|
1779 |
\noindent\rule[0.5ex]{\linewidth}{1pt}
|
|
1780 |
|
|
1781 |
|
|
1782 |
|
|
1783 |
|
|
1784 |
|
|
1785 |
|
|
1786 |
\bibliographystyle{plain}
|
|
1787 |
\bibliography{root}
|
|
1788 |
|
|
1789 |
|
|
1790 |
\end{document}
|
118
|
1791 |
|