--- a/progs/comb2.scala Sun Jul 28 17:29:53 2019 +0100
+++ b/progs/comb2.scala Sun Jul 28 21:10:39 2019 +0100
@@ -76,6 +76,8 @@
case class If(a: BExp, bl1: Block, bl2: Block) extends Stmt
case class While(b: BExp, bl: Block) extends Stmt
case class Assign(s: String, a: AExp) extends Stmt
+case class Write(s: String) extends Stmt
+
case class Var(s: String) extends AExp
case class Num(i: Int) extends AExp
@@ -84,7 +86,8 @@
case object True extends BExp
case object False extends BExp
case class Bop(o: String, a1: AExp, a2: AExp) extends BExp
-
+case class And(b1: BExp, b2: BExp) extends BExp
+case class Or(b1: BExp, b2: BExp) extends BExp
case object IdParser extends Parser[String, String] {
val reg = "[a-z][a-z,0-9]*".r
@@ -95,28 +98,33 @@
}
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
+ (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)
+ NumParser ==> Num
-// boolean expressions
+// 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 } ||
- ("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}
+// 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 } ||
("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) })
@@ -134,7 +142,17 @@
Block.parse_all("{x:=5;y:=8}")
Block.parse_all("if(false)then{x:=5}else{x:=10}")
-val fib = """{n:=10;minus1:=0;minus2:=1;temp:=0;while(n>0)do{temp:=minus2;minus2:=minus1+minus2;minus1:=temp;n:=n-1};result:=minus2}"""
+val fib = """{n := 10;
+ minus1 := 0;
+ minus2 := 1;
+ temp := 0;
+ while (n > 0) do {
+ temp := minus2;
+ minus2 := minus1 + minus2;
+ minus1 := temp;
+ n := n - 1
+ };
+ result := minus2}""".replaceAll("\\s+", "")
Block.parse_all(fib)
@@ -147,15 +165,18 @@
case Aop("+", a1, a2) => eval_aexp(a1, env) + eval_aexp(a2, env)
case Aop("-", a1, a2) => eval_aexp(a1, env) - eval_aexp(a2, env)
case Aop("*", a1, a2) => eval_aexp(a1, env) * eval_aexp(a2, env)
+ case Aop("/", a1, a2) => eval_aexp(a1, env) / eval_aexp(a2, env)
}
def eval_bexp(b: BExp, env: Env) : Boolean = b match {
case True => true
case False => false
- case Bop("=", a1, a2) => eval_aexp(a1, env) == eval_aexp(a2, env)
+ case Bop("==", a1, a2) => eval_aexp(a1, env) == eval_aexp(a2, env)
case Bop("!=", a1, a2) => !(eval_aexp(a1, env) == eval_aexp(a2, env))
case Bop(">", a1, a2) => eval_aexp(a1, env) > eval_aexp(a2, env)
case Bop("<", a1, a2) => eval_aexp(a1, env) < eval_aexp(a2, env)
+ case And(b1, b2) => eval_bexp(b1, env) && eval_bexp(b2, env)
+ case Or(b1, b2) => eval_bexp(b1, env) || eval_bexp(b2, env)
}
def eval_stmt(s: Stmt, env: Env) : Env = s match {
@@ -165,6 +186,7 @@
case While(b, bl) =>
if (eval_bexp(b, env)) eval_stmt(While(b, bl), eval_bl(bl, env))
else env
+ case Write(x) => { println(env(x)) ; env }
}
def eval_bl(bl: Block, env: Env) : Env = bl match {
@@ -177,3 +199,39 @@
// parse + evaluate fib program; then lookup what is
// stored under the variable result
println(eval(Block.parse_all(fib).head)("result"))
+
+
+// more examles
+
+// calculate and print all factors bigger
+// than 1 and smaller than n
+println("Factors")
+
+val factors =
+ """{n := 12;
+ f := 2;
+ while (f < n / 2 + 1) do {
+ if ((n / f) * f == n) then { write(f) } else { skip };
+ f := f + 1
+ }}""".replaceAll("\\s+", "")
+
+eval(Block.parse_all(factors).head)
+
+// calculate all prime numbers up to a number
+println("Primes")
+
+val primes =
+ """{end := 100;
+ n := 2;
+ while (n < end) do {
+ f := 2;
+ tmp := 0;
+ while ((f < n / 2 + 1) && (tmp == 0)) do {
+ if ((n / f) * f == n) then { tmp := 1 } else { skip };
+ f := f + 1
+ };
+ if (tmp == 0) then { write(n) } else { skip };
+ n := n + 1
+ }}""".replaceAll("\\s+", "")
+
+eval(Block.parse_all(primes).head)