diff -r 8e63f9745f46 -r e50096adda15 progs/comb1.scala --- a/progs/comb1.scala Sun Jul 28 01:00:41 2019 +0100 +++ b/progs/comb1.scala Sun Jul 28 14:24:46 2019 +0100 @@ -1,11 +1,11 @@ import scala.language.implicitConversions import scala.language.reflectiveCalls -/* Note, in the lectures I did not show the type consraint - * I <% Seq[_] , which means that the input type I can be - * treated, or seen, as a sequence. */ +/* Note, in the lectures I did not show the implicit type consraint + * I => Seq[_] , which means that the input type I needs to be + * a sequence, subtype of Seq. */ -abstract class Parser[I <% Seq[_], T] { +abstract class Parser[I, T](implicit ev: I => Seq[_]) { def parse(ts: I): Set[(T, I)] def parse_all(ts: I) : Set[T] = @@ -13,20 +13,20 @@ if (tail.isEmpty)) yield head } -class SeqParser[I <% Seq[_], T, S](p: => Parser[I, T], - q: => Parser[I, S]) extends Parser[I, (T, S)] { +class SeqParser[I, T, S](p: => Parser[I, T], + q: => Parser[I, S])(implicit ev: I => Seq[_]) 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[I <% Seq[_], T](p: => Parser[I, T], - q: => Parser[I, T]) extends Parser[I, T] { +class AltParser[I, T](p: => Parser[I, T], + q: => Parser[I, T])(implicit ev: I => Seq[_]) extends Parser[I, T] { def parse(sb: I) = p.parse(sb) ++ q.parse(sb) } -class FunParser[I <% Seq[_], T, S](p: => Parser[I, T], - f: T => S) extends Parser[I, S] { +class FunParser[I, T, S](p: => Parser[I, T], + f: T => S)(implicit ev: I => Seq[_]) extends Parser[I, S] { def parse(sb: I) = for ((head, tail) <- p.parse(sb)) yield (f(head), tail) } @@ -48,13 +48,16 @@ val NumParser = RegexParser("[0-9]+".r) def StringParser(s: String) = RegexParser(Regex.quote(s).r) -val NumParserInt = NumParser ==> (s => s.toInt) +// NumParserInt transforms a "string integer" into an Int; +// needs new, because FunParser is not a case class +val NumParserInt = new FunParser(NumParser, (s: String) => s.toInt) + // convenience 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 { +implicit def ParserOps[I, T](p: Parser[I, T])(implicit ev: I => Seq[_]) = new { def | (q : => Parser[I, T]) = new AltParser[I, T](p, q) def ==>[S] (f: => T => S) = new FunParser[I, T, S](p, f) def ~[S] (q : => Parser[I, S]) = new SeqParser[I, T, S](p, q) @@ -70,6 +73,9 @@ new SeqParser[String, String, String](s, r) } +// NumParserInt can now be written as +val NumParserInt = NumParser ==> (s => s.toInt) + lazy val Pal : Parser[String, String] = (("a" ~ Pal ~ "a") ==> { case ((x, y), z) => x + y + z } | @@ -80,7 +86,7 @@ println("Palindrome: " + Pal.parse_all("abaaaba")) -// well-nested parenthesis parser +// well-nested parentheses parser (transforms '(' -> '{' , ')' -> '}' ) lazy val P : Parser[String, String] = "(" ~ P ~ ")" ~ P ==> { case (((_, x), _), y) => "{" + x + "}" + y } | "" @@ -89,7 +95,7 @@ P.parse_all(")(") P.parse_all("()") -// arithmetic expressions +// Arithmetic Expressions lazy val E: Parser[String, Int] = (T ~ "+" ~ E) ==> { case ((x, y), z) => x + z } | @@ -149,15 +155,13 @@ U.parse_all("1" * 100 + "0") lazy val UCount : Parser[String, Int] = - ("1" ~ UCount) ==> { case (x, y) => y + 1 } | - "" ==> { x => 0 } + ("1" ~ UCount) ==> { case (x, y) => y + 1 } | "" ==> { x => 0 } UCount.parse("11111") UCount.parse_all("11111") - // Single Character parser lazy val One : Parser[String, String] = "1" lazy val Two : Parser[String, String] = "2"