--- 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;")