diff -r 890188804fb4 -r fb5e1ef58049 progs/comb1.scala --- a/progs/comb1.scala Mon Oct 24 11:58:47 2016 +0100 +++ b/progs/comb1.scala Mon Oct 24 14:36:57 2016 +0100 @@ -34,7 +34,7 @@ // atomic parsers 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] { @@ -55,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) @@ -78,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] = @@ -104,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 } || ""