parent
a33c91813b
commit
8a49bf9c11
@ -1,13 +1,13 @@
|
|||||||
use token;
|
|
||||||
use tree;
|
|
||||||
use value::TupleType;
|
|
||||||
use Configuration;
|
use Configuration;
|
||||||
use EmptyConfiguration;
|
use EmptyConfiguration;
|
||||||
use Error;
|
use Error;
|
||||||
use FloatType;
|
use FloatType;
|
||||||
use IntType;
|
use IntType;
|
||||||
use Node;
|
use Node;
|
||||||
|
use token;
|
||||||
|
use tree;
|
||||||
use Value;
|
use Value;
|
||||||
|
use value::TupleType;
|
||||||
|
|
||||||
/// Evaluate the given expression string.
|
/// Evaluate the given expression string.
|
||||||
///
|
///
|
||||||
@ -56,7 +56,7 @@ pub fn eval_with_configuration(
|
|||||||
/// ```rust
|
/// ```rust
|
||||||
/// use evalexpr::*;
|
/// use evalexpr::*;
|
||||||
///
|
///
|
||||||
/// let precomputed = build_operator_tree("one + two + three").unwrap();
|
/// let precomputed = build_operator_tree("one + two + three").unwrap(); // Do proper error handling here
|
||||||
///
|
///
|
||||||
/// let mut configuration = HashMapConfiguration::new();
|
/// let mut configuration = HashMapConfiguration::new();
|
||||||
/// configuration.insert_variable("one", 1);
|
/// configuration.insert_variable("one", 1);
|
||||||
|
15
src/lib.rs
15
src/lib.rs
@ -71,7 +71,7 @@
|
|||||||
//! ```rust
|
//! ```rust
|
||||||
//! use evalexpr::*;
|
//! use evalexpr::*;
|
||||||
//!
|
//!
|
||||||
//! let precompiled = build_operator_tree("a * b - c > 5").unwrap();
|
//! let precompiled = build_operator_tree("a * b - c > 5").unwrap(); // Do proper error handling here
|
||||||
//!
|
//!
|
||||||
//! let mut configuration = HashMapConfiguration::new();
|
//! let mut configuration = HashMapConfiguration::new();
|
||||||
//! configuration.insert_variable("a", 6);
|
//! configuration.insert_variable("a", 6);
|
||||||
@ -269,6 +269,13 @@ extern crate ron;
|
|||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
extern crate serde;
|
extern crate serde;
|
||||||
|
|
||||||
|
pub use configuration::{Configuration, EmptyConfiguration, HashMapConfiguration};
|
||||||
|
pub use error::Error;
|
||||||
|
pub use function::Function;
|
||||||
|
pub use interface::*;
|
||||||
|
pub use tree::Node;
|
||||||
|
pub use value::{FloatType, IntType, Value};
|
||||||
|
|
||||||
mod configuration;
|
mod configuration;
|
||||||
pub mod error;
|
pub mod error;
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
@ -282,9 +289,3 @@ mod value;
|
|||||||
|
|
||||||
// Exports
|
// Exports
|
||||||
|
|
||||||
pub use configuration::{Configuration, EmptyConfiguration, HashMapConfiguration};
|
|
||||||
pub use error::Error;
|
|
||||||
pub use function::Function;
|
|
||||||
pub use interface::*;
|
|
||||||
pub use tree::Node;
|
|
||||||
pub use value::{FloatType, IntType, Value};
|
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
use crate::{configuration::Configuration, error::*, value::Value};
|
|
||||||
use function::builtin::builtin_function;
|
|
||||||
use std::fmt::{Debug, Display};
|
use std::fmt::{Debug, Display};
|
||||||
|
|
||||||
|
use function::builtin::builtin_function;
|
||||||
|
|
||||||
|
use crate::{configuration::Configuration, error::*, value::Value};
|
||||||
|
|
||||||
mod display;
|
mod display;
|
||||||
|
|
||||||
pub trait Operator: Debug + Display {
|
pub trait Operator: Debug + Display {
|
||||||
@ -140,11 +142,8 @@ impl Operator for Add {
|
|||||||
expect_number(&arguments[0])?;
|
expect_number(&arguments[0])?;
|
||||||
expect_number(&arguments[1])?;
|
expect_number(&arguments[1])?;
|
||||||
|
|
||||||
if arguments[0].is_int() && arguments[1].is_int() {
|
if let (Ok(a), Ok(b)) = (arguments[0].as_int(), arguments[1].as_int()) {
|
||||||
let result = arguments[0]
|
let result = a.checked_add(b);
|
||||||
.as_int()
|
|
||||||
.unwrap()
|
|
||||||
.checked_add(arguments[1].as_int().unwrap());
|
|
||||||
if let Some(result) = result {
|
if let Some(result) = result {
|
||||||
Ok(Value::Int(result))
|
Ok(Value::Int(result))
|
||||||
} else {
|
} else {
|
||||||
@ -179,11 +178,8 @@ impl Operator for Sub {
|
|||||||
expect_number(&arguments[0])?;
|
expect_number(&arguments[0])?;
|
||||||
expect_number(&arguments[1])?;
|
expect_number(&arguments[1])?;
|
||||||
|
|
||||||
if arguments[0].is_int() && arguments[1].is_int() {
|
if let (Ok(a), Ok(b)) = (arguments[0].as_int(), arguments[1].as_int()) {
|
||||||
let result = arguments[0]
|
let result = a.checked_sub(b);
|
||||||
.as_int()
|
|
||||||
.unwrap()
|
|
||||||
.checked_sub(arguments[1].as_int().unwrap());
|
|
||||||
if let Some(result) = result {
|
if let Some(result) = result {
|
||||||
Ok(Value::Int(result))
|
Ok(Value::Int(result))
|
||||||
} else {
|
} else {
|
||||||
@ -217,8 +213,8 @@ impl Operator for Neg {
|
|||||||
expect_operator_argument_amount(arguments.len(), 1)?;
|
expect_operator_argument_amount(arguments.len(), 1)?;
|
||||||
expect_number(&arguments[0])?;
|
expect_number(&arguments[0])?;
|
||||||
|
|
||||||
if arguments[0].is_int() {
|
if let Ok(a) = arguments[0].as_int() {
|
||||||
let result = arguments[0].as_int().unwrap().checked_neg();
|
let result = a.checked_neg();
|
||||||
if let Some(result) = result {
|
if let Some(result) = result {
|
||||||
Ok(Value::Int(result))
|
Ok(Value::Int(result))
|
||||||
} else {
|
} else {
|
||||||
@ -248,11 +244,8 @@ impl Operator for Mul {
|
|||||||
expect_number(&arguments[0])?;
|
expect_number(&arguments[0])?;
|
||||||
expect_number(&arguments[1])?;
|
expect_number(&arguments[1])?;
|
||||||
|
|
||||||
if arguments[0].is_int() && arguments[1].is_int() {
|
if let (Ok(a), Ok(b)) = (arguments[0].as_int(), arguments[1].as_int()) {
|
||||||
let result = arguments[0]
|
let result = a.checked_mul(b);
|
||||||
.as_int()
|
|
||||||
.unwrap()
|
|
||||||
.checked_mul(arguments[1].as_int().unwrap());
|
|
||||||
if let Some(result) = result {
|
if let Some(result) = result {
|
||||||
Ok(Value::Int(result))
|
Ok(Value::Int(result))
|
||||||
} else {
|
} else {
|
||||||
@ -287,11 +280,8 @@ impl Operator for Div {
|
|||||||
expect_number(&arguments[0])?;
|
expect_number(&arguments[0])?;
|
||||||
expect_number(&arguments[1])?;
|
expect_number(&arguments[1])?;
|
||||||
|
|
||||||
if arguments[0].is_int() && arguments[1].is_int() {
|
if let (Ok(a), Ok(b)) = (arguments[0].as_int(), arguments[1].as_int()) {
|
||||||
let result = arguments[0]
|
let result = a.checked_div(b);
|
||||||
.as_int()
|
|
||||||
.unwrap()
|
|
||||||
.checked_div(arguments[1].as_int().unwrap());
|
|
||||||
if let Some(result) = result {
|
if let Some(result) = result {
|
||||||
Ok(Value::Int(result))
|
Ok(Value::Int(result))
|
||||||
} else {
|
} else {
|
||||||
@ -326,11 +316,8 @@ impl Operator for Mod {
|
|||||||
expect_number(&arguments[0])?;
|
expect_number(&arguments[0])?;
|
||||||
expect_number(&arguments[1])?;
|
expect_number(&arguments[1])?;
|
||||||
|
|
||||||
if arguments[0].is_int() && arguments[1].is_int() {
|
if let (Ok(a), Ok(b)) = (arguments[0].as_int(), arguments[1].as_int()) {
|
||||||
let result = arguments[0]
|
let result = a.checked_rem(b);
|
||||||
.as_int()
|
|
||||||
.unwrap()
|
|
||||||
.checked_rem(arguments[1].as_int().unwrap());
|
|
||||||
if let Some(result) = result {
|
if let Some(result) = result {
|
||||||
Ok(Value::Int(result))
|
Ok(Value::Int(result))
|
||||||
} else {
|
} else {
|
||||||
@ -440,8 +427,8 @@ impl Operator for Gt {
|
|||||||
expect_number(&arguments[0])?;
|
expect_number(&arguments[0])?;
|
||||||
expect_number(&arguments[1])?;
|
expect_number(&arguments[1])?;
|
||||||
|
|
||||||
if arguments[0].is_int() && arguments[1].is_int() {
|
if let (Ok(a), Ok(b)) = (arguments[0].as_int(), arguments[1].as_int()) {
|
||||||
if arguments[0].as_int().unwrap() > arguments[1].as_int().unwrap() {
|
if a > b {
|
||||||
Ok(Value::Boolean(true))
|
Ok(Value::Boolean(true))
|
||||||
} else {
|
} else {
|
||||||
Ok(Value::Boolean(false))
|
Ok(Value::Boolean(false))
|
||||||
@ -474,8 +461,8 @@ impl Operator for Lt {
|
|||||||
expect_number(&arguments[0])?;
|
expect_number(&arguments[0])?;
|
||||||
expect_number(&arguments[1])?;
|
expect_number(&arguments[1])?;
|
||||||
|
|
||||||
if arguments[0].is_int() && arguments[1].is_int() {
|
if let (Ok(a), Ok(b)) = (arguments[0].as_int(), arguments[1].as_int()) {
|
||||||
if arguments[0].as_int().unwrap() < arguments[1].as_int().unwrap() {
|
if a < b {
|
||||||
Ok(Value::Boolean(true))
|
Ok(Value::Boolean(true))
|
||||||
} else {
|
} else {
|
||||||
Ok(Value::Boolean(false))
|
Ok(Value::Boolean(false))
|
||||||
@ -508,8 +495,8 @@ impl Operator for Geq {
|
|||||||
expect_number(&arguments[0])?;
|
expect_number(&arguments[0])?;
|
||||||
expect_number(&arguments[1])?;
|
expect_number(&arguments[1])?;
|
||||||
|
|
||||||
if arguments[0].is_int() && arguments[1].is_int() {
|
if let (Ok(a), Ok(b)) = (arguments[0].as_int(), arguments[1].as_int()) {
|
||||||
if arguments[0].as_int().unwrap() >= arguments[1].as_int().unwrap() {
|
if a >= b {
|
||||||
Ok(Value::Boolean(true))
|
Ok(Value::Boolean(true))
|
||||||
} else {
|
} else {
|
||||||
Ok(Value::Boolean(false))
|
Ok(Value::Boolean(false))
|
||||||
@ -542,8 +529,8 @@ impl Operator for Leq {
|
|||||||
expect_number(&arguments[0])?;
|
expect_number(&arguments[0])?;
|
||||||
expect_number(&arguments[1])?;
|
expect_number(&arguments[1])?;
|
||||||
|
|
||||||
if arguments[0].is_int() && arguments[1].is_int() {
|
if let (Ok(a), Ok(b)) = (arguments[0].as_int(), arguments[1].as_int()) {
|
||||||
if arguments[0].as_int().unwrap() <= arguments[1].as_int().unwrap() {
|
if a <= b {
|
||||||
Ok(Value::Boolean(true))
|
Ok(Value::Boolean(true))
|
||||||
} else {
|
} else {
|
||||||
Ok(Value::Boolean(false))
|
Ok(Value::Boolean(false))
|
||||||
|
@ -20,7 +20,7 @@ mod display;
|
|||||||
///
|
///
|
||||||
/// let mut configuration = HashMapConfiguration::new();
|
/// let mut configuration = HashMapConfiguration::new();
|
||||||
/// configuration.insert_variable("alpha", 2);
|
/// configuration.insert_variable("alpha", 2);
|
||||||
/// let node = build_operator_tree("1 + alpha").unwrap();
|
/// let node = build_operator_tree("1 + alpha").unwrap(); // Do proper error handling here
|
||||||
/// assert_eq!(node.eval_with_configuration(&configuration), Ok(Value::from(3)));
|
/// assert_eq!(node.eval_with_configuration(&configuration), Ok(Value::from(3)));
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
@ -290,14 +290,18 @@ pub(crate) fn tokens_to_operator_tree(tokens: Vec<Token>) -> Result<Node, Error>
|
|||||||
|
|
||||||
if root.len() > 1 {
|
if root.len() > 1 {
|
||||||
Err(Error::UnmatchedLBrace)
|
Err(Error::UnmatchedLBrace)
|
||||||
} else if root.len() == 0 {
|
} else if let Some(mut root) = root.pop() {
|
||||||
Err(Error::UnmatchedRBrace)
|
if root.children().len() > 1 {
|
||||||
} else {
|
Err(Error::wrong_operator_argument_amount(
|
||||||
let mut root = root.pop().unwrap();
|
root.children().len(),
|
||||||
if root.children().len() == 1 {
|
1,
|
||||||
Ok(root.children.pop().unwrap())
|
))
|
||||||
|
} else if let Some(child) = root.children.pop() {
|
||||||
|
Ok(child)
|
||||||
} else {
|
} else {
|
||||||
Err(Error::EmptyExpression)
|
Err(Error::EmptyExpression)
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
Err(Error::UnmatchedRBrace)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -159,15 +159,15 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_value_conversions() {
|
fn test_value_conversions() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Value::from("string").as_string().unwrap(),
|
Value::from("string").as_string(),
|
||||||
String::from("string")
|
Ok(String::from("string"))
|
||||||
);
|
);
|
||||||
assert_eq!(Value::from(3).as_int().unwrap(), 3);
|
assert_eq!(Value::from(3).as_int(), Ok(3));
|
||||||
assert_eq!(Value::from(3.3).as_float().unwrap(), 3.3);
|
assert_eq!(Value::from(3.3).as_float(), Ok(3.3));
|
||||||
assert_eq!(Value::from(true).as_boolean().unwrap(), true);
|
assert_eq!(Value::from(true).as_boolean(), Ok(true));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Value::from(TupleType::new()).as_tuple().unwrap(),
|
Value::from(TupleType::new()).as_tuple(),
|
||||||
TupleType::new()
|
Ok(TupleType::new())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user