Merge pull request #40 from rustysec/inc_dec

candidate increment/decrement implementation
This commit is contained in:
Lukáš Hozda [magnusi] 2017-10-30 08:35:07 +01:00 committed by GitHub
commit 68f4f77cb7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 72 additions and 4 deletions

View File

@ -152,6 +152,8 @@ pub enum Token {
Fn,
Break,
Return,
PlusEquals,
MinusEquals,
LexErr(LexError),
}
@ -350,8 +352,24 @@ impl<'a> Iterator for TokenIterator<'a> {
')' => return Some(Token::RParen),
'[' => return Some(Token::LSquare),
']' => 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::Divide),
';' => return Some(Token::Semicolon),
@ -427,7 +445,9 @@ pub fn lex(input: &str) -> TokenIterator {
fn get_precedence(token: &Token) -> i32 {
match *token {
Token::Equals => 10,
Token::Equals
| Token::PlusEquals
| Token::MinusEquals => 10,
Token::Or => 11,
Token::And => 12,
Token::LessThan
@ -458,7 +478,7 @@ fn parse_call_expr<'a>(id: String,
input: &mut Peekable<TokenIterator<'a>>)
-> Result<Expr, ParseError> {
let mut args = Vec::new();
if let Some(&Token::RParen) = input.peek() {
input.next();
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::Divide => Expr::FnCall("/".to_string(), vec![lhs_curr, 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::EqualTo => 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);
}
}
#[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);
}
}