while.scala
changeset 72 d65525aeca08
parent 71 7717f20f0504
child 73 27469183da75
--- a/while.scala	Fri Nov 23 14:08:31 2012 +0000
+++ b/while.scala	Fri Nov 23 15:17:17 2012 +0000
@@ -1,4 +1,5 @@
-
+// A parser and evaluator for teh while language
+// 
 //:load matcher.scala
 //:load parser3.scala
 
@@ -9,7 +10,7 @@
 val NUM = PLUS(DIGIT)
 val KEYWORD = ALTS("skip", "while", "do", "if", "then", "else", "true", "false") 
 val SEMI: Rexp = ";"
-val OP: Rexp = ALTS(":=", "=", "+", "-", "*")
+val OP: Rexp = ALTS(":=", "=", "+", "-", "*", "!=", "<", ">")
 val WHITESPACE = PLUS(RANGE(" \n"))
 val RPAREN: Rexp = ")"
 val LPAREN: Rexp = "("
@@ -86,6 +87,7 @@
 }
 
 
+// arithmetic expressions
 lazy val AExp: Parser[List[Token], AExp] = 
   (T ~ T_OP("+") ~ AExp) ==> { case ((x, y), z) => Aop("+", x, z): AExp } ||
   (T ~ T_OP("-") ~ AExp) ==> { case ((x, y), z) => Aop("-", x, z): AExp } || T  
@@ -96,8 +98,12 @@
   IdParser ==> Var || 
   NumParser ==> Num
 
+// boolean expressions
 lazy val BExp: Parser[List[Token], BExp] = 
   (AExp ~ T_OP("=") ~ AExp) ==> { case ((x, y), z) => Bop("=", x, z): BExp } || 
+  (AExp ~ T_OP("!=") ~ AExp) ==> { case ((x, y), z) => Bop("!=", x, z): BExp } || 
+  (AExp ~ T_OP("<") ~ AExp) ==> { case ((x, y), z) => Bop("<", x, z): BExp } || 
+  (AExp ~ T_OP(">") ~ AExp) ==> { case ((x, y), z) => Bop(">", x, z): BExp } || 
   (T_KWD("true") ==> ((_) => True)) || 
   (T_KWD("false") ==> ((_) => False: BExp))
 
@@ -154,10 +160,11 @@
 val p3b_ast = Stmt.parse_all(p3b_toks)
 println(p3b_ast)
 
+// multiplication
 val p4 = """{ x := 5;
-              y := 3;
+              y := 4;
               r := 0;
-              while y = 0 do {
+              while y > 0 do {
                  r := r + x;
                  y := y - 1
               } 
@@ -166,6 +173,23 @@
 val p4_ast = Block.parse_all(p4_toks)
 println(p4_ast)
 
+// fibonacci numbers
+val p5 = 
+"""{ n := 9;
+     minus1 := 0;
+     minus2 := 1;
+     temp := 0;
+     while n > 0 do  {
+       temp := minus2;
+       minus2 := minus1 + minus2;
+       minus1 := temp;
+       n := n - 1
+     };
+     fib_res := minus2
+  }
+"""
+val p5_toks = Tok.fromString(p5) 
+val p5_ast = Block.parse_all(p5_toks)
 
 // interpreter
 type Env = Map[String, Int]
@@ -174,6 +198,9 @@
   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)
 }
 
 def eval_aexp(a: AExp, env : Env) : Int = a match {
@@ -188,6 +215,9 @@
   case Skip => env
   case Assign(x, a) => env + (x -> eval_aexp(a, env))
   case If(b, bl1, bl2) => if (eval_bexp(b, env)) eval_bl(bl1, env) else eval_bl(bl2, env) 
+  case While(b, bl) => 
+    if (eval_bexp(b, env)) eval_stmt(While(b, bl), eval_bl(bl, env))
+    else env
 }
 
 def eval_bl(bl: Block, env: Env) : Env = bl match {
@@ -195,5 +225,8 @@
   case s::bl => eval_bl(bl, eval_stmt(s, env))
 }
 
-//println(eval_stmt(p3a_ast.head, Nil.toMap))
-//println(eval_stmt(p3b_ast.head, Nil.toMap))
+//examples
+println(eval_stmt(p3a_ast.head, Map.empty))
+println(eval_stmt(p3b_ast.head, Map.empty))
+println(eval_bl(p4_ast.head, Map.empty))
+println(eval_bl(p5_ast.head, Map.empty))