handouts/ho06.tex
author Christian Urban <urbanc@in.tum.de>
Thu, 25 Oct 2018 18:36:04 +0100
changeset 590 c6a1e19e9801
parent 589 0451b8b67f62
child 591 863e502f6a5c
permissions -rw-r--r--
updated
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
584
529460073b24 updated
Christian Urban <urbanc@in.tum.de>
parents: 392
diff changeset
     1
173
7cfb7a6f7c99 added slides
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
     2
\documentclass{article}
297
5c51839c88fd updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 292
diff changeset
     3
\usepackage{../style}
217
cd6066f1056a updated handouts
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 183
diff changeset
     4
\usepackage{../langs}
588
a4646557016d updated
Christian Urban <urbanc@in.tum.de>
parents: 587
diff changeset
     5
\usepackage{../grammar}
173
7cfb7a6f7c99 added slides
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
     6
7cfb7a6f7c99 added slides
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
     7
\begin{document}
7cfb7a6f7c99 added slides
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
     8
292
7ed2a25dd115 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 217
diff changeset
     9
\section*{Handout 6 (Parser Combinators)}
173
7cfb7a6f7c99 added slides
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    10
584
529460073b24 updated
Christian Urban <urbanc@in.tum.de>
parents: 392
diff changeset
    11
This handout explains how \emph{parser combinators} work and how they
587
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
    12
can be implemented in Scala. Their most distinguishing feature is that
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
    13
they are very easy to implement (admittedly it is only easy in a
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
    14
functional programming language).  Another good point of parser
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
    15
combinators is that they can deal with any kind of input as long as
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
    16
this input is of ``sequence-kind'', for example a string or a list of
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
    17
tokens. The only two properties of the input we need is to be able to
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
    18
test when it is empty and ``sequentially'' take it apart. Strings and
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
    19
lists fit this bill. However, parser combinators also have their
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
    20
drawbacks. For example they require that the grammar to be parsed is
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
    21
\emph{not} left-recursive and they are efficient only when the grammar
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
    22
is unambiguous. It is the responsibility of the grammar designer to
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
    23
ensure these two properties.
173
7cfb7a6f7c99 added slides
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    24
587
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
    25
The general idea behind parser combinators is to transform the input
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
    26
into sets of pairs, like so
175
5801e8c0e528 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 173
diff changeset
    27
5801e8c0e528 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 173
diff changeset
    28
\begin{center}
385
7f8516ff408d updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 297
diff changeset
    29
$\underbrace{\text{list of tokens}}_{\text{input}}$ 
7f8516ff408d updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 297
diff changeset
    30
$\Rightarrow$
7f8516ff408d updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 297
diff changeset
    31
$\underbrace{\text{set of (parsed input, unparsed input)}}_{\text{output}}$
7f8516ff408d updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 297
diff changeset
    32
\end{center} 
175
5801e8c0e528 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 173
diff changeset
    33
587
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
    34
\noindent
590
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
    35
Given the extended effort we have spent implementing a lexer in order
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
    36
to generate list of tokens, it might be surprising that in what
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
    37
follows we shall often use strings as input, rather than list of
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
    38
tokens. This is for making the explanation more lucid. It does not
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
    39
make our previous work on lexers obsolete (remember they transform a
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
    40
string into a list of tokens). Lexers will still be needed for
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
    41
building a somewhat realistic compiler.
584
529460073b24 updated
Christian Urban <urbanc@in.tum.de>
parents: 392
diff changeset
    42
590
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
    43
As mentioned above, parser combinators are relatively agnostic about what
587
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
    44
kind of input they process. In my Scala code I use the following
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
    45
polymorphic types for parser combinators:
176
3c2653fc8b5a updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 175
diff changeset
    46
3c2653fc8b5a updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 175
diff changeset
    47
\begin{center}
584
529460073b24 updated
Christian Urban <urbanc@in.tum.de>
parents: 392
diff changeset
    48
input:\;\; \texttt{I}  \qquad output:\;\; \texttt{T}
176
3c2653fc8b5a updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 175
diff changeset
    49
\end{center}
3c2653fc8b5a updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 175
diff changeset
    50
587
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
    51
\noindent That is they take as input something of type \texttt{I} and
590
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
    52
return a set of pairs of type \texttt{Set[(T, I)]}. Since the input
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
    53
needs to be of ``sequence-kind'', I actually have to often write
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
    54
\texttt{I <\% Seq[\_]} for the input type. This ensures the input is a
584
529460073b24 updated
Christian Urban <urbanc@in.tum.de>
parents: 392
diff changeset
    55
subtype of Scala sequences. The first component of the generated pairs
529460073b24 updated
Christian Urban <urbanc@in.tum.de>
parents: 392
diff changeset
    56
corresponds to what the parser combinator was able to process from the
590
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
    57
input and the second is the unprocessed part, or leftover, of the
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
    58
input (therefore the type of this unprocessed part is the same as the
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
    59
input). A parser combinator might return more than one such pair; the
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
    60
idea is that there are potentially several ways of how to parse the
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
    61
input.  As a concrete example, consider the string
183
b17eff695c7f added new stuff
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 177
diff changeset
    62
b17eff695c7f added new stuff
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 177
diff changeset
    63
\begin{center}
b17eff695c7f added new stuff
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 177
diff changeset
    64
\tt\Grid{iffoo\VS testbar}
b17eff695c7f added new stuff
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 177
diff changeset
    65
\end{center}
b17eff695c7f added new stuff
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 177
diff changeset
    66
385
7f8516ff408d updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 297
diff changeset
    67
\noindent We might have a parser combinator which tries to
386
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 385
diff changeset
    68
interpret this string as a keyword (\texttt{if}) or as an
385
7f8516ff408d updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 297
diff changeset
    69
identifier (\texttt{iffoo}). Then the output will be the set
177
53def1fbf472 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 176
diff changeset
    70
183
b17eff695c7f added new stuff
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 177
diff changeset
    71
\begin{center}
386
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 385
diff changeset
    72
$\left\{ \left(\texttt{\Grid{if}}\;,\; \texttt{\Grid{foo\VS testbar}}\right), 
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 385
diff changeset
    73
           \left(\texttt{\Grid{iffoo}}\;,\; \texttt{\Grid{\VS testbar}}\right) \right\}$
183
b17eff695c7f added new stuff
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 177
diff changeset
    74
\end{center}
b17eff695c7f added new stuff
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 177
diff changeset
    75
587
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
    76
\noindent where the first pair means the parser could recognise
590
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
    77
\texttt{if} from the input and leaves the \texttt{foo\VS testbar} as
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
    78
`unprocessed' part; in the other case it could recognise
587
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
    79
\texttt{iffoo} and leaves \texttt{\VS testbar} as unprocessed. If the
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
    80
parser cannot recognise anything from the input at all, then parser
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
    81
combinators just return the empty set $\{\}$. This will indicate
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
    82
something ``went wrong''\ldots or more precisely, nothing could be
385
7f8516ff408d updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 297
diff changeset
    83
parsed.
183
b17eff695c7f added new stuff
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 177
diff changeset
    84
584
529460073b24 updated
Christian Urban <urbanc@in.tum.de>
parents: 392
diff changeset
    85
Also important to note is that the type \texttt{T} for the processed
590
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
    86
part is different from the input type \texttt{I} in the parse. In the
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
    87
example above is just happens to be the same. The reason for the
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
    88
potential difference is that in general we are interested in
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
    89
transforming our input into something ``different''\ldots for example
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
    90
into a tree; or if we implement the grammar for arithmetic
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
    91
expressions, we might be interested in the actual integer number the
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
    92
arithmetic expression, say \texttt{1 + 2 * 3}, stands for. In this way
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
    93
we can use parser combinators to implement relatively easily a
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
    94
calculator, for instance.
584
529460073b24 updated
Christian Urban <urbanc@in.tum.de>
parents: 392
diff changeset
    95
529460073b24 updated
Christian Urban <urbanc@in.tum.de>
parents: 392
diff changeset
    96
The main idea of parser combinators is that we can easily build parser
529460073b24 updated
Christian Urban <urbanc@in.tum.de>
parents: 392
diff changeset
    97
combinators out of smaller components following very closely the
529460073b24 updated
Christian Urban <urbanc@in.tum.de>
parents: 392
diff changeset
    98
structure of a grammar. In order to implement this in an
529460073b24 updated
Christian Urban <urbanc@in.tum.de>
parents: 392
diff changeset
    99
object-oriented programming language, like Scala, we need to specify
529460073b24 updated
Christian Urban <urbanc@in.tum.de>
parents: 392
diff changeset
   100
an abstract class for parser combinators. This abstract class states
529460073b24 updated
Christian Urban <urbanc@in.tum.de>
parents: 392
diff changeset
   101
that the function \texttt{parse} takes an argument of type \texttt{I}
529460073b24 updated
Christian Urban <urbanc@in.tum.de>
parents: 392
diff changeset
   102
and returns a set of type \mbox{\texttt{Set[(T, I)]}}.
177
53def1fbf472 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 176
diff changeset
   103
53def1fbf472 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 176
diff changeset
   104
\begin{center}
385
7f8516ff408d updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 297
diff changeset
   105
\begin{lstlisting}[language=Scala]
177
53def1fbf472 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 176
diff changeset
   106
abstract class Parser[I, T] {
590
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   107
  def parse(in: I) : Set[(T, I)]
177
53def1fbf472 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 176
diff changeset
   108
590
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   109
  def parse_all(in: I) : Set[T] =
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   110
    for ((head, tail) <- parse(in); if (tail.isEmpty)) 
177
53def1fbf472 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 176
diff changeset
   111
      yield head
53def1fbf472 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 176
diff changeset
   112
}
53def1fbf472 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 176
diff changeset
   113
\end{lstlisting}
53def1fbf472 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 176
diff changeset
   114
\end{center}
176
3c2653fc8b5a updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 175
diff changeset
   115
584
529460073b24 updated
Christian Urban <urbanc@in.tum.de>
parents: 392
diff changeset
   116
\noindent It is the obligation in each instance (parser combinator) to
529460073b24 updated
Christian Urban <urbanc@in.tum.de>
parents: 392
diff changeset
   117
supply an implementation for \texttt{parse}.  From this function we
529460073b24 updated
Christian Urban <urbanc@in.tum.de>
parents: 392
diff changeset
   118
can then ``centrally'' derive the function \texttt{parse\_all}, which
529460073b24 updated
Christian Urban <urbanc@in.tum.de>
parents: 392
diff changeset
   119
just filters out all pairs whose second component is not empty (that
529460073b24 updated
Christian Urban <urbanc@in.tum.de>
parents: 392
diff changeset
   120
is has still some unprocessed part). The reason is that at the end of
529460073b24 updated
Christian Urban <urbanc@in.tum.de>
parents: 392
diff changeset
   121
the parsing we are only interested in the results where all the input
529460073b24 updated
Christian Urban <urbanc@in.tum.de>
parents: 392
diff changeset
   122
has been consumed and no unprocessed part is left over.
183
b17eff695c7f added new stuff
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 177
diff changeset
   123
385
7f8516ff408d updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 297
diff changeset
   124
One of the simplest parser combinators recognises just a
584
529460073b24 updated
Christian Urban <urbanc@in.tum.de>
parents: 392
diff changeset
   125
single character, say $c$, from the beginning of strings. Its
385
7f8516ff408d updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 297
diff changeset
   126
behaviour can be described as follows:
176
3c2653fc8b5a updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 175
diff changeset
   127
177
53def1fbf472 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 176
diff changeset
   128
\begin{itemize}
584
529460073b24 updated
Christian Urban <urbanc@in.tum.de>
parents: 392
diff changeset
   129
\item If the head of the input string starts with a $c$, then return 
529460073b24 updated
Christian Urban <urbanc@in.tum.de>
parents: 392
diff changeset
   130
  the set
529460073b24 updated
Christian Urban <urbanc@in.tum.de>
parents: 392
diff changeset
   131
  \[\{(c, \textit{tail of}\; s)\}\]
529460073b24 updated
Christian Urban <urbanc@in.tum.de>
parents: 392
diff changeset
   132
  where \textit{tail of} 
529460073b24 updated
Christian Urban <urbanc@in.tum.de>
parents: 392
diff changeset
   133
  $s$ is the unprocessed part of the input string.
529460073b24 updated
Christian Urban <urbanc@in.tum.de>
parents: 392
diff changeset
   134
\item Otherwise return the empty set $\{\}$.	
177
53def1fbf472 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 176
diff changeset
   135
\end{itemize}
53def1fbf472 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 176
diff changeset
   136
53def1fbf472 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 176
diff changeset
   137
\noindent
590
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   138
The input type of this simple parser combinator is \texttt{String} and
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   139
the output type is \texttt{Char}. This means \texttt{parse} returns
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   140
\mbox{\texttt{Set[(Char, String)]}}.  The code in Scala is as follows:
177
53def1fbf472 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 176
diff changeset
   141
53def1fbf472 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 176
diff changeset
   142
\begin{center}
53def1fbf472 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 176
diff changeset
   143
\begin{lstlisting}[language=Scala,basicstyle=\small\ttfamily, numbers=none]
53def1fbf472 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 176
diff changeset
   144
case class CharParser(c: Char) extends Parser[String, Char] {
587
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   145
  def parse(in: String) = 
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   146
    if (in.head == c) Set((c, in.tail)) else Set()
177
53def1fbf472 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 176
diff changeset
   147
}
53def1fbf472 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 176
diff changeset
   148
\end{lstlisting}
53def1fbf472 updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 176
diff changeset
   149
\end{center}
176
3c2653fc8b5a updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 175
diff changeset
   150
589
0451b8b67f62 updated
Christian Urban <urbanc@in.tum.de>
parents: 588
diff changeset
   151
\noindent You can see \texttt{parse} tests whether the
587
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   152
first character of the input string \texttt{in} is equal to
584
529460073b24 updated
Christian Urban <urbanc@in.tum.de>
parents: 392
diff changeset
   153
\texttt{c}. If yes, then it splits the string into the recognised part
587
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   154
\texttt{c} and the unprocessed part \texttt{in.tail}. In case
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   155
\texttt{in} does not start with \texttt{c} then the parser returns the
584
529460073b24 updated
Christian Urban <urbanc@in.tum.de>
parents: 392
diff changeset
   156
empty set (in Scala \texttt{Set()}). Since this parser recognises
529460073b24 updated
Christian Urban <urbanc@in.tum.de>
parents: 392
diff changeset
   157
characters and just returns characters as the processed part, the
529460073b24 updated
Christian Urban <urbanc@in.tum.de>
parents: 392
diff changeset
   158
output type of the parser is \texttt{Char}.
529460073b24 updated
Christian Urban <urbanc@in.tum.de>
parents: 392
diff changeset
   159
529460073b24 updated
Christian Urban <urbanc@in.tum.de>
parents: 392
diff changeset
   160
If we want to parse a list of tokens and interested in recognising a
590
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   161
number token, for example, we could write something like this
584
529460073b24 updated
Christian Urban <urbanc@in.tum.de>
parents: 392
diff changeset
   162
529460073b24 updated
Christian Urban <urbanc@in.tum.de>
parents: 392
diff changeset
   163
\begin{center}
529460073b24 updated
Christian Urban <urbanc@in.tum.de>
parents: 392
diff changeset
   164
\begin{lstlisting}[language=Scala,basicstyle=\small\ttfamily,numbers=none]
529460073b24 updated
Christian Urban <urbanc@in.tum.de>
parents: 392
diff changeset
   165
case object NumParser extends Parser[List[Token], Int] {
529460073b24 updated
Christian Urban <urbanc@in.tum.de>
parents: 392
diff changeset
   166
  def parse(ts: List[Token]) = ts match {
529460073b24 updated
Christian Urban <urbanc@in.tum.de>
parents: 392
diff changeset
   167
    case Num_token(s)::ts => Set((s.toInt, ts)) 
529460073b24 updated
Christian Urban <urbanc@in.tum.de>
parents: 392
diff changeset
   168
    case _ => Set ()
529460073b24 updated
Christian Urban <urbanc@in.tum.de>
parents: 392
diff changeset
   169
  }
529460073b24 updated
Christian Urban <urbanc@in.tum.de>
parents: 392
diff changeset
   170
}
529460073b24 updated
Christian Urban <urbanc@in.tum.de>
parents: 392
diff changeset
   171
\end{lstlisting}
529460073b24 updated
Christian Urban <urbanc@in.tum.de>
parents: 392
diff changeset
   172
\end{center}
529460073b24 updated
Christian Urban <urbanc@in.tum.de>
parents: 392
diff changeset
   173
529460073b24 updated
Christian Urban <urbanc@in.tum.de>
parents: 392
diff changeset
   174
\noindent
529460073b24 updated
Christian Urban <urbanc@in.tum.de>
parents: 392
diff changeset
   175
In this parser the input is of type \texttt{List[Token]}. The function
529460073b24 updated
Christian Urban <urbanc@in.tum.de>
parents: 392
diff changeset
   176
parse looks at the input \texttt{ts} and checks whether the first
589
0451b8b67f62 updated
Christian Urban <urbanc@in.tum.de>
parents: 588
diff changeset
   177
token is a \texttt{Num\_token} (let us assume our lexer generated
0451b8b67f62 updated
Christian Urban <urbanc@in.tum.de>
parents: 588
diff changeset
   178
these tokens for numbers). But this parser does not just return this
584
529460073b24 updated
Christian Urban <urbanc@in.tum.de>
parents: 392
diff changeset
   179
token (and the rest of the list), like the \texttt{CharParser} above,
590
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   180
rather it extracts also the string \texttt{s} from the token and
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   181
converts it into an integer. The hope is that the lexer did its work
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   182
well and this conversion always succeeds. The consequence of this is
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   183
that the output type for this parser is \texttt{Int}, not
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   184
\texttt{Token}. Such a conversion would be needed if we want to
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   185
implement a simple calculator program, because string-numbers need to
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   186
be transformed into \texttt{Int}-numbers in order to do the
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   187
calculations.
385
7f8516ff408d updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 297
diff changeset
   188
7f8516ff408d updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 297
diff changeset
   189
584
529460073b24 updated
Christian Urban <urbanc@in.tum.de>
parents: 392
diff changeset
   190
These simple parsers that just look at the input and do a simple
529460073b24 updated
Christian Urban <urbanc@in.tum.de>
parents: 392
diff changeset
   191
transformation are often called \emph{atomic} parser combinators.
529460073b24 updated
Christian Urban <urbanc@in.tum.de>
parents: 392
diff changeset
   192
More interesting are the parser combinators that build larger parsers
587
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   193
out of smaller component parsers. There are three such parser
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   194
combinators that can be implemented generically. The \emph{alternative
584
529460073b24 updated
Christian Urban <urbanc@in.tum.de>
parents: 392
diff changeset
   195
  parser combinator} is as follows: given two parsers, say, $p$ and
529460073b24 updated
Christian Urban <urbanc@in.tum.de>
parents: 392
diff changeset
   196
$q$, we apply both parsers to the input (remember parsers are
587
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   197
functions) and combine the output (remember they are sets of pairs):
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   198
 
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   199
\begin{center}
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   200
$p(\text{input}) \cup q(\text{input})$
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   201
\end{center}
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   202
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   203
\noindent In Scala we can implement alternative parser
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   204
combinator as follows
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   205
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   206
\begin{center}
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   207
\begin{lstlisting}[language=Scala, numbers=none]
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   208
class AltParser[I, T]
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   209
       (p: => Parser[I, T], 
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   210
        q: => Parser[I, T]) extends Parser[I, T] {
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   211
  def parse(in: I) = p.parse(in) ++ q.parse(in)
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   212
}
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   213
\end{lstlisting}
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   214
\end{center}
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   215
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   216
\noindent The types of this parser combinator are again generic (we
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   217
have \texttt{I} for the input type, and \texttt{T} for the output
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   218
type). The alternative parser builds a new parser out of two existing
590
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   219
parsers \texttt{p} and \texttt{q} which are given as arguments.  Both
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   220
parsers need to be able to process input of type \texttt{I} and return
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   221
in \texttt{parse} the same output type \texttt{Set[(T,
587
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   222
  I)]}.\footnote{There is an interesting detail of Scala, namely the
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   223
  \texttt{=>} in front of the types of \texttt{p} and \texttt{q}. They
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   224
  will prevent the evaluation of the arguments before they are
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   225
  used. This is often called \emph{lazy evaluation} of the
590
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   226
  arguments. We will explain this later.}  The alternative parser runs
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   227
the input with the first parser \texttt{p} (producing a set of pairs)
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   228
and then runs the same input with \texttt{q} (producing another set of
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   229
pairs).  The result should be then just the union of both sets, which
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   230
is the operation \texttt{++} in Scala.
587
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   231
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   232
The alternative parser combinator allows us to construct a parser that
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   233
parses either a character \texttt{a} or \texttt{b} using the
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   234
\texttt{CharParser} shown above. For this we can write
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   235
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   236
\begin{center}
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   237
\begin{lstlisting}[language=Scala, numbers=none]
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   238
new AltParser(CharParser('a'), CharParser('b'))
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   239
\end{lstlisting}
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   240
\end{center}
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   241
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   242
\noindent Later on we will use Scala mechanism for introducing some
589
0451b8b67f62 updated
Christian Urban <urbanc@in.tum.de>
parents: 588
diff changeset
   243
more readable shorthand notation for this, like \texttt{"a" |
587
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   244
  "b"}. Let us look in detail at what this parser combinator produces
590
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   245
with some sample strings.
587
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   246
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   247
\begin{center}
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   248
\begin{tabular}{rcl}
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   249
input strings & & output\medskip\\
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   250
\texttt{\Grid{acde}} & $\rightarrow$ & $\left\{(\texttt{\Grid{a}}, \texttt{\Grid{cde}})\right\}$\\
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   251
\texttt{\Grid{bcde}} & $\rightarrow$ & $\left\{(\texttt{\Grid{b}}, \texttt{\Grid{cde}})\right\}$\\
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   252
\texttt{\Grid{ccde}} & $\rightarrow$ & $\{\}$
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   253
\end{tabular}
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   254
\end{center}
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   255
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   256
\noindent We receive in the first two cases a successful
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   257
output (that is a non-empty set). In each case, either
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   258
\pcode{a} or \pcode{b} is in the processed part, and
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   259
\pcode{cde} in the unprocessed part. Clearly this parser cannot
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   260
parse anything with \pcode{ccde}, therefore the empty
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   261
set is returned.
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   262
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   263
A bit more interesting is the \emph{sequence parser combinator}. Given
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   264
two parsers, say again, $p$ and $q$, we want to apply first the input
590
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   265
to $p$ producing a set of pairs; then apply $q$ to all the unparsed  
587
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   266
parts in the pairs; and then combine the results. Mathematically we would
590
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   267
write something like this for the result set of pairs:
587
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   268
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   269
\begin{center}
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   270
\begin{tabular}{lcl}
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   271
$\{((\textit{output}_1, \textit{output}_2), u_2)$ & $\,|\,$ & 
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   272
$(\textit{output}_1, u_1) \in p(\text{input}) 
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   273
\;\wedge\;$\\
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   274
&& $(\textit{output}_2, u_2) \in q(u_1)\}$
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   275
\end{tabular}
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   276
\end{center}
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   277
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   278
\noindent Notice that the $p$ will first be run on the input,
590
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   279
producing pairs of the form $(\textit{output}_1, u_1)$ where the $u_1$
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   280
stands for the unprocessed, or leftover, parts pf $p$. We want that
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   281
$q$ runs on all these unprocessed parts $u_1$. Therefore these
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   282
unprocessed parts are fed into the second parser $q$. The overall
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   283
result of the sequence parser combinator is pairs of the form
584
529460073b24 updated
Christian Urban <urbanc@in.tum.de>
parents: 392
diff changeset
   284
$((\textit{output}_1, \textit{output}_2), u_2)$. This means the
590
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   285
unprocessed part of the sequqnce p[arser combinator is the unprocessed
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   286
part the second parser $q$ leaves as leftover. The processed parts of
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   287
of the component parsers is a pair consisting of the outputs of $p$
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   288
and $q$, namely $(\textit{output}_1, \textit{output}_2)$. This
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   289
behaviour can be implemented in Scala as follows:
183
b17eff695c7f added new stuff
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 177
diff changeset
   290
b17eff695c7f added new stuff
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 177
diff changeset
   291
\begin{center}
385
7f8516ff408d updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 297
diff changeset
   292
\begin{lstlisting}[language=Scala,numbers=none]
183
b17eff695c7f added new stuff
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 177
diff changeset
   293
class SeqParser[I, T, S]
b17eff695c7f added new stuff
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 177
diff changeset
   294
       (p: => Parser[I, T], 
b17eff695c7f added new stuff
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 177
diff changeset
   295
        q: => Parser[I, S]) extends Parser[I, (T, S)] {
587
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   296
  def parse(in: I) = 
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   297
    for ((output1, u1) <- p.parse(in); 
386
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 385
diff changeset
   298
         (output2, u2) <- q.parse(u1)) 
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 385
diff changeset
   299
            yield ((output1, output2), u2)
183
b17eff695c7f added new stuff
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 177
diff changeset
   300
}
b17eff695c7f added new stuff
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 177
diff changeset
   301
\end{lstlisting}
b17eff695c7f added new stuff
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 177
diff changeset
   302
\end{center}
b17eff695c7f added new stuff
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 177
diff changeset
   303
587
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   304
\noindent This parser takes again as arguments two parsers, \texttt{p}
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   305
and \texttt{q}. It implements \texttt{parse} as follows: let first run
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   306
the parser \texttt{p} on the input producing a set of pairs
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   307
(\texttt{output1}, \texttt{u1}). The \texttt{u1} stands for the
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   308
unprocessed parts left over by \texttt{p}. Let then \texttt{q} run on these
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   309
unprocessed parts producing again a set of pairs. The output of the
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   310
sequence parser combinator is then a set containing pairs where the
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   311
first components are again pairs, namely what the first parser could
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   312
parse together with what the second parser could parse; the second
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   313
component is the unprocessed part left over after running the second
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   314
parser \texttt{q}. Therefore the input type of the sequence parser
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   315
combinator is as usual \texttt{I}, but the output type is
183
b17eff695c7f added new stuff
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 177
diff changeset
   316
b17eff695c7f added new stuff
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 177
diff changeset
   317
\begin{center}
590
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   318
\texttt{(T, S)}
183
b17eff695c7f added new stuff
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 177
diff changeset
   319
\end{center}
b17eff695c7f added new stuff
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 177
diff changeset
   320
584
529460073b24 updated
Christian Urban <urbanc@in.tum.de>
parents: 392
diff changeset
   321
\noindent
590
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   322
This means \texttt{parse} in the sequence parser combinator returns
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   323
sets of type \texttt{Set[((T, S), I)]}.  Notice that we have
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   324
essentially two output types for the sequence parser combinator
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   325
(packaged in a pair), because in general \textit{p} and \textit{q}
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   326
might produce different things (for example first we recognise a
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   327
number and then a string corresponding to an operator).  If any of the
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   328
runs of \textit{p} and \textit{q} fail, that is produce the empty set,
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   329
then \texttt{parse} will also produce the empty set.
584
529460073b24 updated
Christian Urban <urbanc@in.tum.de>
parents: 392
diff changeset
   330
587
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   331
With the shorthand notation we shall introduce later for the sequence
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   332
parser combinator, we can write for example \pcode{"a" ~ "b"}, which
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   333
is the parser combinator that first recognises the character
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   334
\texttt{a} from a string and then \texttt{b}. Let us look again at
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   335
three examples of how this parser combinator processes some strings:
385
7f8516ff408d updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 297
diff changeset
   336
7f8516ff408d updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 297
diff changeset
   337
\begin{center}
7f8516ff408d updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 297
diff changeset
   338
\begin{tabular}{rcl}
7f8516ff408d updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 297
diff changeset
   339
input strings & & output\medskip\\
584
529460073b24 updated
Christian Urban <urbanc@in.tum.de>
parents: 392
diff changeset
   340
\texttt{\Grid{abcde}} & $\rightarrow$ & $\left\{((\texttt{\Grid{a}}, \texttt{\Grid{b}}), \texttt{\Grid{cde}})\right\}$\\
529460073b24 updated
Christian Urban <urbanc@in.tum.de>
parents: 392
diff changeset
   341
\texttt{\Grid{bacde}} & $\rightarrow$ & $\{\}$\\
529460073b24 updated
Christian Urban <urbanc@in.tum.de>
parents: 392
diff changeset
   342
\texttt{\Grid{cccde}} & $\rightarrow$ & $\{\}$
385
7f8516ff408d updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 297
diff changeset
   343
\end{tabular}
7f8516ff408d updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 297
diff changeset
   344
\end{center}
7f8516ff408d updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 297
diff changeset
   345
586
Christian Urban <urbanc@in.tum.de>
parents: 585
diff changeset
   346
\noindent In the first line we have a successful parse, because the
587
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   347
string starts with \texttt{ab}, which is the prefix we are looking
584
529460073b24 updated
Christian Urban <urbanc@in.tum.de>
parents: 392
diff changeset
   348
for. But since the parsing combinator is constructed as sequence of
529460073b24 updated
Christian Urban <urbanc@in.tum.de>
parents: 392
diff changeset
   349
the two simple (atomic) parsers for \texttt{a} and \texttt{b}, the
529460073b24 updated
Christian Urban <urbanc@in.tum.de>
parents: 392
diff changeset
   350
result is a nested pair of the form \texttt{((a, b), cde)}. It is
586
Christian Urban <urbanc@in.tum.de>
parents: 585
diff changeset
   351
\emph{not} a simple pair \texttt{(ab, cde)} as one might erroneously
587
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   352
expect.  The parser returns the empty set in the other examples,
584
529460073b24 updated
Christian Urban <urbanc@in.tum.de>
parents: 392
diff changeset
   353
because they do not fit with what the parser is supposed to parse.
529460073b24 updated
Christian Urban <urbanc@in.tum.de>
parents: 392
diff changeset
   354
529460073b24 updated
Christian Urban <urbanc@in.tum.de>
parents: 392
diff changeset
   355
589
0451b8b67f62 updated
Christian Urban <urbanc@in.tum.de>
parents: 588
diff changeset
   356
A slightly more complicated parser is \pcode{("a" | "b") ~ "c"} which
587
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   357
parses as first character either an \texttt{a} or \texttt{b}, followed
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   358
by a \texttt{c}. This parser produces the following outputs.
385
7f8516ff408d updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 297
diff changeset
   359
7f8516ff408d updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 297
diff changeset
   360
\begin{center}
7f8516ff408d updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 297
diff changeset
   361
\begin{tabular}{rcl}
7f8516ff408d updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 297
diff changeset
   362
input strings & & output\medskip\\
585
6ee22f196884 updated
Christian Urban <urbanc@in.tum.de>
parents: 584
diff changeset
   363
\texttt{\Grid{acde}} & $\rightarrow$ & $\left\{((\texttt{\Grid{a}}, \texttt{\Grid{c}}), \texttt{\Grid{de}})\right\}$\\
6ee22f196884 updated
Christian Urban <urbanc@in.tum.de>
parents: 584
diff changeset
   364
\texttt{\Grid{bcde}} & $\rightarrow$ & $\left\{((\texttt{\Grid{b}}, \texttt{\Grid{c}}), \texttt{\Grid{de}})\right\}$\\
6ee22f196884 updated
Christian Urban <urbanc@in.tum.de>
parents: 584
diff changeset
   365
\texttt{\Grid{abde}} & $\rightarrow$ & $\{\}$
385
7f8516ff408d updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 297
diff changeset
   366
\end{tabular}
7f8516ff408d updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 297
diff changeset
   367
\end{center}
7f8516ff408d updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 297
diff changeset
   368
585
6ee22f196884 updated
Christian Urban <urbanc@in.tum.de>
parents: 584
diff changeset
   369
\noindent
6ee22f196884 updated
Christian Urban <urbanc@in.tum.de>
parents: 584
diff changeset
   370
Now consider the parser \pcode{("a" ~ "b") ~ "c"} which parses
6ee22f196884 updated
Christian Urban <urbanc@in.tum.de>
parents: 584
diff changeset
   371
\texttt{a}, \texttt{b}, \texttt{c} in sequence. This parser produces
6ee22f196884 updated
Christian Urban <urbanc@in.tum.de>
parents: 584
diff changeset
   372
the following outputs.
6ee22f196884 updated
Christian Urban <urbanc@in.tum.de>
parents: 584
diff changeset
   373
6ee22f196884 updated
Christian Urban <urbanc@in.tum.de>
parents: 584
diff changeset
   374
\begin{center}
6ee22f196884 updated
Christian Urban <urbanc@in.tum.de>
parents: 584
diff changeset
   375
\begin{tabular}{rcl}
6ee22f196884 updated
Christian Urban <urbanc@in.tum.de>
parents: 584
diff changeset
   376
input strings & & output\medskip\\
6ee22f196884 updated
Christian Urban <urbanc@in.tum.de>
parents: 584
diff changeset
   377
\texttt{\Grid{abcde}} & $\rightarrow$ & $\left\{(((\texttt{\Grid{a}},\texttt{\Grid{b}}), \texttt{\Grid{c}}), \texttt{\Grid{de}})\right\}$\\
6ee22f196884 updated
Christian Urban <urbanc@in.tum.de>
parents: 584
diff changeset
   378
\texttt{\Grid{abde}} & $\rightarrow$ & $\{\}$\\
6ee22f196884 updated
Christian Urban <urbanc@in.tum.de>
parents: 584
diff changeset
   379
\texttt{\Grid{bcde}} & $\rightarrow$ & $\{\}$
6ee22f196884 updated
Christian Urban <urbanc@in.tum.de>
parents: 584
diff changeset
   380
\end{tabular}
6ee22f196884 updated
Christian Urban <urbanc@in.tum.de>
parents: 584
diff changeset
   381
\end{center}
6ee22f196884 updated
Christian Urban <urbanc@in.tum.de>
parents: 584
diff changeset
   382
6ee22f196884 updated
Christian Urban <urbanc@in.tum.de>
parents: 584
diff changeset
   383
6ee22f196884 updated
Christian Urban <urbanc@in.tum.de>
parents: 584
diff changeset
   384
\noindent The second and third example fail, because something is
590
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   385
``missing'' in the sequence we are looking for. The first succeeds but
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   386
notice how the results nest with sequences: the parsed part is a
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   387
nested pair of the form \pcode{((a, b), c)}. If we nest the sequence
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   388
parser differently, for example \pcode{"a" ~ ("b" ~ "c")}, then also
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   389
our output pairs nest differently
589
0451b8b67f62 updated
Christian Urban <urbanc@in.tum.de>
parents: 588
diff changeset
   390
0451b8b67f62 updated
Christian Urban <urbanc@in.tum.de>
parents: 588
diff changeset
   391
\begin{center}
0451b8b67f62 updated
Christian Urban <urbanc@in.tum.de>
parents: 588
diff changeset
   392
\begin{tabular}{rcl}
0451b8b67f62 updated
Christian Urban <urbanc@in.tum.de>
parents: 588
diff changeset
   393
input strings & & output\medskip\\
0451b8b67f62 updated
Christian Urban <urbanc@in.tum.de>
parents: 588
diff changeset
   394
\texttt{\Grid{abcde}} & $\rightarrow$ & $\left\{((\texttt{\Grid{a}},(\texttt{\Grid{b}}, \texttt{\Grid{c}})), \texttt{\Grid{de}})\right\}$\\
0451b8b67f62 updated
Christian Urban <urbanc@in.tum.de>
parents: 588
diff changeset
   395
\end{tabular}
0451b8b67f62 updated
Christian Urban <urbanc@in.tum.de>
parents: 588
diff changeset
   396
\end{center}
0451b8b67f62 updated
Christian Urban <urbanc@in.tum.de>
parents: 588
diff changeset
   397
0451b8b67f62 updated
Christian Urban <urbanc@in.tum.de>
parents: 588
diff changeset
   398
\noindent
0451b8b67f62 updated
Christian Urban <urbanc@in.tum.de>
parents: 588
diff changeset
   399
Two more examples: first consider the parser
585
6ee22f196884 updated
Christian Urban <urbanc@in.tum.de>
parents: 584
diff changeset
   400
\pcode{("a" ~ "a") ~ "a"} and the input \pcode{aaaa}:
183
b17eff695c7f added new stuff
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 177
diff changeset
   401
b17eff695c7f added new stuff
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 177
diff changeset
   402
\begin{center}
b17eff695c7f added new stuff
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 177
diff changeset
   403
\begin{tabular}{rcl}
b17eff695c7f added new stuff
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 177
diff changeset
   404
input string & & output\medskip\\
385
7f8516ff408d updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 297
diff changeset
   405
\texttt{\Grid{aaaa}} & $\rightarrow$ & 
7f8516ff408d updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 297
diff changeset
   406
$\left\{(((\texttt{\Grid{a}}, \texttt{\Grid{a}}), \texttt{\Grid{a}}), \texttt{\Grid{a}})\right\}$\\
183
b17eff695c7f added new stuff
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 177
diff changeset
   407
\end{tabular}
b17eff695c7f added new stuff
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 177
diff changeset
   408
\end{center}
b17eff695c7f added new stuff
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 177
diff changeset
   409
587
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   410
\noindent Notice how again the results nest deeper and deeper as pairs (the
585
6ee22f196884 updated
Christian Urban <urbanc@in.tum.de>
parents: 584
diff changeset
   411
last \pcode{a} is in the unprocessed part). To consume everything of
6ee22f196884 updated
Christian Urban <urbanc@in.tum.de>
parents: 584
diff changeset
   412
this string we can use the parser \pcode{(("a" ~ "a") ~ "a") ~
6ee22f196884 updated
Christian Urban <urbanc@in.tum.de>
parents: 584
diff changeset
   413
  "a"}. Then the output is as follows:
183
b17eff695c7f added new stuff
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 177
diff changeset
   414
b17eff695c7f added new stuff
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 177
diff changeset
   415
\begin{center}
b17eff695c7f added new stuff
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 177
diff changeset
   416
\begin{tabular}{rcl}
b17eff695c7f added new stuff
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 177
diff changeset
   417
input string & & output\medskip\\
385
7f8516ff408d updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 297
diff changeset
   418
\texttt{\Grid{aaaa}} & $\rightarrow$ & 
7f8516ff408d updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 297
diff changeset
   419
$\left\{((((\texttt{\Grid{a}}, \texttt{\Grid{a}}), \texttt{\Grid{a}}), \texttt{\Grid{a}}), \texttt{""})\right\}$\\
183
b17eff695c7f added new stuff
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 177
diff changeset
   420
\end{tabular}
b17eff695c7f added new stuff
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 177
diff changeset
   421
\end{center}
b17eff695c7f added new stuff
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 177
diff changeset
   422
385
7f8516ff408d updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 297
diff changeset
   423
\noindent This is an instance where the parser consumed
7f8516ff408d updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 297
diff changeset
   424
completely the input, meaning the unprocessed part is just the
587
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   425
empty string. So if we called \pcode{parse_all}, instead of \pcode{parse},
585
6ee22f196884 updated
Christian Urban <urbanc@in.tum.de>
parents: 584
diff changeset
   426
we would get back the result
6ee22f196884 updated
Christian Urban <urbanc@in.tum.de>
parents: 584
diff changeset
   427
6ee22f196884 updated
Christian Urban <urbanc@in.tum.de>
parents: 584
diff changeset
   428
\[
6ee22f196884 updated
Christian Urban <urbanc@in.tum.de>
parents: 584
diff changeset
   429
\left\{(((\texttt{\Grid{a}}, \texttt{\Grid{a}}), \texttt{\Grid{a}}), \texttt{\Grid{a}})\right\}
6ee22f196884 updated
Christian Urban <urbanc@in.tum.de>
parents: 584
diff changeset
   430
\]
6ee22f196884 updated
Christian Urban <urbanc@in.tum.de>
parents: 584
diff changeset
   431
6ee22f196884 updated
Christian Urban <urbanc@in.tum.de>
parents: 584
diff changeset
   432
\noindent where the unprocessed (empty) parts have been stripped away
6ee22f196884 updated
Christian Urban <urbanc@in.tum.de>
parents: 584
diff changeset
   433
from the pairs; everything where the second part was not empty has
587
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   434
been thrown away as well, because they represent
590
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   435
ultimately-unsuccessful-parses. The main point is that the sequence
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   436
parser combinator returns pairs that can nest according to the
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   437
nesting of the component parsers.
385
7f8516ff408d updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 297
diff changeset
   438
183
b17eff695c7f added new stuff
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 177
diff changeset
   439
590
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   440
Consider also carefully that constructing a parser such \pcode{"a" |
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   441
  ("a" ~ "b")} will result in a typing error. The intention with this
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   442
parser is that we want to parse an \texttt{a}, or an \texttt{a}
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   443
followed by a \texttt{b}. However, the first parser has as output type
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   444
a single character (recall the type of \texttt{CharParser}), but the
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   445
second parser produces a pair of characters as output. The alternative
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   446
parser is required to have both component parsers to have the same
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   447
type---we need to be able to build the union of two sets, which means
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   448
in Scala they need to be of the same type.  Since ther are not, there
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   449
is a typing error in this example.  We will see later how we can build
587
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   450
this parser without the typing error.
385
7f8516ff408d updated
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 297
diff changeset
   451
587
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   452
The next parser combinator, called \emph{semantic action}, does not
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   453
actually combine smaller parsers, but applies a function to the result
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   454
of a parser.  It is implemented in Scala as follows
183
b17eff695c7f added new stuff
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 177
diff changeset
   455
b17eff695c7f added new stuff
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 177
diff changeset
   456
\begin{center}
b17eff695c7f added new stuff
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 177
diff changeset
   457
\begin{lstlisting}[language=Scala,basicstyle=\small\ttfamily, numbers=none]
b17eff695c7f added new stuff
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 177
diff changeset
   458
class FunParser[I, T, S]
b17eff695c7f added new stuff
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 177
diff changeset
   459
         (p: => Parser[I, T], 
b17eff695c7f added new stuff
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 177
diff changeset
   460
          f: T => S) extends Parser[I, S] {
587
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   461
  def parse(in: I) = 
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   462
    for ((head, tail) <- p.parse(in)) yield (f(head), tail)
183
b17eff695c7f added new stuff
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 177
diff changeset
   463
}
b17eff695c7f added new stuff
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 177
diff changeset
   464
\end{lstlisting}
b17eff695c7f added new stuff
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 177
diff changeset
   465
\end{center}
b17eff695c7f added new stuff
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 177
diff changeset
   466
b17eff695c7f added new stuff
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 177
diff changeset
   467
590
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   468
\noindent This parser combinator takes a parser \texttt{p} (with input
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   469
type \texttt{I} and output type \texttt{T}) as one argument but also a
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   470
function \texttt{f} (with type \texttt{T => S}). The parser \texttt{p}
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   471
produces sets of type \texttt{Set[(T, I)]}. The semantic action
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   472
combinator then applies the function \texttt{f} to all the `processed'
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   473
parser outputs. Since this function is of type \texttt{T => S}, we
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   474
obtain a parser with output type \texttt{S}. Again Scala lets us
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   475
introduce some shorthand notation for this parser
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   476
combinator. Therefore we will write \texttt{p ==> f} for it.
386
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 385
diff changeset
   477
589
0451b8b67f62 updated
Christian Urban <urbanc@in.tum.de>
parents: 588
diff changeset
   478
What are semantic actions good for? Well, they allow you to transform
590
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   479
the parsed input into datastructures you can use for further
587
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   480
processing. A simple example would be to transform parsed characters
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   481
into ASCII numbers. Suppose we define a function \texttt{f} (from
589
0451b8b67f62 updated
Christian Urban <urbanc@in.tum.de>
parents: 588
diff changeset
   482
characters to ints) and use a \texttt{CharParser} for parsing
0451b8b67f62 updated
Christian Urban <urbanc@in.tum.de>
parents: 588
diff changeset
   483
the character \texttt{c}.
587
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   484
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   485
\begin{center}
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   486
\begin{lstlisting}[language=Scala,basicstyle=\small\ttfamily, numbers=none]
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   487
val f = (c: Char) => c.toInt
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   488
val c = new CharParser('c')
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   489
\end{lstlisting}
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   490
\end{center}
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   491
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   492
\noindent
589
0451b8b67f62 updated
Christian Urban <urbanc@in.tum.de>
parents: 588
diff changeset
   493
We then can run the following two parsers on the input \texttt{cbd}:
587
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   494
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   495
\begin{center}
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   496
\begin{lstlisting}[language=Scala,basicstyle=\small\ttfamily, numbers=none]
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   497
c.parse("cbd")
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   498
(c ==> f).parse("cbd")
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   499
\end{lstlisting}
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   500
\end{center}
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   501
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   502
\noindent
589
0451b8b67f62 updated
Christian Urban <urbanc@in.tum.de>
parents: 588
diff changeset
   503
In the first line we obtain the expected result \texttt{Set(('c',
0451b8b67f62 updated
Christian Urban <urbanc@in.tum.de>
parents: 588
diff changeset
   504
  "bd"))}, whereas the second produces \texttt{Set((99, "bd"))}---the
0451b8b67f62 updated
Christian Urban <urbanc@in.tum.de>
parents: 588
diff changeset
   505
character has been transformed into an ASCII number.
588
a4646557016d updated
Christian Urban <urbanc@in.tum.de>
parents: 587
diff changeset
   506
a4646557016d updated
Christian Urban <urbanc@in.tum.de>
parents: 587
diff changeset
   507
A slightly less contrived example is about parsing numbers (recall
a4646557016d updated
Christian Urban <urbanc@in.tum.de>
parents: 587
diff changeset
   508
\texttt{NumParser} above). However, we want to do this here for strings.
a4646557016d updated
Christian Urban <urbanc@in.tum.de>
parents: 587
diff changeset
   509
For this assume we have the following \texttt{RegexParser}.
a4646557016d updated
Christian Urban <urbanc@in.tum.de>
parents: 587
diff changeset
   510
a4646557016d updated
Christian Urban <urbanc@in.tum.de>
parents: 587
diff changeset
   511
\begin{center}
a4646557016d updated
Christian Urban <urbanc@in.tum.de>
parents: 587
diff changeset
   512
  \begin{lstlisting}[language=Scala,xleftmargin=0mm,
a4646557016d updated
Christian Urban <urbanc@in.tum.de>
parents: 587
diff changeset
   513
    basicstyle=\small\ttfamily, numbers=none]
a4646557016d updated
Christian Urban <urbanc@in.tum.de>
parents: 587
diff changeset
   514
import scala.util.matching.Regex
a4646557016d updated
Christian Urban <urbanc@in.tum.de>
parents: 587
diff changeset
   515
    
a4646557016d updated
Christian Urban <urbanc@in.tum.de>
parents: 587
diff changeset
   516
case class RegexParser(reg: Regex) extends Parser[String, String] {
a4646557016d updated
Christian Urban <urbanc@in.tum.de>
parents: 587
diff changeset
   517
  def parse(in: String) = reg.findPrefixMatchOf(in) match {
a4646557016d updated
Christian Urban <urbanc@in.tum.de>
parents: 587
diff changeset
   518
    case None => Set()
a4646557016d updated
Christian Urban <urbanc@in.tum.de>
parents: 587
diff changeset
   519
    case Some(m) => Set((m.matched, m.after.toString))  
a4646557016d updated
Christian Urban <urbanc@in.tum.de>
parents: 587
diff changeset
   520
  }
a4646557016d updated
Christian Urban <urbanc@in.tum.de>
parents: 587
diff changeset
   521
}
a4646557016d updated
Christian Urban <urbanc@in.tum.de>
parents: 587
diff changeset
   522
\end{lstlisting}
a4646557016d updated
Christian Urban <urbanc@in.tum.de>
parents: 587
diff changeset
   523
\end{center}
a4646557016d updated
Christian Urban <urbanc@in.tum.de>
parents: 587
diff changeset
   524
a4646557016d updated
Christian Urban <urbanc@in.tum.de>
parents: 587
diff changeset
   525
\noindent
a4646557016d updated
Christian Urban <urbanc@in.tum.de>
parents: 587
diff changeset
   526
This parser takes a regex as argument and splits up a string into a
a4646557016d updated
Christian Urban <urbanc@in.tum.de>
parents: 587
diff changeset
   527
prefix and the rest according to this regex
a4646557016d updated
Christian Urban <urbanc@in.tum.de>
parents: 587
diff changeset
   528
(\texttt{reg.findPrefixMatchOf} generates a match---in the successful
a4646557016d updated
Christian Urban <urbanc@in.tum.de>
parents: 587
diff changeset
   529
case---and the corresponding strings can be extracted with
589
0451b8b67f62 updated
Christian Urban <urbanc@in.tum.de>
parents: 588
diff changeset
   530
\texttt{matched} and \texttt{after}). Using this parser we can define a
588
a4646557016d updated
Christian Urban <urbanc@in.tum.de>
parents: 587
diff changeset
   531
\texttt{NumParser} for strings as follows:
a4646557016d updated
Christian Urban <urbanc@in.tum.de>
parents: 587
diff changeset
   532
a4646557016d updated
Christian Urban <urbanc@in.tum.de>
parents: 587
diff changeset
   533
\begin{center}
a4646557016d updated
Christian Urban <urbanc@in.tum.de>
parents: 587
diff changeset
   534
\begin{lstlisting}[language=Scala,basicstyle=\small\ttfamily, numbers=none]
a4646557016d updated
Christian Urban <urbanc@in.tum.de>
parents: 587
diff changeset
   535
val NumParser = RegexParser("[0-9]+".r)
a4646557016d updated
Christian Urban <urbanc@in.tum.de>
parents: 587
diff changeset
   536
\end{lstlisting}
a4646557016d updated
Christian Urban <urbanc@in.tum.de>
parents: 587
diff changeset
   537
\end{center}
a4646557016d updated
Christian Urban <urbanc@in.tum.de>
parents: 587
diff changeset
   538
a4646557016d updated
Christian Urban <urbanc@in.tum.de>
parents: 587
diff changeset
   539
\noindent
a4646557016d updated
Christian Urban <urbanc@in.tum.de>
parents: 587
diff changeset
   540
This parser will recognise a number at the beginning of a string, for
a4646557016d updated
Christian Urban <urbanc@in.tum.de>
parents: 587
diff changeset
   541
example
a4646557016d updated
Christian Urban <urbanc@in.tum.de>
parents: 587
diff changeset
   542
a4646557016d updated
Christian Urban <urbanc@in.tum.de>
parents: 587
diff changeset
   543
\begin{center}
a4646557016d updated
Christian Urban <urbanc@in.tum.de>
parents: 587
diff changeset
   544
\begin{lstlisting}[language=Scala,basicstyle=\small\ttfamily, numbers=none]
a4646557016d updated
Christian Urban <urbanc@in.tum.de>
parents: 587
diff changeset
   545
NumParser.parse("123abc")
a4646557016d updated
Christian Urban <urbanc@in.tum.de>
parents: 587
diff changeset
   546
\end{lstlisting}
a4646557016d updated
Christian Urban <urbanc@in.tum.de>
parents: 587
diff changeset
   547
\end{center}  
a4646557016d updated
Christian Urban <urbanc@in.tum.de>
parents: 587
diff changeset
   548
a4646557016d updated
Christian Urban <urbanc@in.tum.de>
parents: 587
diff changeset
   549
\noindent
a4646557016d updated
Christian Urban <urbanc@in.tum.de>
parents: 587
diff changeset
   550
produces \texttt{Set((123,abc))}. The problem is that \texttt{123} is
590
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   551
still a string (the required double-quotes are not printed by
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   552
Scala). We want to convert this string into the corresponding
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   553
\texttt{Int}. We can do this as follows using a semantic action
588
a4646557016d updated
Christian Urban <urbanc@in.tum.de>
parents: 587
diff changeset
   554
a4646557016d updated
Christian Urban <urbanc@in.tum.de>
parents: 587
diff changeset
   555
\begin{center}
a4646557016d updated
Christian Urban <urbanc@in.tum.de>
parents: 587
diff changeset
   556
\begin{lstlisting}[language=Scala,basicstyle=\small\ttfamily, numbers=none]
a4646557016d updated
Christian Urban <urbanc@in.tum.de>
parents: 587
diff changeset
   557
(NumParser ==> (s => s.toInt)).parse("123abc")
a4646557016d updated
Christian Urban <urbanc@in.tum.de>
parents: 587
diff changeset
   558
\end{lstlisting}
a4646557016d updated
Christian Urban <urbanc@in.tum.de>
parents: 587
diff changeset
   559
\end{center}  
a4646557016d updated
Christian Urban <urbanc@in.tum.de>
parents: 587
diff changeset
   560
a4646557016d updated
Christian Urban <urbanc@in.tum.de>
parents: 587
diff changeset
   561
\noindent
589
0451b8b67f62 updated
Christian Urban <urbanc@in.tum.de>
parents: 588
diff changeset
   562
The function in the semantic action converts a string into an
588
a4646557016d updated
Christian Urban <urbanc@in.tum.de>
parents: 587
diff changeset
   563
\texttt{Int}. Let us come back to semantic actions when we are going
589
0451b8b67f62 updated
Christian Urban <urbanc@in.tum.de>
parents: 588
diff changeset
   564
to implement actual context-free gammars.
587
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   565
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   566
\subsubsection*{Shorthand notation for parser combinators}
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   567
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   568
Before we proceed, let us just explain the shorthand notation for
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   569
parser combinators. Like for regular expressions, the shorthand notation
590
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   570
will make our life much easier when writing actual parsers. We can define
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   571
some implicits which allow us to write \pcode{p | q}, \pcode{p ~ q} and
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   572
\pcode{p ==> f} as well as to use plain strings for specifying simple
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   573
string parsers.
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   574
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   575
The idea is that this shorthand notation allows us to easily translate
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   576
context-free grammars into code. For example recall our context-free
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   577
grammar for palindromes:
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   578
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   579
\begin{plstx}[margin=3cm]
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   580
: \meta{P} ::=  a\cdot \meta{P}\cdot a | b\cdot \meta{P}\cdot b | a | b | \epsilon\\
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   581
\end{plstx}
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   582
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   583
\noindent
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   584
Each alternative in this grammar translates into an alternative parser
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   585
combinator.  The $\cdot$ can be translated to a sequence parser
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   586
combinator. The parsers for $a$, $b$ and $\epsilon$ can be simply
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   587
written as \texttt{"a"}, \texttt{"b"} and \texttt{""}.
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   588
587
5ddedcd92d84 updated
Christian Urban <urbanc@in.tum.de>
parents: 586
diff changeset
   589
386
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 385
diff changeset
   590
\subsubsection*{How to build parsers using parser combinators?}
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 385
diff changeset
   591
588
a4646557016d updated
Christian Urban <urbanc@in.tum.de>
parents: 587
diff changeset
   592
The beauty of parser combinators is the ease with which they can be
a4646557016d updated
Christian Urban <urbanc@in.tum.de>
parents: 587
diff changeset
   593
implemented and how easy it is to translate context-free grammars into
a4646557016d updated
Christian Urban <urbanc@in.tum.de>
parents: 587
diff changeset
   594
code (though the grammars need to be non-left-recursive). To
590
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   595
demonstrate this recall the grammar for palindromes from above.
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   596
The first idea would be to translate it into the following code
588
a4646557016d updated
Christian Urban <urbanc@in.tum.de>
parents: 587
diff changeset
   597
a4646557016d updated
Christian Urban <urbanc@in.tum.de>
parents: 587
diff changeset
   598
\begin{center}
a4646557016d updated
Christian Urban <urbanc@in.tum.de>
parents: 587
diff changeset
   599
\begin{lstlisting}[language=Scala,basicstyle=\small\ttfamily, numbers=none]
a4646557016d updated
Christian Urban <urbanc@in.tum.de>
parents: 587
diff changeset
   600
lazy val Pal : Parser[String, String] = 
a4646557016d updated
Christian Urban <urbanc@in.tum.de>
parents: 587
diff changeset
   601
  (("a" ~ Pal ~ "a") | ("b" ~ Pal ~ "b") | "a" | "b" | "")
a4646557016d updated
Christian Urban <urbanc@in.tum.de>
parents: 587
diff changeset
   602
\end{lstlisting}
a4646557016d updated
Christian Urban <urbanc@in.tum.de>
parents: 587
diff changeset
   603
\end{center}
a4646557016d updated
Christian Urban <urbanc@in.tum.de>
parents: 587
diff changeset
   604
a4646557016d updated
Christian Urban <urbanc@in.tum.de>
parents: 587
diff changeset
   605
\noindent
590
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   606
Unfortunately, this does not quite work yet as it produces a typing
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   607
error. The reason is that the parsers \texttt{"a"}, \texttt{"b"} and
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   608
\texttt{""} all produce strings as output type and therefore can be
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   609
put into an alternative \texttt{...| "a" | "b" | ""}. But both
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   610
\pcode{"a" ~ Pal ~ "a"} and \pcode{"b" ~ Pal ~ "b"} produce pairs of
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   611
the form $(((\_, \_), \_), \_)$---that is how the sequence parser
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   612
combinator nests results when \pcode{\~} is used between two
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   613
components. The solution is to use a semantic action that ``flattens''
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   614
these pairs and appends the corresponding strings, like
588
a4646557016d updated
Christian Urban <urbanc@in.tum.de>
parents: 587
diff changeset
   615
a4646557016d updated
Christian Urban <urbanc@in.tum.de>
parents: 587
diff changeset
   616
\begin{center}
a4646557016d updated
Christian Urban <urbanc@in.tum.de>
parents: 587
diff changeset
   617
\begin{lstlisting}[language=Scala,basicstyle=\small\ttfamily, numbers=none]
a4646557016d updated
Christian Urban <urbanc@in.tum.de>
parents: 587
diff changeset
   618
lazy val Pal : Parser[String, String] =  
a4646557016d updated
Christian Urban <urbanc@in.tum.de>
parents: 587
diff changeset
   619
  (("a" ~ Pal ~ "a") ==> { case ((x, y), z) => x + y + z } |
a4646557016d updated
Christian Urban <urbanc@in.tum.de>
parents: 587
diff changeset
   620
   ("b" ~ Pal ~ "b") ==> { case ((x, y), z) => x + y + z } |
a4646557016d updated
Christian Urban <urbanc@in.tum.de>
parents: 587
diff changeset
   621
    "a" | "b" | "")
a4646557016d updated
Christian Urban <urbanc@in.tum.de>
parents: 587
diff changeset
   622
\end{lstlisting}
a4646557016d updated
Christian Urban <urbanc@in.tum.de>
parents: 587
diff changeset
   623
\end{center}
a4646557016d updated
Christian Urban <urbanc@in.tum.de>
parents: 587
diff changeset
   624
589
0451b8b67f62 updated
Christian Urban <urbanc@in.tum.de>
parents: 588
diff changeset
   625
\noindent
590
c6a1e19e9801 updated
Christian Urban <urbanc@in.tum.de>
parents: 589
diff changeset
   626
Now in all cases we have strings as output type for the parser variants.
589
0451b8b67f62 updated
Christian Urban <urbanc@in.tum.de>
parents: 588
diff changeset
   627
The semantic action
0451b8b67f62 updated
Christian Urban <urbanc@in.tum.de>
parents: 588
diff changeset
   628
0451b8b67f62 updated
Christian Urban <urbanc@in.tum.de>
parents: 588
diff changeset
   629
0451b8b67f62 updated
Christian Urban <urbanc@in.tum.de>
parents: 588
diff changeset
   630
\noindent
0451b8b67f62 updated
Christian Urban <urbanc@in.tum.de>
parents: 588
diff changeset
   631
Important to note is that we must define \texttt{Pal}-parser as a
0451b8b67f62 updated
Christian Urban <urbanc@in.tum.de>
parents: 588
diff changeset
   632
\emph{lazy} value.
588
a4646557016d updated
Christian Urban <urbanc@in.tum.de>
parents: 587
diff changeset
   633
386
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 385
diff changeset
   634
\subsubsection*{Implementing an Interpreter}
183
b17eff695c7f added new stuff
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 177
diff changeset
   635
b17eff695c7f added new stuff
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 177
diff changeset
   636
%\bigskip
b17eff695c7f added new stuff
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 177
diff changeset
   637
%takes advantage of the full generality---have a look
b17eff695c7f added new stuff
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 177
diff changeset
   638
%what it produces if we call it with the string \texttt{abc}
b17eff695c7f added new stuff
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 177
diff changeset
   639
%
b17eff695c7f added new stuff
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 177
diff changeset
   640
%\begin{center}
b17eff695c7f added new stuff
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 177
diff changeset
   641
%\begin{tabular}{rcl}
b17eff695c7f added new stuff
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 177
diff changeset
   642
%input string & & output\medskip\\
b17eff695c7f added new stuff
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 177
diff changeset
   643
%\texttt{\Grid{abc}} & $\rightarrow$ & $\left\{((\texttt{\Grid{a}}, \texttt{\Grid{b}}), \texttt{\Grid{c}})\right\}$\\
b17eff695c7f added new stuff
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 177
diff changeset
   644
%\texttt{\Grid{bbc}} & $\rightarrow$ & $\left\{((\texttt{\Grid{b}}, \texttt{\Grid{b}}), \texttt{\Grid{c}})\right\}$\\
b17eff695c7f added new stuff
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 177
diff changeset
   645
%\texttt{\Grid{aac}} & $\rightarrow$ & $\varnothing$
b17eff695c7f added new stuff
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 177
diff changeset
   646
%\end{tabular}
b17eff695c7f added new stuff
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 177
diff changeset
   647
%\end{center}
b17eff695c7f added new stuff
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 177
diff changeset
   648
b17eff695c7f added new stuff
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents: 177
diff changeset
   649
173
7cfb7a6f7c99 added slides
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   650
7cfb7a6f7c99 added slides
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   651
\end{document}
7cfb7a6f7c99 added slides
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   652
7cfb7a6f7c99 added slides
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   653
%%% Local Variables: 
7cfb7a6f7c99 added slides
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   654
%%% mode: latex  
7cfb7a6f7c99 added slides
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   655
%%% TeX-master: t
7cfb7a6f7c99 added slides
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
   656
%%% End: