--- a/handouts/ho06.tex Thu Oct 05 14:36:54 2023 +0100
+++ b/handouts/ho06.tex Fri Oct 13 15:07:37 2023 +0100
@@ -107,16 +107,20 @@
class we specify that \texttt{I} is the \emph{input type} of the
parser combinator and that \texttt{T} is the \emph{output type}. This
implies that the function \texttt{parse} takes an argument of type
-\texttt{I} and returns a set of type \mbox{\texttt{Set[(T, I)]}}.
+\texttt{I} and returns a set of type \mbox{\texttt{Set[(T,
+ I)]}}.\footnote{In the actual code on KEATS there is some
+ kerfuffle about correct type-bounds and using clauses. Ignore this
+ part of the implementation for the moment---it is not needed for
+ understanding how the code works.}
\begin{center}
\begin{lstlisting}[language=Scala]
-abstract class Parser[I, T](using is: I => Seq[_]) {
+abstract class Parser[I, T] {
def parse(in: I): Set[(T, I)]
def parse_all(in: I) : Set[T] =
for ((hd, tl) <- parse(in);
- if is(tl).isEmpty) yield hd
+ if tl.isEmpty) yield hd
}
\end{lstlisting}
\end{center}
@@ -214,8 +218,7 @@
\begin{lstlisting}[language=Scala, numbers=none]
class AltParser[I, T]
(p: => Parser[I, T],
- q: => Parser[I, T])(using I => Seq[_])
- extends Parser[I, T] {
+ q: => Parser[I, T]) extends Parser[I, T] {
def parse(in: I) = p.parse(in) ++ q.parse(in)
}
\end{lstlisting}
@@ -306,8 +309,7 @@
\begin{lstlisting}[language=Scala,numbers=none]
class SeqParser[I, T, S]
(p: => Parser[I, T],
- q: => Parser[I, S])(using I => Seq[_])
- extends Parser[I, (T, S)] {
+ q: => Parser[I, S]) extends Parser[I, (T, S)] {
def parse(in: I) =
for ((output1, u1) <- p.parse(in);
(output2, u2) <- q.parse(u1))
@@ -483,7 +485,7 @@
\begin{lstlisting}[language=Scala,basicstyle=\small\ttfamily, numbers=none]
class MapParser[I, T, S]
(p: => Parser[I, T],
- f: T => S)(using I => Seq[_]) extends Parser[I, S] {
+ f: T => S) extends Parser[I, S] {
def parse(in: I) =
for ((hd, tl) <- p.parse(in)) yield (f(hd), tl)
}
@@ -593,7 +595,7 @@
\texttt{Int}. Now \texttt{parse} generates \texttt{Set((123,abc))},
but this time \texttt{123} is an \texttt{Int}. Think carefully what
the input and output type of the parser is without the semantic action
-adn what with the semantic action (the type of the function can
+and what with the semantic action (the type of the function can
already tell you). Let us come back to semantic actions when we are
going to implement actual context-free grammars.