diff -r e0d76f7f0688 -r 715b46eee102 progs/comb2.scala --- 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;")