123 case class Or(b1: BExp, b2: BExp) extends BExp  | 
   123 case class Or(b1: BExp, b2: BExp) extends BExp  | 
   124   | 
   124   | 
   125   | 
   125   | 
   126 // arithmetic expressions  | 
   126 // arithmetic expressions  | 
   127 lazy val AExp: Parser[String, AExp] =   | 
   127 lazy val AExp: Parser[String, AExp] =   | 
   128   (Te ~ p"+" ~ AExp).mapp[AExp]{ case x ~ _ ~ z => Aop("+", x, z) } || | 
   128   (Te ~ p"+" ~ AExp).map[AExp]{ case x ~ _ ~ z => Aop("+", x, z) } || | 
   129   (Te ~ p"-" ~ AExp).mapp[AExp]{ case x ~ _ ~ z => Aop("-", x, z) } || Te | 
   129   (Te ~ p"-" ~ AExp).map[AExp]{ case x ~ _ ~ z => Aop("-", x, z) } || Te | 
   130 lazy val Te: Parser[String, AExp] =   | 
   130 lazy val Te: Parser[String, AExp] =   | 
   131   (Fa ~ p"*" ~ Te).mapp[AExp]{ case x ~ _ ~ z => Aop("*", x, z) } ||  | 
   131   (Fa ~ p"*" ~ Te).map[AExp]{ case x ~ _ ~ z => Aop("*", x, z) } ||  | 
   132   (Fa ~ p"/" ~ Te).mapp[AExp]{ case x ~ _ ~ z => Aop("/", x, z) } || Fa   | 
   132   (Fa ~ p"/" ~ Te).map[AExp]{ case x ~ _ ~ z => Aop("/", x, z) } || Fa   | 
   133 lazy val Fa: Parser[String, AExp] =   | 
   133 lazy val Fa: Parser[String, AExp] =   | 
   134    (p"(" ~ AExp ~ p")").mapp{ case _ ~ y ~ _ => y } ||  | 
   134    (p"(" ~ AExp ~ p")").map{ case _ ~ y ~ _ => y } ||  | 
   135    IdParser.mapp(Var) ||   | 
   135    IdParser.map(Var) ||   | 
   136    NumParser.mapp(Num)  | 
   136    NumParser.map(Num)  | 
   137   | 
   137   | 
   138 // boolean expressions with some simple nesting  | 
   138 // boolean expressions with some simple nesting  | 
   139 lazy val BExp: Parser[String, BExp] =   | 
   139 lazy val BExp: Parser[String, BExp] =   | 
   140    (AExp ~ p"==" ~ AExp).mapp[BExp]{ case x ~ _ ~ z => Bop("==", x, z) } ||  | 
   140    (AExp ~ p"==" ~ AExp).map[BExp]{ case x ~ _ ~ z => Bop("==", x, z) } ||  | 
   141    (AExp ~ p"!=" ~ AExp).mapp[BExp]{ case x ~ _ ~ z => Bop("!=", x, z) } ||  | 
   141    (AExp ~ p"!=" ~ AExp).map[BExp]{ case x ~ _ ~ z => Bop("!=", x, z) } ||  | 
   142    (AExp ~ p"<" ~ AExp).mapp[BExp]{ case x ~ _ ~ z => Bop("<", x, z) } ||  | 
   142    (AExp ~ p"<" ~ AExp).map[BExp]{ case x ~ _ ~ z => Bop("<", x, z) } ||  | 
   143    (AExp ~ p">" ~ AExp).mapp[BExp]{ case x ~ _ ~ z => Bop(">", x, z) } || | 
   143    (AExp ~ p">" ~ AExp).map[BExp]{ case x ~ _ ~ z => Bop(">", x, z) } || | 
   144    (p"(" ~ BExp ~ p")" ~ p"&&" ~ BExp).mapp[BExp]{ case _ ~ y ~ _ ~ _ ~ v => And(y, v) } || | 
   144    (p"(" ~ BExp ~ p")" ~ p"&&" ~ BExp).map[BExp]{ case _ ~ y ~ _ ~ _ ~ v => And(y, v) } || | 
   145    (p"(" ~ BExp ~ p")" ~ p"||" ~ BExp).mapp[BExp]{ case _ ~ y ~ _ ~ _ ~ v => Or(y, v) } || | 
   145    (p"(" ~ BExp ~ p")" ~ p"||" ~ BExp).map[BExp]{ case _ ~ y ~ _ ~ _ ~ v => Or(y, v) } || | 
   146    (p"true".mapp[BExp]{ _ => True }) ||  | 
   146    (p"true".map[BExp]{ _ => True }) ||  | 
   147    (p"false".mapp[BExp]{ _ => False }) || | 
   147    (p"false".map[BExp]{ _ => False }) || | 
   148    (p"(" ~ BExp ~ p")").mapp[BExp]{ case _ ~ x ~ _ => x } | 
   148    (p"(" ~ BExp ~ p")").map[BExp]{ case _ ~ x ~ _ => x } | 
   149   | 
   149   | 
   150 // a single statement   | 
   150 // a single statement   | 
   151 lazy val Stmt: Parser[String, Stmt] =  | 
   151 lazy val Stmt: Parser[String, Stmt] =  | 
   152   ((p"skip".mapp[Stmt]{_ => Skip }) || | 
   152   ((p"skip".map[Stmt]{_ => Skip }) || | 
   153    (IdParser ~ p":=" ~ AExp).mapp[Stmt]{ case x ~ _ ~ z => Assign(x, z) } || | 
   153    (IdParser ~ p":=" ~ AExp).map[Stmt]{ case x ~ _ ~ z => Assign(x, z) } || | 
   154    (p"write(" ~ IdParser ~ p")").mapp[Stmt]{ case _ ~ y ~ _ => Write(y) } || | 
   154    (p"write(" ~ IdParser ~ p")").map[Stmt]{ case _ ~ y ~ _ => Write(y) } || | 
   155    (p"if" ~ BExp ~ p"then" ~ Block ~ p"else" ~ Block)  | 
   155    (p"if" ~ BExp ~ p"then" ~ Block ~ p"else" ~ Block)  | 
   156      .mapp[Stmt]{ case _ ~ y ~ _ ~ u ~ _ ~ w => If(y, u, w) } || | 
   156      .map[Stmt]{ case _ ~ y ~ _ ~ u ~ _ ~ w => If(y, u, w) } || | 
   157    (p"while" ~ BExp ~ p"do" ~ Block).mapp[Stmt]{ case _ ~ y ~ _ ~ w => While(y, w) })    | 
   157    (p"while" ~ BExp ~ p"do" ~ Block).map[Stmt]{ case _ ~ y ~ _ ~ w => While(y, w) })    | 
   158    | 
   158    | 
   159    | 
   159    | 
   160 // statements  | 
   160 // statements  | 
   161 lazy val Stmts: Parser[String, Block] =  | 
   161 lazy val Stmts: Parser[String, Block] =  | 
   162   (Stmt ~ p";" ~ Stmts).mapp[Block]{ case x ~ _ ~ z => x :: z } || | 
   162   (Stmt ~ p";" ~ Stmts).map[Block]{ case x ~ _ ~ z => x :: z } || | 
   163   (Stmt.mapp[Block]{ s => List(s) }) | 
   163   (Stmt.map[Block]{ s => List(s) }) | 
   164   | 
   164   | 
   165 // blocks (enclosed in curly braces)  | 
   165 // blocks (enclosed in curly braces)  | 
   166 lazy val Block: Parser[String, Block] =  | 
   166 lazy val Block: Parser[String, Block] =  | 
   167   ((p"{" ~ Stmts ~ p"}").mapp{ case _ ~ y ~ _ => y } ||  | 
   167   ((p"{" ~ Stmts ~ p"}").map{ case _ ~ y ~ _ => y } ||  | 
   168    (Stmt.mapp(s => List(s))))  | 
   168    (Stmt.map(s => List(s))))  | 
   169   | 
   169   | 
   170   | 
   170   | 
   171 // Examples  | 
   171 // Examples  | 
   172 Stmt.parse_all("x2:=5+3") | 
   172 Stmt.parse_all("x2:=5+3") | 
   173 Block.parse_all("{x:=5;y:=8}") | 
   173 Block.parse_all("{x:=5;y:=8}") |