diff -r b7a6436c7758 -r 904de68a27a4 progs/parser-combinators/comb1.sc --- a/progs/parser-combinators/comb1.sc Thu Nov 10 23:49:29 2022 +0000 +++ b/progs/parser-combinators/comb1.sc Tue Nov 15 11:34:33 2022 +0000 @@ -50,6 +50,7 @@ if (in != "" && in.head == c) Set((c, in.tail)) else Set() } +CharParser('c').parse("abc") // an atomic parser for parsing strings according to a regex import scala.util.matching.Regex @@ -65,23 +66,27 @@ val NumParser = RegexParser("[0-9]+".r) def StrParser(s: String) = RegexParser(Regex.quote(s).r) +NumParser.parse("a123a123bc") +StrParser("else").parse("eelsethen") // NumParserInt transforms a "string integer" into a propper Int // (needs "new" because MapParser is not a case class) val NumParserInt = new MapParser(NumParser, (s: String) => s.toInt) - +NumParserInt.parse("123abc") // the following string interpolation allows us to write // StrParser(_some_string_) more conveniently as // // p"<_some_string_>" + implicit def parser_interpolation(sc: StringContext) = new { def p(args: Any*) = StrParser(sc.s(args:_*)) } - + +(p"else").parse("elsethen") // more convenient syntax for parser combinators implicit def ParserOps[I : IsSeq, T](p: Parser[I, T]) = new { @@ -90,6 +95,10 @@ def map[S](f: => T => S) = new MapParser[I, T, S](p, f) } +def toU(s: String) = s.map(_.toUpper) + +(p"ELSE").map(toU(_)).parse("ELSEifthen") + // these implicits allow us to use an infix notation for // sequences and alternatives; we also can write the usual // map for a MapParser @@ -101,9 +110,11 @@ val NumParserInt2 = NumParser.map(_.toInt) + + // A parser for palindromes (just returns them as string) lazy val Pal : Parser[String, String] = { - ((p"a" ~ Pal) ~ p"a").map{ case ((x, y), z) => s"$x$y$z" } || + (p"a" ~ Pal ~ p"a").map{ case ((x, y), z) => s"$x$y$z" } || (p"b" ~ Pal ~ p"b").map{ case ((x, y), z) => s"$x$y$z" } || p"a" || p"b" || p"" } @@ -130,7 +141,7 @@ println(P.parse_all("()")) // A parser for arithmetic expressions (Terms and Factors) - +{ lazy val E: Parser[String, Int] = { (T ~ p"+" ~ E).map{ case ((x, _), z) => x + z } || (T ~ p"-" ~ E).map{ case ((x, _), z) => x - z } || T } @@ -138,7 +149,7 @@ (F ~ p"*" ~ T).map{ case ((x, _), z) => x * z } || F } lazy val F: Parser[String, Int] = { (p"(" ~ E ~ p")").map{ case ((_, y), _) => y } || NumParserInt } - +} println(E.parse_all("1+3+4")) println(E.parse("1+3+4")) println(E.parse_all("4*2+3"))