progs/comb1.scala
changeset 458 896a5f91838d
parent 367 04127a5aad23
child 461 890188804fb4
--- a/progs/comb1.scala	Wed Oct 19 08:46:50 2016 +0100
+++ b/progs/comb1.scala	Sat Oct 22 13:11:33 2016 +0100
@@ -5,34 +5,42 @@
  * I <% Seq[_] , which means that the input type I can be
  * treated, or seen, as a sequence. */
 
-abstract class Parser[I <% Seq[_], T] {
-  def parse(ts: I): Set[(T, I)]
+trait Input { 
+  def isEmpty: Boolean
+}
+
 
-  def parse_all(ts: I) : Set[T] =
+abstract class Parser[T] {
+
+  def parse(ts: Input): Set[(T, Input)]
+
+  def parse_all(ts: Input) : Set[T] =
     for ((head, tail) <- parse(ts); 
         if (tail.isEmpty)) yield head
 }
 
-class SeqParser[I <% Seq[_], T, S](p: => Parser[I, T], 
-                                   q: => Parser[I, S]) extends Parser[I, (T, S)] {
-  def parse(sb: I) = 
+class SeqParser[T, S](p: => Parser[T], 
+                      q: => Parser[S]) extends Parser[(T, S)] {
+  def parse(sb: Input) = 
     for ((head1, tail1) <- p.parse(sb); 
          (head2, tail2) <- q.parse(tail1)) yield ((head1, head2), tail2)
 }
 
-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 AltParser[T](p: => Parser[T], 
+                   q: => Parser[T]) extends Parser[T] {
+  def parse(sb: Input) = p.parse(sb) ++ q.parse(sb)   
 }
 
-class FunParser[I <% Seq[_], T, S](p: => Parser[I, T], 
-                                   f: T => S) extends Parser[I, S] {
-  def parse(sb: I) = 
+class FunParser[T, S](p: => Parser[T], 
+                      f: T => S) extends Parser[S] {
+  def parse(sb: Input) = 
     for ((head, tail) <- p.parse(sb)) yield (f(head), tail)
 }
 
 // atomic parsers  
-case class CharParser(c: Char) extends Parser[String, Char] {
+case class CharParser(c: Char) extends Parser[Char] {
+  type Input = String
+
   def parse(sb: String) = 
     if (sb.head == c) Set((c, sb.tail)) else Set()
 }