2019-03-15 15:11:31 +00:00
|
|
|
use configuration::EmptyConfiguration;
|
|
|
|
use error::Error;
|
|
|
|
use value::Value;
|
2016-11-16 16:12:26 +00:00
|
|
|
|
2019-03-15 15:11:31 +00:00
|
|
|
mod configuration;
|
|
|
|
mod error;
|
2016-11-16 16:12:26 +00:00
|
|
|
mod operator;
|
2019-03-15 15:11:31 +00:00
|
|
|
mod token;
|
2016-11-20 08:04:06 +00:00
|
|
|
mod tree;
|
2019-03-15 15:11:31 +00:00
|
|
|
mod value;
|
2019-03-15 11:42:18 +00:00
|
|
|
|
2019-03-15 15:11:31 +00:00
|
|
|
pub fn eval(string: &str) -> Result<Value, Error> {
|
2019-03-15 17:19:59 +00:00
|
|
|
tree::tokens_to_operator_tree(token::tokenize(string)?)?.eval(&EmptyConfiguration)
|
2017-02-13 00:20:53 +00:00
|
|
|
}
|
2016-11-16 16:12:26 +00:00
|
|
|
|
|
|
|
#[cfg(test)]
|
2019-03-15 15:11:31 +00:00
|
|
|
mod test {
|
|
|
|
use crate::{eval, value::Value};
|
2019-03-15 15:18:20 +00:00
|
|
|
use error::Error;
|
2016-11-16 16:12:26 +00:00
|
|
|
|
|
|
|
#[test]
|
2019-03-15 15:18:20 +00:00
|
|
|
fn test_unary_examples() {
|
2019-03-15 15:40:38 +00:00
|
|
|
assert_eq!(eval("3"), Ok(Value::Int(3)));
|
2019-03-15 15:43:26 +00:00
|
|
|
assert_eq!(eval("3.3"), Ok(Value::Float(3.3)));
|
2019-03-15 15:18:20 +00:00
|
|
|
assert_eq!(eval("true"), Ok(Value::Boolean(true)));
|
|
|
|
assert_eq!(eval("false"), Ok(Value::Boolean(false)));
|
|
|
|
assert_eq!(eval("blub"), Err(Error::IdentifierNotFound));
|
2019-03-15 16:27:10 +00:00
|
|
|
assert_eq!(eval("-3"), Ok(Value::Int(-3)));
|
|
|
|
assert_eq!(eval("-3.6"), Ok(Value::Float(-3.6)));
|
|
|
|
assert_eq!(eval("----3"), Ok(Value::Int(3)));
|
2019-03-15 15:18:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_binary_examples() {
|
2019-03-15 15:40:38 +00:00
|
|
|
assert_eq!(eval("1+3"), Ok(Value::Int(4)));
|
|
|
|
assert_eq!(eval("3+1"), Ok(Value::Int(4)));
|
|
|
|
assert_eq!(eval("3-5"), Ok(Value::Int(-2)));
|
|
|
|
assert_eq!(eval("5-3"), Ok(Value::Int(2)));
|
|
|
|
assert_eq!(eval("5 / 4"), Ok(Value::Int(1)));
|
|
|
|
assert_eq!(eval("5 *3"), Ok(Value::Int(15)));
|
2019-03-15 15:43:26 +00:00
|
|
|
assert_eq!(eval("1.0+3"), Ok(Value::Float(4.0)));
|
|
|
|
assert_eq!(eval("3.0+1"), Ok(Value::Float(4.0)));
|
|
|
|
assert_eq!(eval("3-5.0"), Ok(Value::Float(-2.0)));
|
|
|
|
assert_eq!(eval("5-3.0"), Ok(Value::Float(2.0)));
|
|
|
|
assert_eq!(eval("5 / 4.0"), Ok(Value::Float(1.25)));
|
|
|
|
assert_eq!(eval("5.0 *3"), Ok(Value::Float(15.0)));
|
2019-03-15 16:27:10 +00:00
|
|
|
assert_eq!(eval("5.0 *-3"), Ok(Value::Float(-15.0)));
|
|
|
|
assert_eq!(eval("5.0 *- 3"), Ok(Value::Float(-15.0)));
|
|
|
|
assert_eq!(eval("5.0 * -3"), Ok(Value::Float(-15.0)));
|
|
|
|
assert_eq!(eval("5.0 * - 3"), Ok(Value::Float(-15.0)));
|
|
|
|
assert_eq!(eval("-5.0 *-3"), Ok(Value::Float(15.0)));
|
|
|
|
assert_eq!(eval("3+-1"), Ok(Value::Int(2)));
|
|
|
|
assert_eq!(eval("-3-5"), Ok(Value::Int(-8)));
|
|
|
|
assert_eq!(eval("-5--3"), Ok(Value::Int(-2)));
|
2016-11-16 16:12:26 +00:00
|
|
|
}
|
2019-03-15 15:24:45 +00:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_arithmetic_precedence_examples() {
|
2019-03-15 15:40:38 +00:00
|
|
|
assert_eq!(eval("1+3-2"), Ok(Value::Int(2)));
|
|
|
|
assert_eq!(eval("3+1*5"), Ok(Value::Int(8)));
|
|
|
|
assert_eq!(eval("2*3-5"), Ok(Value::Int(1)));
|
|
|
|
assert_eq!(eval("5-3/3"), Ok(Value::Int(4)));
|
|
|
|
assert_eq!(eval("5 / 4*2"), Ok(Value::Int(2)));
|
|
|
|
assert_eq!(eval("1-5 *3/15"), Ok(Value::Int(0)));
|
2019-03-15 15:43:26 +00:00
|
|
|
assert_eq!(eval("15/7/2.0"), Ok(Value::Float(1.0)));
|
2019-03-15 16:27:10 +00:00
|
|
|
assert_eq!(eval("15.0/7/2"), Ok(Value::Float(15.0 / 7.0 / 2.0)));
|
|
|
|
assert_eq!(eval("15.0/-7/2"), Ok(Value::Float(15.0 / -7.0 / 2.0)));
|
|
|
|
assert_eq!(eval("-15.0/7/2"), Ok(Value::Float(-15.0 / 7.0 / 2.0)));
|
|
|
|
assert_eq!(eval("-15.0/7/-2"), Ok(Value::Float(-15.0 / 7.0 / -2.0)));
|
2019-03-15 15:24:45 +00:00
|
|
|
}
|
2019-03-15 16:27:10 +00:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_braced_examples() {
|
|
|
|
assert_eq!(eval("(1)"), Ok(Value::Int(1)));
|
|
|
|
assert_eq!(eval("( 1.0 )"), Ok(Value::Float(1.0)));
|
|
|
|
assert_eq!(eval("( true)"), Ok(Value::Boolean(true)));
|
|
|
|
assert_eq!(eval("( -1 )"), Ok(Value::Int(-1)));
|
|
|
|
assert_eq!(eval("-(1)"), Ok(Value::Int(-1)));
|
|
|
|
assert_eq!(eval("-(1 + 3) * 7"), Ok(Value::Int(-28)));
|
|
|
|
assert_eq!(eval("(1 * 1) - 3"), Ok(Value::Int(-2)));
|
|
|
|
assert_eq!(eval("4 / (2 * 2)"), Ok(Value::Int(1)));
|
|
|
|
assert_eq!(eval("7/(7/(7/(7/(7/(7)))))"), Ok(Value::Int(1)));
|
|
|
|
}
|
|
|
|
|
2019-03-15 16:34:40 +00:00
|
|
|
#[test]
|
|
|
|
fn test_mod_examples() {
|
|
|
|
assert_eq!(eval("1 % 4"), Ok(Value::Int(1)));
|
|
|
|
assert_eq!(eval("6 % 4"), Ok(Value::Int(2)));
|
|
|
|
assert_eq!(eval("1 % 4 + 2"), Ok(Value::Int(3)));
|
|
|
|
}
|
|
|
|
|
2019-03-15 16:27:10 +00:00
|
|
|
#[test]
|
2019-03-15 17:19:59 +00:00
|
|
|
fn test_boolean_examples() {
|
|
|
|
assert_eq!(eval("true && false"), Ok(Value::Boolean(false)));
|
2019-03-15 17:22:14 +00:00
|
|
|
assert_eq!(
|
|
|
|
eval("true && false || true && true"),
|
|
|
|
Ok(Value::Boolean(true))
|
|
|
|
);
|
2019-03-15 17:19:59 +00:00
|
|
|
assert_eq!(eval("5 > 4 && 1 <= 1"), Ok(Value::Boolean(true)));
|
|
|
|
assert_eq!(eval("5.0 <= 4.9 || !(4 > 3.5)"), Ok(Value::Boolean(false)));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_errors() {
|
2019-03-15 16:27:10 +00:00
|
|
|
assert_eq!(
|
|
|
|
eval("-true"),
|
|
|
|
Err(Error::expected_number(Value::Boolean(true)))
|
|
|
|
);
|
|
|
|
assert_eq!(
|
|
|
|
eval("1-true"),
|
|
|
|
Err(Error::expected_number(Value::Boolean(true)))
|
|
|
|
);
|
|
|
|
assert_eq!(eval("true-"), Err(Error::wrong_argument_amount(1, 2)));
|
2019-03-15 17:19:59 +00:00
|
|
|
assert_eq!(eval("!(()true)"), Err(Error::AppendedToLeafNode));
|
2019-03-15 16:27:10 +00:00
|
|
|
}
|
2016-11-16 16:12:26 +00:00
|
|
|
}
|