expressive/src/lib.rs

141 lines
5.8 KiB
Rust
Raw Normal View History

2019-03-15 17:46:00 +00:00
use configuration::{EmptyConfiguration, Configuration};
use error::Error;
use value::Value;
2016-11-16 16:12:26 +00:00
mod configuration;
mod error;
2016-11-16 16:12:26 +00:00
mod operator;
mod token;
mod tree;
mod value;
2019-03-15 11:42:18 +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)
}
2016-11-16 16:12:26 +00:00
2019-03-15 17:46:00 +00:00
pub fn eval_with_configuration(string: &str, configuration: &Configuration) -> Result<Value, Error> {
tree::tokens_to_operator_tree(token::tokenize(string)?)?.eval(configuration)
}
2016-11-16 16:12:26 +00:00
#[cfg(test)]
mod test {
use crate::{eval, value::Value};
2019-03-15 15:18:20 +00:00
use error::Error;
2019-03-15 17:46:00 +00:00
use configuration::HashMapConfiguration;
use eval_with_configuration;
2016-11-16 16:12:26 +00:00
#[test]
2019-03-15 15:18:20 +00:00
fn test_unary_examples() {
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)));
2019-03-15 17:28:59 +00:00
assert_eq!(eval("blub"), Err(Error::IdentifierNotFound("blub".to_string())));
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() {
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() {
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)));
}
#[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)));
}
2019-03-15 17:46:00 +00:00
#[test]
fn test_with_configuration() {
let mut configuration = HashMapConfiguration::new();
configuration.insert("tr".to_string(), Value::Boolean(true));
configuration.insert("fa".to_string(), Value::Boolean(false));
configuration.insert("five".to_string(), Value::Int(5));
configuration.insert("six".to_string(), Value::Int(6));
configuration.insert("half".to_string(), Value::Float(0.5));
configuration.insert("zero".to_string(), Value::Int(0));
assert_eq!(eval_with_configuration("tr", &configuration), Ok(Value::Boolean(true)));
assert_eq!(eval_with_configuration("fa", &configuration), Ok(Value::Boolean(false)));
assert_eq!(eval_with_configuration("tr && false", &configuration), Ok(Value::Boolean(false)));
assert_eq!(eval_with_configuration("five + six", &configuration), Ok(Value::Int(11)));
assert_eq!(eval_with_configuration("five * half", &configuration), Ok(Value::Float(2.5)));
assert_eq!(eval_with_configuration("five < six && true", &configuration), Ok(Value::Boolean(true)));
}
2019-03-15 17:19:59 +00:00
#[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
}