progs/comb2.scala
changeset 627 f5214da1976e
parent 624 8d0af38389bc
child 628 8067d0a8ba04
--- 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)