updated
authorChristian Urban <urbanc@in.tum.de>
Sun, 27 Oct 2019 13:03:58 +0000
changeset 673 715b46eee102
parent 672 e0d76f7f0688
child 674 e0a41a1f24cf
updated
progs/comb1.scala
progs/comb1a.scala
progs/comb2.scala
--- a/progs/comb1.scala	Sun Oct 27 11:57:57 2019 +0000
+++ b/progs/comb1.scala	Sun Oct 27 13:03:58 2019 +0000
@@ -102,12 +102,22 @@
 P.parse_all("()")
 
 // just counts parentheses
-lazy val PC : Parser[String, Int] = 
-  ("(" ~ PC ~ ")" ~ PC ==> { case (((_, x), _), y) => x + y + 2 } || 
-   "" ==> { (s) => 0 })
+lazy val P2 : Parser[String, Int] = 
+  ("(" ~ P2 ~ ")" ~ P2 ==> { case (((_, x), _), y) => x + y + 2 } || 
+   "" ==> { _ => 0 })
+
+P2.parse_all("(((()()))())")
+P2.parse_all("(((()()))()))")
 
-PC.parse_all("(((()()))())")
-P.parse_all("(((()()))()))")
+// counts opening and closing parentheses
+lazy val P3 : Parser[String, Int] = 
+  ("(" ~ P3 ==> { case (_, x) => x + 1 } ||
+   ")" ~ P3 ==> { case (_, x) => x - 1 } || 
+   "" ==> { _ => 0 })
+
+P3.parse_all("(((()()))())")
+P3.parse_all("(((()()))()))")
+P3.parse_all(")(")
 
 // Arithmetic Expressions (Terms and Factors)
 // (because it is mutually recursive, you need :paste 
--- a/progs/comb1a.scala	Sun Oct 27 11:57:57 2019 +0000
+++ b/progs/comb1a.scala	Sun Oct 27 13:03:58 2019 +0000
@@ -65,7 +65,7 @@
 implicit def string2parser(s: String) = StringParser(s)
 implicit def char2parser(c: Char) = CharParser(c)
 
-implicit def ParserOps[I, T](p: Parser[I, T])(implicit ev: I => Seq[_]) = new {
+implicit def ParserOps[I : IsSeq, T](p: Parser[I, T]) = new {
   def || (q : => Parser[I, T]) = new AltParser[I, T](p, q)
   def ==>[S] (f: => T => S) = new FunParser[I, T, S](p, f)
   def ~[S] (q : => Parser[I, S]) = new SeqParser[I, T, S](p, q)
--- a/progs/comb2.scala	Sun Oct 27 11:57:57 2019 +0000
+++ b/progs/comb2.scala	Sun Oct 27 13:03:58 2019 +0000
@@ -4,25 +4,30 @@
 import scala.language.implicitConversions
 import scala.language.reflectiveCalls
 
+// more convenience for the semantic actions later on
+case class ~[+A, +B](_1: A, _2: B)
 
-abstract class Parser[I, T](implicit ev: I => Seq[_]) {
+
+type IsSeq[A] = A => Seq[_]
+
+abstract class Parser[I : IsSeq, T] {
   def parse(ts: I): Set[(T, I)]
 
   def parse_all(ts: I) : Set[T] =
     for ((head, tail) <- parse(ts); if (tail.isEmpty)) yield head
 }
 
-class SeqParser[I, T, S](p: => Parser[I, T], q: => Parser[I, S])(implicit ev: I => Seq[_]) extends Parser[I, (T, S)] {
+class SeqParser[I : IsSeq, T, S](p: => Parser[I, T], q: => Parser[I, S]) extends Parser[I, ~[T, S]] {
   def parse(sb: I) = 
     for ((head1, tail1) <- p.parse(sb); 
-         (head2, tail2) <- q.parse(tail1)) yield ((head1, head2), tail2)
+         (head2, tail2) <- q.parse(tail1)) yield (new ~(head1, head2), tail2)
 }
 
-class AltParser[I, T](p: => Parser[I, T], q: => Parser[I, T])(implicit ev: I => Seq[_]) extends Parser[I, T] {
+class AltParser[I : IsSeq, T](p: => Parser[I, T], q: => Parser[I, T]) extends Parser[I, T] {
   def parse(sb: I) = p.parse(sb) ++ q.parse(sb)   
 }
 
-class FunParser[I, T, S](p: => Parser[I, T], f: T => S)(implicit ev: I => Seq[_]) extends Parser[I, S] {
+class FunParser[I : IsSeq, T, S](p: => Parser[I, T], f: T => S) extends Parser[I, S] {
   def parse(sb: I) = 
     for ((head, tail) <- p.parse(sb)) yield (f(head), tail)
 }
@@ -48,7 +53,7 @@
 
 implicit def string2parser(s : String) = StringParser(s)
 
-implicit def ParserOps[I, T](p: Parser[I, T])(implicit ev: I => Seq[_]) = new {
+implicit def ParserOps[I : IsSeq, T](p: Parser[I, T]) = new {
   def || (q : => Parser[I, T]) = new AltParser[I, T](p, q)
   def ==>[S] (f: => T => S) = new FunParser[I, T, S](p, f)
   def ~[S] (q : => Parser[I, S]) = new SeqParser[I, T, S](p, q)
@@ -98,45 +103,45 @@
 }
 
 lazy val AExp: Parser[String, AExp] = 
-  (Te ~ "+" ~ AExp) ==> { case ((x, y), z) => Aop("+", x, z): AExp } ||
-  (Te ~ "-" ~ AExp) ==> { case ((x, y), z) => Aop("-", x, z): AExp } || Te 
+  (Te ~ "+" ~ AExp) ==> { case x ~ y ~ z => Aop("+", x, z): AExp } ||
+  (Te ~ "-" ~ AExp) ==> { case x ~ y ~ z => Aop("-", x, z): AExp } || Te 
 lazy val Te: Parser[String, AExp] = 
-  (Fa ~ "*" ~ Te) ==> { case ((x, y), z) => Aop("*", x, z): AExp } || 
-  (Fa ~ "/" ~ Te) ==> { case ((x, y), z) => Aop("/", x, z): AExp } || Fa  
+  (Fa ~ "*" ~ Te) ==> { case x ~ y ~ z => Aop("*", x, z): AExp } || 
+  (Fa ~ "/" ~ Te) ==> { case x ~ y ~ z => Aop("/", x, z): AExp } || Fa  
 lazy val Fa: Parser[String, AExp] = 
-   ("(" ~ AExp ~ ")") ==> { case ((x, y), z) => y } || 
+   ("(" ~ AExp ~ ")") ==> { case x ~ y ~ z => y } || 
    IdParser ==> Var || 
    NumParser ==> Num
 
 // boolean expressions with some simple nesting
 lazy val BExp: Parser[String, BExp] = 
-   (AExp ~ "==" ~ AExp) ==> { case ((x, y), z) => Bop("==", x, z): BExp } || 
-   (AExp ~ "!=" ~ AExp) ==> { case ((x, y), z) => Bop("!=", x, z): BExp } || 
-   (AExp ~ "<" ~ AExp) ==> { case ((x, y), z) => Bop("<", x, z): BExp } || 
-   (AExp ~ ">" ~ AExp) ==> { case ((x, y), z) => Bop(">", x, z): BExp } ||
-   ("(" ~ BExp ~ ")" ~ "&&" ~ BExp) ==> { case ((((x, y), z), u), v) => And(y, v): BExp } ||
-   ("(" ~ BExp ~ ")" ~ "||" ~ BExp) ==> { case ((((x, y), z), u), v) => Or(y, v): BExp } ||
-   ("true" ==> ((_) => True: BExp )) || 
-   ("false" ==> ((_) => False: BExp )) ||
-   ("(" ~ BExp ~ ")") ==> { case ((x, y), z) => y}
+   (AExp ~ "==" ~ AExp) ==> { case x ~ y ~ z => Bop("==", x, z): BExp } || 
+   (AExp ~ "!=" ~ AExp) ==> { case x ~ y ~ z => Bop("!=", x, z): BExp } || 
+   (AExp ~ "<" ~ AExp) ==> { case x ~ y ~ z => Bop("<", x, z): BExp } || 
+   (AExp ~ ">" ~ AExp) ==> { case x ~ y ~ z => Bop(">", x, z): BExp } ||
+   ("(" ~ BExp ~ ")" ~ "&&" ~ BExp) ==> { case x ~ y ~ z ~ u ~ v => And(y, v): BExp } ||
+   ("(" ~ BExp ~ ")" ~ "||" ~ BExp) ==> { case x ~ y ~ z ~ u ~ v => Or(y, v): BExp } ||
+   ("true" ==> (_ => True: BExp )) || 
+   ("false" ==> (_ => False: BExp )) ||
+   ("(" ~ BExp ~ ")") ==> { case x ~ y ~ z => y}
 
 // statement / statements
 lazy val Stmt: Parser[String, Stmt] =
-  (("skip" ==> ((_) => Skip: Stmt)) ||
-   (IdParser ~ ":=" ~ AExp) ==> { case ((x, y), z) => Assign(x, z): Stmt } ||
-   ("write(" ~ IdParser ~ ")") ==> { case ((x, y), z) => Write(y): Stmt } ||
+  (("skip" ==> (_ => Skip: Stmt)) ||
+   (IdParser ~ ":=" ~ AExp) ==> { case x ~ y ~ z => Assign(x, z): Stmt } ||
+   ("write(" ~ IdParser ~ ")") ==> { case x ~y ~ z => Write(y): Stmt } ||
    ("if" ~ BExp ~ "then" ~ Block ~ "else" ~ Block) ==>
-    { case (((((x,y),z),u),v),w) => If(y, u, w): Stmt } ||
-   ("while" ~ BExp ~ "do" ~ Block) ==> { case (((x, y), z), w) => While(y, w) }) 
+    { case x ~ y ~ z ~ u ~ v ~ w => If(y, u, w): Stmt } ||
+   ("while" ~ BExp ~ "do" ~ Block) ==> { case x ~ y ~ z ~ w => While(y, w) }) 
  
 lazy val Stmts: Parser[String, Block] =
-  (Stmt ~ ";" ~ Stmts) ==> { case ((x, y), z) => x :: z : Block } ||
-  (Stmt ==> ((s) => List(s) : Block))
+  (Stmt ~ ";" ~ Stmts) ==> { case x ~ y ~ z => x :: z : Block } ||
+  (Stmt ==> ( s => List(s) : Block))
 
 // blocks (enclosed in curly braces)
 lazy val Block: Parser[String, Block] =
-  (("{" ~ Stmts ~ "}") ==> { case ((x, y), z) => y} || 
-   (Stmt ==> ((s) => List(s))))
+  (("{" ~ Stmts ~ "}") ==> { case x ~ y ~ z => y} || 
+   (Stmt ==> (s => List(s))))
 
 
 Stmts.parse_all("x2:=5+3;")