Natively handle negative numbers in tokenizer instead of the neg() function.
This commit is contained in:
parent
c5b40783ef
commit
01d04f717b
@ -338,6 +338,7 @@ impl Token {
|
|||||||
use self::Token::*;
|
use self::Token::*;
|
||||||
|
|
||||||
match *self {
|
match *self {
|
||||||
|
LexError(_) |
|
||||||
LeftBrace | // (+expr) - is unary
|
LeftBrace | // (+expr) - is unary
|
||||||
// RightBrace | {expr} - expr not unary & is closing
|
// RightBrace | {expr} - expr not unary & is closing
|
||||||
LeftParen | // {-expr} - is unary
|
LeftParen | // {-expr} - is unary
|
||||||
@ -386,6 +387,7 @@ impl Token {
|
|||||||
PowerOf |
|
PowerOf |
|
||||||
In |
|
In |
|
||||||
PowerOfAssign => true,
|
PowerOfAssign => true,
|
||||||
|
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -398,6 +400,7 @@ impl Token {
|
|||||||
RightBrace | RightParen | RightBracket | Plus | Minus | Multiply | Divide | Comma
|
RightBrace | RightParen | RightBracket | Plus | Minus | Multiply | Divide | Comma
|
||||||
| Equals | LessThan | GreaterThan | LessThanEqualsTo | GreaterThanEqualsTo
|
| Equals | LessThan | GreaterThan | LessThanEqualsTo | GreaterThanEqualsTo
|
||||||
| EqualsTo | NotEqualsTo | Pipe | Or | Ampersand | And | PowerOf => true,
|
| EqualsTo | NotEqualsTo | Pipe | Or | Ampersand | And | PowerOf => true,
|
||||||
|
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -567,6 +570,8 @@ impl<'a> TokenIterator<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn inner_next(&mut self) -> Option<(Token, Position)> {
|
fn inner_next(&mut self) -> Option<(Token, Position)> {
|
||||||
|
let mut negated = false;
|
||||||
|
|
||||||
while let Some(c) = self.char_stream.next() {
|
while let Some(c) = self.char_stream.next() {
|
||||||
self.advance();
|
self.advance();
|
||||||
|
|
||||||
@ -653,6 +658,10 @@ impl<'a> TokenIterator<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if negated {
|
||||||
|
result.insert(0, '-');
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(radix) = radix_base {
|
if let Some(radix) = radix_base {
|
||||||
let out: String = result.iter().skip(2).filter(|&&c| c != '_').collect();
|
let out: String = result.iter().skip(2).filter(|&&c| c != '_').collect();
|
||||||
|
|
||||||
@ -761,20 +770,17 @@ impl<'a> TokenIterator<'a> {
|
|||||||
pos,
|
pos,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
'-' => {
|
'-' => match self.char_stream.peek() {
|
||||||
return Some((
|
// Negative number?
|
||||||
match self.char_stream.peek() {
|
Some('0'..='9') => negated = true,
|
||||||
Some(&'=') => {
|
Some('=') => {
|
||||||
self.char_stream.next();
|
self.char_stream.next();
|
||||||
self.advance();
|
self.advance();
|
||||||
Token::MinusAssign
|
return Some((Token::MinusAssign, pos));
|
||||||
}
|
}
|
||||||
_ if self.last.is_next_unary() => Token::UnaryMinus,
|
_ if self.last.is_next_unary() => return Some((Token::UnaryMinus, pos)),
|
||||||
_ => Token::Minus,
|
_ => return Some((Token::Minus, pos)),
|
||||||
},
|
},
|
||||||
pos,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
'*' => {
|
'*' => {
|
||||||
return Some((
|
return Some((
|
||||||
match self.char_stream.peek() {
|
match self.char_stream.peek() {
|
||||||
@ -1034,19 +1040,28 @@ fn get_precedence(token: &Token) -> i8 {
|
|||||||
| Token::XOrAssign
|
| Token::XOrAssign
|
||||||
| Token::ModuloAssign
|
| Token::ModuloAssign
|
||||||
| Token::PowerOfAssign => 10,
|
| Token::PowerOfAssign => 10,
|
||||||
|
|
||||||
Token::Or | Token::XOr | Token::Pipe => 11,
|
Token::Or | Token::XOr | Token::Pipe => 11,
|
||||||
|
|
||||||
Token::And | Token::Ampersand => 12,
|
Token::And | Token::Ampersand => 12,
|
||||||
|
|
||||||
Token::LessThan
|
Token::LessThan
|
||||||
| Token::LessThanEqualsTo
|
| Token::LessThanEqualsTo
|
||||||
| Token::GreaterThan
|
| Token::GreaterThan
|
||||||
| Token::GreaterThanEqualsTo
|
| Token::GreaterThanEqualsTo
|
||||||
| Token::EqualsTo
|
| Token::EqualsTo
|
||||||
| Token::NotEqualsTo => 15,
|
| Token::NotEqualsTo => 15,
|
||||||
|
|
||||||
Token::Plus | Token::Minus => 20,
|
Token::Plus | Token::Minus => 20,
|
||||||
|
|
||||||
Token::Divide | Token::Multiply | Token::PowerOf => 40,
|
Token::Divide | Token::Multiply | Token::PowerOf => 40,
|
||||||
|
|
||||||
Token::LeftShift | Token::RightShift => 50,
|
Token::LeftShift | Token::RightShift => 50,
|
||||||
|
|
||||||
Token::Modulo => 60,
|
Token::Modulo => 60,
|
||||||
|
|
||||||
Token::Period => 100,
|
Token::Period => 100,
|
||||||
|
|
||||||
_ => -1,
|
_ => -1,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1056,6 +1071,7 @@ fn parse_paren_expr<'a>(
|
|||||||
begin: Position,
|
begin: Position,
|
||||||
) -> Result<Expr, ParseError> {
|
) -> Result<Expr, ParseError> {
|
||||||
match input.peek() {
|
match input.peek() {
|
||||||
|
// ()
|
||||||
Some((Token::RightParen, _)) => {
|
Some((Token::RightParen, _)) => {
|
||||||
input.next();
|
input.next();
|
||||||
return Ok(Expr::Unit(begin));
|
return Ok(Expr::Unit(begin));
|
||||||
@ -1272,16 +1288,22 @@ fn parse_unary<'a>(input: &mut Peekable<TokenIterator<'a>>) -> Result<Expr, Pars
|
|||||||
Some(&(Token::UnaryMinus, pos)) => {
|
Some(&(Token::UnaryMinus, pos)) => {
|
||||||
input.next();
|
input.next();
|
||||||
|
|
||||||
Ok(Expr::FunctionCall(
|
match parse_unary(input) {
|
||||||
"-".into(),
|
// Negative integer
|
||||||
vec![parse_primary(input)?],
|
Ok(Expr::IntegerConstant(i, pos)) => Ok(i
|
||||||
None,
|
.checked_neg()
|
||||||
pos,
|
.map(|x| Expr::IntegerConstant(x, pos))
|
||||||
))
|
.unwrap_or_else(|| Expr::FloatConstant(-(i as f64), pos))),
|
||||||
|
// Negative float
|
||||||
|
Ok(Expr::FloatConstant(f, pos)) => Ok(Expr::FloatConstant(-f, pos)),
|
||||||
|
// Call negative function
|
||||||
|
Ok(expr) => Ok(Expr::FunctionCall("-".into(), vec![expr], None, pos)),
|
||||||
|
err @ Err(_) => err,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Some(&(Token::UnaryPlus, _)) => {
|
Some(&(Token::UnaryPlus, _)) => {
|
||||||
input.next();
|
input.next();
|
||||||
parse_primary(input)
|
parse_unary(input)
|
||||||
}
|
}
|
||||||
Some(&(Token::Bang, pos)) => {
|
Some(&(Token::Bang, pos)) => {
|
||||||
input.next();
|
input.next();
|
||||||
|
@ -21,7 +21,7 @@ fn test_math() -> Result<(), EvalAltResult> {
|
|||||||
Err(EvalAltResult::ErrorArithmetic(_, _)) => (),
|
Err(EvalAltResult::ErrorArithmetic(_, _)) => (),
|
||||||
r => panic!("should return overflow error: {:?}", r),
|
r => panic!("should return overflow error: {:?}", r),
|
||||||
}
|
}
|
||||||
match engine.eval::<i64>("(-9223372036854775807) - 2") {
|
match engine.eval::<i64>("-9223372036854775808 - 1") {
|
||||||
Err(EvalAltResult::ErrorArithmetic(_, _)) => (),
|
Err(EvalAltResult::ErrorArithmetic(_, _)) => (),
|
||||||
r => panic!("should return underflow error: {:?}", r),
|
r => panic!("should return underflow error: {:?}", r),
|
||||||
}
|
}
|
||||||
|
@ -5,8 +5,8 @@ fn test_unary_minus() -> Result<(), EvalAltResult> {
|
|||||||
let mut engine = Engine::new();
|
let mut engine = Engine::new();
|
||||||
|
|
||||||
assert_eq!(engine.eval::<i64>("let x = -5; x")?, -5);
|
assert_eq!(engine.eval::<i64>("let x = -5; x")?, -5);
|
||||||
assert_eq!(engine.eval::<i64>("fn n(x) { -x } n(5)")?, -5);
|
assert_eq!(engine.eval::<i64>("fn neg(x) { -x } neg(5)")?, -5);
|
||||||
assert_eq!(engine.eval::<i64>("5 - -(-5)")?, 0);
|
assert_eq!(engine.eval::<i64>("5 - -+++--+-5")?, 0);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user