progs/parser-combinators/comb1.sc
changeset 799 85267be9a5ed
parent 742 b5b5583a3a08
child 801 7aab258bf72a
--- 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"))