--- a/progs/comb1.scala Sat Oct 22 18:29:54 2016 +0100
+++ b/progs/comb1.scala Mon Oct 24 14:37:46 2016 +0100
@@ -5,44 +5,36 @@
* I <% Seq[_] , which means that the input type I can be
* treated, or seen, as a sequence. */
-trait Input {
- def isEmpty: Boolean
-}
-
+abstract class Parser[I <% Seq[_], T] {
+ def parse(ts: I): Set[(T, I)]
-abstract class Parser[T] {
-
- def parse(ts: Input): Set[(T, Input)]
-
- def parse_all(ts: Input) : Set[T] =
+ def parse_all(ts: I) : Set[T] =
for ((head, tail) <- parse(ts);
if (tail.isEmpty)) yield head
}
-class SeqParser[T, S](p: => Parser[T],
- q: => Parser[S]) extends Parser[(T, S)] {
- def parse(sb: Input) =
+class SeqParser[I <% Seq[_], T, S](p: => Parser[I, T],
+ q: => Parser[I, S]) extends Parser[I, (T, S)] {
+ def parse(sb: I) =
for ((head1, tail1) <- p.parse(sb);
(head2, tail2) <- q.parse(tail1)) yield ((head1, head2), tail2)
}
-class AltParser[T](p: => Parser[T],
- q: => Parser[T]) extends Parser[T] {
- def parse(sb: Input) = p.parse(sb) ++ q.parse(sb)
+class AltParser[I <% Seq[_], T](p: => Parser[I, T],
+ q: => Parser[I, T]) extends Parser[I, T] {
+ def parse(sb: I) = p.parse(sb) ++ q.parse(sb)
}
-class FunParser[T, S](p: => Parser[T],
- f: T => S) extends Parser[S] {
- def parse(sb: Input) =
+class FunParser[I <% Seq[_], T, S](p: => Parser[I, T],
+ f: T => S) extends Parser[I, S] {
+ def parse(sb: I) =
for ((head, tail) <- p.parse(sb)) yield (f(head), tail)
}
// atomic parsers
-case class CharParser(c: Char) extends Parser[Char] {
- type Input = String
-
+case class CharParser(c: Char) extends Parser[String, Char] {
def parse(sb: String) =
- if (sb.head == c) Set((c, sb.tail)) else Set()
+ if (sb != "" && sb.head == c) Set((c, sb.tail)) else Set()
}
case class StringParser(s: String) extends Parser[String, String] {
@@ -63,7 +55,8 @@
}
// convenience
-implicit def string2parser(s : String) = StringParser(s)
+implicit def string2parser(s: String) = StringParser(s)
+implicit def char2parser(c: Char) = CharParser(c)
implicit def ParserOps[I<% Seq[_], T](p: Parser[I, T]) = new {
def || (q : => Parser[I, T]) = new AltParser[I, T](p, q)
@@ -86,7 +79,7 @@
(("a" ~ Pal ~ "a") ==> { case ((x, y), z) => x + y + z } ||
("b" ~ Pal ~ "b") ==> { case ((x, y), z) => x + y + z } || "")
-println("Palindrom: " + Pal.parse_all("ababbaba"))
+println("Palindrome: " + Pal.parse_all("ababbaba"))
// well-nested parenthesis parser
lazy val P : Parser[String, String] =
@@ -112,6 +105,20 @@
println(E.parse_all("1+2+3")) // this is not parsed, because of
// how the grammar is set up
+// a repetition parser
+
+def RepParser[I <% Seq[_], T](p: => Parser[I, T]): Parser[I, List[T]] = {
+ p ==> { case x => x :: Nil } ||
+ p ~ RepParser(p) ==> { case (x, y) => x :: y }
+}
+
+
+// a repetition parser
+lazy val R : Parser[String, List[Char]] = RepParser('a')
+println(R.parse_all("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"))
+
+
+
// non-ambiguous vs ambiguous grammars
lazy val S : Parser[String, String] =
("1" ~ S ~ S) ==> { case ((x, y), z) => x + y + z } || ""