diff -r 7717f20f0504 -r d65525aeca08 while.scala --- 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))