diff -r 5e070fb0332a -r eda0ccf56c72 progs/parser-combinators/comb1.sc --- a/progs/parser-combinators/comb1.sc Sat Nov 04 18:28:09 2023 +0000 +++ b/progs/parser-combinators/comb1.sc Sat Nov 11 10:08:33 2023 +0000 @@ -20,6 +20,7 @@ if is(tl).isEmpty) yield hd } + // parser combinators @@ -39,7 +40,7 @@ // map parser class MapParser[I : IsSeq, T, S](p: => Parser[I, T], - f: T => S) extends Parser[I, S] { + f: T => S) extends Parser[I, S] { def parse(in: I) = for ((hd, tl) <- p.parse(in)) yield (f(hd), tl) } @@ -51,7 +52,11 @@ if (in != "" && in.head == c) Set((c, in.tail)) else Set() } -CharParser('a').parse("abc") +val ap = CharParser('a') +val bp = CharParser('b') + +val abp = SeqParser(ap, bp) +MapParser(abp, ab => s"$ab").parse("abc") // an atomic parser for parsing strings according to a regex import scala.util.matching.Regex @@ -67,14 +72,14 @@ val NumParser = RegexParser("[0-9]+".r) def StrParser(s: String) = RegexParser(Regex.quote(s).r) -NumParser.parse("a123a123bc") +NumParser.parse("123a123bc") StrParser("else").parse("elsethen") // 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) +val NumParserInt = MapParser(NumParser, (s: String) => s.toInt) NumParserInt.parse("123abc") // the following string interpolation allows us to write @@ -111,6 +116,7 @@ val NumParserInt2 = NumParser.map(_.toInt) +val x = 1 + 3 // A parser for palindromes (just returns them as string) // since the parser is recursive it needs to be lazy @@ -121,8 +127,8 @@ } // examples -Pal.parse_all("abaaaba") -Pal.parse("abaaaba") +Pal.parse_all("abacaba") +Pal.parse("abacaaba") println("Palindrome: " + Pal.parse_all("abaaaba")) @@ -143,6 +149,9 @@ // A parser for arithmetic expressions (Terms and Factors) +"1 + 2 * 3" +"(1 + 2) * 3" +{ 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 } @@ -150,12 +159,12 @@ (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")) println(E.parse_all("4*(2+3)")) -println(E.parse_all("(4)*((2+3))")) +println(E.parse_all("(4)*(((2+3)))")) println(E.parse_all("4/2+3")) println(E.parse("1 + 2 * 3")) println(E.parse_all("(1+2)+3"))