candidate increment/decrement implementation

This commit is contained in:
russ 2017-10-29 22:03:35 -07:00
parent 0b9865b24c
commit e042e1e31d
2 changed files with 72 additions and 4 deletions

View File

@ -152,6 +152,8 @@ pub enum Token {
Fn, Fn,
Break, Break,
Return, Return,
PlusEquals,
MinusEquals,
LexErr(LexError), LexErr(LexError),
} }
@ -350,8 +352,24 @@ impl<'a> Iterator for TokenIterator<'a> {
')' => return Some(Token::RParen), ')' => return Some(Token::RParen),
'[' => return Some(Token::LSquare), '[' => return Some(Token::LSquare),
']' => return Some(Token::RSquare), ']' => return Some(Token::RSquare),
'+' => return Some(Token::Plus), '+' => {
'-' => return Some(Token::Minus), return match self.char_stream.peek() {
Some(&'=') => {
self.char_stream.next();
Some(Token::PlusEquals)
},
_ => Some(Token::Plus)
}
},
'-' => {
return match self.char_stream.peek() {
Some(&'=') => {
self.char_stream.next();
Some(Token::MinusEquals)
},
_ => Some(Token::Minus)
}
},
'*' => return Some(Token::Multiply), '*' => return Some(Token::Multiply),
'/' => return Some(Token::Divide), '/' => return Some(Token::Divide),
';' => return Some(Token::Semicolon), ';' => return Some(Token::Semicolon),
@ -427,7 +445,9 @@ pub fn lex(input: &str) -> TokenIterator {
fn get_precedence(token: &Token) -> i32 { fn get_precedence(token: &Token) -> i32 {
match *token { match *token {
Token::Equals => 10, Token::Equals
| Token::PlusEquals
| Token::MinusEquals => 10,
Token::Or => 11, Token::Or => 11,
Token::And => 12, Token::And => 12,
Token::LessThan Token::LessThan
@ -458,7 +478,7 @@ fn parse_call_expr<'a>(id: String,
input: &mut Peekable<TokenIterator<'a>>) input: &mut Peekable<TokenIterator<'a>>)
-> Result<Expr, ParseError> { -> Result<Expr, ParseError> {
let mut args = Vec::new(); let mut args = Vec::new();
if let Some(&Token::RParen) = input.peek() { if let Some(&Token::RParen) = input.peek() {
input.next(); input.next();
return Ok(Expr::FnCall(id, args)); return Ok(Expr::FnCall(id, args));
@ -609,6 +629,20 @@ fn parse_binop<'a>(input: &mut Peekable<TokenIterator<'a>>,
Token::Multiply => Expr::FnCall("*".to_string(), vec![lhs_curr, rhs]), Token::Multiply => Expr::FnCall("*".to_string(), vec![lhs_curr, rhs]),
Token::Divide => Expr::FnCall("/".to_string(), vec![lhs_curr, rhs]), Token::Divide => Expr::FnCall("/".to_string(), vec![lhs_curr, rhs]),
Token::Equals => Expr::Assignment(Box::new(lhs_curr), Box::new(rhs)), Token::Equals => Expr::Assignment(Box::new(lhs_curr), Box::new(rhs)),
Token::PlusEquals => {
let lhs_copy = lhs_curr.clone();
Expr::Assignment(
Box::new(lhs_curr),
Box::new(Expr::FnCall("+".to_string(), vec![lhs_copy, rhs]))
)
},
Token::MinusEquals => {
let lhs_copy = lhs_curr.clone();
Expr::Assignment(
Box::new(lhs_curr),
Box::new(Expr::FnCall("-".to_string(), vec![lhs_copy, rhs]))
)
},
Token::Period => Expr::Dot(Box::new(lhs_curr), Box::new(rhs)), Token::Period => Expr::Dot(Box::new(lhs_curr), Box::new(rhs)),
Token::EqualTo => Expr::FnCall("==".to_string(), vec![lhs_curr, rhs]), Token::EqualTo => Expr::FnCall("==".to_string(), vec![lhs_curr, rhs]),
Token::NotEqualTo => Expr::FnCall("!=".to_string(), vec![lhs_curr, rhs]), Token::NotEqualTo => Expr::FnCall("!=".to_string(), vec![lhs_curr, rhs]),

View File

@ -401,3 +401,37 @@ fn test_array_with_structs() {
assert!(false); assert!(false);
} }
} }
#[test]
fn test_increment() {
let mut engine = Engine::new();
if let Ok(result) = engine.eval::<i64>("let x = 1; x += 2; x") {
assert_eq!(result, 3);
} else {
assert!(false);
}
if let Ok(result) = engine.eval::<String>("let s = \"test\"; s += \"ing\"; s") {
assert_eq!(result, "testing".to_owned());
} else {
assert!(false);
}
}
#[test]
fn test_decrement() {
let mut engine = Engine::new();
if let Ok(result) = engine.eval::<i64>("let x = 10; x -= 7; x") {
assert_eq!(result, 3);
} else {
assert!(false);
}
if let Ok(_) = engine.eval::<String>("let s = \"test\"; s -= \"ing\"; s") {
assert!(false);
} else {
assert!(true);
}
}