--- 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))