--- a/progs/parser-combinators/comb1.sc Fri Oct 30 01:45:03 2020 +0000
+++ b/progs/parser-combinators/comb1.sc Wed Nov 04 17:34:52 2020 +0000
@@ -22,6 +22,12 @@
// parser combinators
+// alternative parser
+class AltParser[I : IsSeq, T](p: => Parser[I, T],
+ q: => Parser[I, T]) extends Parser[I, T] {
+ def parse(in: I) = p.parse(in) ++ q.parse(in)
+}
+
// sequence parser
class SeqParser[I : IsSeq, T, S](p: => Parser[I, T],
q: => Parser[I, S]) extends Parser[I, (T, S)] {
@@ -30,12 +36,6 @@
(hd2, tl2) <- q.parse(tl1)) yield ((hd1, hd2), tl2)
}
-// alternative parser
-class AltParser[I : IsSeq, T](p: => Parser[I, T],
- q: => Parser[I, T]) extends Parser[I, T] {
- def parse(in: I) = p.parse(in) ++ q.parse(in)
-}
-
// map parser
class MapParser[I : IsSeq, T, S](p: => Parser[I, T],
f: T => S) extends Parser[I, S] {
@@ -50,6 +50,7 @@
if (in != "" && in.head == c) Set((c, in.tail)) else Set()
}
+
// an atomic parser for parsing strings according to a regex
import scala.util.matching.Regex
@@ -65,6 +66,7 @@
def StrParser(s: String) = RegexParser(Regex.quote(s).r)
+
// NumParserInt transforms a "string integer" into a propper Int
// (needs "new" because MapParser is not a case class)
@@ -80,6 +82,7 @@
def p(args: Any*) = StrParser(sc.s(args:_*))
}
+
// more convenient syntax for parser combinators
implicit def ParserOps[I : IsSeq, T](p: Parser[I, T]) = new {
def ||(q : => Parser[I, T]) = new AltParser[I, T](p, q)
@@ -95,7 +98,7 @@
// with this NumParserInt can now be written more conveniently
// as:
-val NumParserInt2 = NumParser.map(s => s.toInt)
+val NumParserInt2 = NumParser.map(_.toInt)
// A parser for palindromes (just returns them as string)
@@ -111,9 +114,15 @@
println("Palindrome: " + Pal.parse_all("abaaaba"))
-// A parser for wellnested parentheses (transforms '(' -> '{' , ')' -> '}' )
-lazy val P : Parser[String, String] =
- (p"(" ~ P ~ p")" ~ P).map{ case (((_, x), _), y) => "{" + x + "}" + y } || p""
+// A parser for wellnested parentheses
+//
+// P ::= ( P ) P | epsilon
+//
+// (transforms '(' -> '{' , ')' -> '}' )
+lazy val P : Parser[String, String] = {
+ (p"(" ~ P ~ p")" ~ P).map{ case (((_, x), _), y) => "{" + x + "}" + y } ||
+ p""
+}
println(P.parse_all("(((()()))())"))
println(P.parse_all("(((()()))()))"))
@@ -122,22 +131,13 @@
// A parser for arithmetic expressions (Terms and Factors)
-lazy val E: Parser[String, Int] =
+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
-lazy val T: Parser[String, Int] =
- (F ~ p"*" ~ T).map{ case ((x, _), z) => x * z } || F
-lazy val F: Parser[String, Int] =
- (p"(" ~ E ~ p")").map{ case ((_, y), _) => y } || NumParserInt
-
-/* same parser but producing a string
-lazy val E: Parser[String, String] =
- (T ~ "+" ~ E).map{ case x ~ y ~ z => "(" + x + ")+(" + z + ")"} || T
-lazy val T: Parser[String, String] =
- (F ~ "*" ~ T).map{ case x ~ y ~ z => "(" + x + ")*("+ z + ")"} || F
-lazy val F: Parser[String, String] =
- ("(" ~ E ~ ")").map{ case x ~ y ~ z => y } || NumParser
-*/
+ (T ~ p"-" ~ E).map{ case ((x, _), z) => x - z } || T }
+lazy val T: Parser[String, Int] = {
+ (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"))
@@ -147,7 +147,7 @@
println(E.parse_all("4/2+3"))
println(E.parse("1 + 2 * 3"))
println(E.parse_all("(1+2)+3"))
-println(E.parse_all("1+2+3"))
+println(E.parse_all("1+2+3"))
// with parser combinators (and other parsing algorithms)
@@ -194,7 +194,7 @@
// A variant which counts how many 1s are parsed
lazy val UCount : Parser[String, Int] =
- (p"1" ~ UCount).map[Int]{ case (_, y) => y + 1 } || p"".map[Int]{ _ => 0 }
+ (p"1" ~ UCount).map{ case (_, y) => y + 1 } || p"".map{ _ => 0 }
println(UCount.parse("11111"))
println(UCount.parse_all("11111"))