From 30b914e7b7d64fa7958da0e13b6dbf355f244785 Mon Sep 17 00:00:00 2001 From: jonathandturner Date: Thu, 3 Mar 2016 08:20:55 -0500 Subject: [PATCH] Add else to if --- src/engine.rs | 29 +++++++++++++++++++++++++++++ src/main.rs | 6 +++--- src/parser.rs | 20 ++++++++++++++++---- 3 files changed, 48 insertions(+), 7 deletions(-) diff --git a/src/engine.rs b/src/engine.rs index 845bcc3f..9aacee67 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -120,6 +120,7 @@ impl Engine { let result3 = self.call_fn("clone", Some(a3), None, None, None, None, None); let result4 = self.call_fn("clone", Some(a4), None, None, None, None, None); let result5 = self.call_fn("clone", Some(a5), None, None, None, None, None); + match (result1, result2, result3, result4, result5) { (Ok(r1), Ok(r2), Ok(r3), Ok(r4), Ok(r5)) => { new_scope.push((f.params[0].clone(), r1)); @@ -480,6 +481,20 @@ impl Engine { Err(_) => Err(EvalError::IfGuardMismatch) } } + Stmt::IfElse(ref guard, ref body, ref else_body) => { + let guard_result = try!(self.eval_expr(scope, guard)); + match guard_result.downcast::() { + Ok(g) => { + if *g { + self.eval_stmt(scope, body) + } + else { + self.eval_stmt(scope, else_body) + } + } + Err(_) => Err(EvalError::IfGuardMismatch) + } + } Stmt::While(ref guard, ref body) => { loop { let guard_result = try!(self.eval_expr(scope, guard)); @@ -684,6 +699,20 @@ fn test_if() { else { assert!(false); } + + if let Ok(result) = engine.eval("if false { 55 } else { 44 }".to_string()).unwrap().downcast::() { + assert_eq!(*result, 44); + } + else { + assert!(false); + } + + if let Ok(result) = engine.eval("if true { 55 } else { 44 }".to_string()).unwrap().downcast::() { + assert_eq!(*result, 55); + } + else { + assert!(false); + } } #[test] diff --git a/src/main.rs b/src/main.rs index 559d42d4..c5cfb599 100644 --- a/src/main.rs +++ b/src/main.rs @@ -13,13 +13,13 @@ mod parser; // Todo (in no particular order): // * Doc some examples -// * Hello world -// * Functions and methods -// * Registering types // * Maintaining state // * Overloading // * How it works // * Vectors +// * Return +// * Break +// * Tighten parser? // * Errors with positions? // * Remove empty box values? diff --git a/src/parser.rs b/src/parser.rs index 9e3e5d84..ce624f4c 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -84,8 +84,8 @@ pub struct FnDef { } #[derive(Debug, Clone)] -pub enum Stmt { If(Box, Box), While(Box, Box), Var(String, Option>), - Block(Box>), Expr(Box) } +pub enum Stmt { If(Box, Box), IfElse(Box, Box, Box), While(Box, Box), + Var(String, Option>), Block(Box>), Expr(Box) } #[derive(Debug, Clone)] pub enum Expr { IntConst(i32), Identifier(String), StringConst(String), FnCall(String, Box>), @@ -93,7 +93,7 @@ pub enum Expr { IntConst(i32), Identifier(String), StringConst(String), FnCall(S #[derive(Debug)] pub enum Token { IntConst(i32), Identifier(String), StringConst(String), LCurly, RCurly, LParen, RParen, LSquare, RSquare, - Plus, Minus, Multiply, Divide, Semicolon, Colon, Comma, Period, Equals, True, False, Var, If, While, + Plus, Minus, Multiply, Divide, Semicolon, Colon, Comma, Period, Equals, True, False, Var, If, Else, While, LessThan, GreaterThan, Bang, LessThanEqual, GreaterThanEqual, EqualTo, NotEqualTo, Pipe, Or, Ampersand, And, Fn, LexErr(LexError) } @@ -151,6 +151,9 @@ impl<'a> Iterator for TokenIterator<'a> { else if out == "if" { return Some(Token::If); } + else if out == "else" { + return Some(Token::Else); + } else if out == "while" { return Some(Token::While); } @@ -482,7 +485,16 @@ fn parse_if<'a>(input: &mut Peekable>) -> Result { + input.next(); + let else_body = try!(parse_block(input)); + Ok(Stmt::IfElse(Box::new(guard), Box::new(body), Box::new(else_body))) + } + _ => { + Ok(Stmt::If(Box::new(guard), Box::new(body))) + } + } } fn parse_while<'a>(input: &mut Peekable>) -> Result {