Merge branch 'master' into master
This commit is contained in:
commit
b95c402e3f
@ -154,6 +154,8 @@ pub enum Token {
|
|||||||
Fn,
|
Fn,
|
||||||
Break,
|
Break,
|
||||||
Return,
|
Return,
|
||||||
|
PlusEquals,
|
||||||
|
MinusEquals,
|
||||||
LexErr(LexError),
|
LexErr(LexError),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -436,13 +438,25 @@ impl<'a> TokenIterator<'a> {
|
|||||||
'[' => return Some(Token::LSquare),
|
'[' => return Some(Token::LSquare),
|
||||||
']' => return Some(Token::RSquare),
|
']' => return Some(Token::RSquare),
|
||||||
'+' => {
|
'+' => {
|
||||||
if self.last.is_next_unary() { return Some(Token::UnaryPlus) }
|
return match self.char_stream.peek() {
|
||||||
else { return Some(Token::Plus) }
|
Some(&'=') => {
|
||||||
}
|
self.char_stream.next();
|
||||||
|
Some(Token::PlusEquals)
|
||||||
|
},
|
||||||
|
_ if self.last.is_next_unary() => Some(Token::UnaryPlus),
|
||||||
|
_ => Some(Token::Plus),
|
||||||
|
}
|
||||||
|
},
|
||||||
'-' => {
|
'-' => {
|
||||||
if self.last.is_next_unary() { return Some(Token::UnaryMinus) }
|
return match self.char_stream.peek() {
|
||||||
else { return Some(Token::Minus) }
|
Some(&'=') => {
|
||||||
}
|
self.char_stream.next();
|
||||||
|
Some(Token::MinusEquals)
|
||||||
|
},
|
||||||
|
_ if self.last.is_next_unary() => Some(Token::UnaryMinus),
|
||||||
|
_ => Some(Token::Minus),
|
||||||
|
}
|
||||||
|
},
|
||||||
'*' => return Some(Token::Multiply),
|
'*' => return Some(Token::Multiply),
|
||||||
'/' => {
|
'/' => {
|
||||||
match self.char_stream.peek() {
|
match self.char_stream.peek() {
|
||||||
@ -544,7 +558,7 @@ impl<'a> TokenIterator<'a> {
|
|||||||
impl<'a> Iterator for TokenIterator<'a> {
|
impl<'a> Iterator for TokenIterator<'a> {
|
||||||
type Item = Token;
|
type Item = Token;
|
||||||
|
|
||||||
// TODO - perhaps this could be optimized to only keep track of last for operators?
|
// TODO - perhaps this could be optimized?
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
self.last = match self.inner_next() {
|
self.last = match self.inner_next() {
|
||||||
Some(c) => c,
|
Some(c) => c,
|
||||||
@ -560,7 +574,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
|
||||||
@ -756,6 +772,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]),
|
||||||
|
34
src/tests.rs
34
src/tests.rs
@ -457,3 +457,37 @@ fn test_loop() {
|
|||||||
").unwrap()
|
").unwrap()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user