From 6c078c49e5908cbbb44bb514e27fc9e27c288bdc Mon Sep 17 00:00:00 2001 From: Sebastian Schmidt Date: Sun, 14 Apr 2019 16:54:35 +0200 Subject: [PATCH] Refactor operators into an enum (This commit is not formatted properly) Relates to #46 --- src/error/display.rs | 34 +- src/error/mod.rs | 7 +- src/function/builtin.rs | 11 +- src/operator/display.rs | 157 +---- src/operator/mod.rs | 1213 +++++++++++++++------------------------ src/token/mod.rs | 16 +- src/tree/iter.rs | 6 +- src/tree/mod.rs | 86 +-- src/value/display.rs | 2 +- tests/integration.rs | 19 +- 10 files changed, 589 insertions(+), 962 deletions(-) diff --git a/src/error/display.rs b/src/error/display.rs index d0ac2d2..b704b2a 100644 --- a/src/error/display.rs +++ b/src/error/display.rs @@ -18,18 +18,22 @@ impl fmt::Display for EvalexprError { ), ExpectedString { actual } => { write!(f, "Expected a Value::String, but got {:?}.", actual) - }, + } ExpectedInt { actual } => write!(f, "Expected a Value::Int, but got {:?}.", actual), ExpectedFloat { actual } => write!(f, "Expected a Value::Float, but got {:?}.", actual), - ExpectedNumber { actual } => { - write!(f, "Expected a Value::Float or Value::Int, but got {:?}.", actual) - }, - ExpectedNumberOrString { actual } => { - write!(f, "Expected a Value::Number or a Value::String, but got {:?}.", actual) - }, + ExpectedNumber { actual } => write!( + f, + "Expected a Value::Float or Value::Int, but got {:?}.", + actual + ), + ExpectedNumberOrString { actual } => write!( + f, + "Expected a Value::Number or a Value::String, but got {:?}.", + actual + ), ExpectedBoolean { actual } => { write!(f, "Expected a Value::Boolean, but got {:?}.", actual) - }, + } ExpectedTuple { actual } => write!(f, "Expected a Value::Tuple, but got {:?}.", actual), ExpectedEmpty { actual } => write!(f, "Expected a Value::Empty, but got {:?}.", actual), AppendedToLeafNode => write!(f, "Tried to append a node to a leaf node."), @@ -49,7 +53,7 @@ impl fmt::Display for EvalexprError { ), TypeError { expected, actual } => { write!(f, "Expected one of {:?}, but got {:?}.", expected, actual) - }, + } UnmatchedLBrace => write!(f, "Found an unmatched opening parenthesis '('."), UnmatchedRBrace => write!(f, "Found an unmatched closing parenthesis ')'."), UnmatchedPartialToken { first, second } => { @@ -67,7 +71,7 @@ impl fmt::Display for EvalexprError { first ) } - }, + } AdditionError { augend, addend } => write!(f, "Error adding {} + {}", augend, addend), SubtractionError { minuend, @@ -80,11 +84,15 @@ impl fmt::Display for EvalexprError { } => write!(f, "Error multiplying {} * {}", multiplicand, multiplier), DivisionError { dividend, divisor } => { write!(f, "Error dividing {} / {}", dividend, divisor) - }, + } ModulationError { dividend, divisor } => { write!(f, "Error modulating {} % {}", dividend, divisor) - }, - InvalidRegex { regex, message } => write!(f, "Regular expression {:?} is invalid: {:?}", regex, message), + } + InvalidRegex { regex, message } => write!( + f, + "Regular expression {:?} is invalid: {:?}", + regex, message + ), ContextNotManipulable => write!(f, "Cannot manipulate context"), IllegalEscapeSequence(string) => write!(f, "Illegal escape sequence: {}", string), CustomMessage(message) => write!(f, "Error: {}", message), diff --git a/src/error/mod.rs b/src/error/mod.rs index 47d5bb1..9b73b47 100644 --- a/src/error/mod.rs +++ b/src/error/mod.rs @@ -290,7 +290,7 @@ impl EvalexprError { /// Constructs `EvalexprError::InvalidRegex(regex)` pub fn invalid_regex(regex: String, message: String) -> Self { - EvalexprError::InvalidRegex{ regex, message } + EvalexprError::InvalidRegex { regex, message } } } @@ -309,10 +309,7 @@ pub(crate) fn expect_operator_argument_amount( } /// Returns `Ok(())` if the actual and expected parameters are equal, and `Err(Error::WrongFunctionArgumentAmount)` otherwise. -pub fn expect_function_argument_amount( - actual: usize, - expected: usize, -) -> EvalexprResult<()> { +pub fn expect_function_argument_amount(actual: usize, expected: usize) -> EvalexprResult<()> { if actual == expected { Ok(()) } else { diff --git a/src/function/builtin.rs b/src/function/builtin.rs index 717b7db..1ff1256 100644 --- a/src/function/builtin.rs +++ b/src/function/builtin.rs @@ -67,7 +67,6 @@ pub fn builtin_function(identifier: &str) -> Option { )), // string functions - #[cfg(feature = "regex_support")] "str::regex_matches" => Some(Function::new( Some(2), @@ -76,7 +75,10 @@ pub fn builtin_function(identifier: &str) -> Option { let re_str = expect_string(&arguments[1])?; match Regex::new(re_str) { Ok(re) => Ok(Value::Boolean(re.is_match(subject))), - Err(err) => Err(EvalexprError::invalid_regex(re_str.to_string(), format!("{}", err))) + Err(err) => Err(EvalexprError::invalid_regex( + re_str.to_string(), + format!("{}", err), + )), } }), )), @@ -89,7 +91,10 @@ pub fn builtin_function(identifier: &str) -> Option { let repl = expect_string(&arguments[2])?; match Regex::new(re_str) { Ok(re) => Ok(Value::String(re.replace_all(subject, repl).to_string())), - Err(err) => Err(EvalexprError::invalid_regex(re_str.to_string(), format!("{}", err))), + Err(err) => Err(EvalexprError::invalid_regex( + re_str.to_string(), + format!("{}", err), + )), } }), )), diff --git a/src/operator/display.rs b/src/operator/display.rs index ef2ef52..b713b20 100644 --- a/src/operator/display.rs +++ b/src/operator/display.rs @@ -2,140 +2,37 @@ use std::fmt::{Display, Error, Formatter}; use operator::*; -impl Display for RootNode { - fn fmt(&self, _f: &mut Formatter) -> Result<(), Error> { - Ok(()) - } -} - -impl Display for Add { +impl Display for Operator { fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { - write!(f, "+") - } -} + use crate::operator::Operator::*; + match self { + RootNode => Ok(()), + Add => write!(f, "+"), + Sub => write!(f, "-"), + Neg => write!(f, "-"), + Mul => write!(f, "*"), + Div => write!(f, "/"), + Mod => write!(f, "%"), + Exp => write!(f, "^"), -impl Display for Sub { - fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { - write!(f, "-") - } -} + Eq => write!(f, "=="), + Neq => write!(f, "!="), + Gt => write!(f, ">"), + Lt => write!(f, "<"), + Geq => write!(f, ">="), + Leq => write!(f, "<="), + And => write!(f, "&&"), + Or => write!(f, "||"), + Not => write!(f, "!"), -impl Display for Neg { - fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { - write!(f, "-") - } -} + Tuple => write!(f, ", "), + Assign => write!(f, " = "), -impl Display for Mul { - fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { - write!(f, "*") - } -} + Chain => write!(f, "; "), -impl Display for Div { - fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { - write!(f, "/") - } -} - -impl Display for Mod { - fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { - write!(f, "%") - } -} - -impl Display for Exp { - fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { - write!(f, "^") - } -} - -impl Display for Eq { - fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { - write!(f, "==") - } -} - -impl Display for Neq { - fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { - write!(f, "!=") - } -} - -impl Display for Gt { - fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { - write!(f, ">") - } -} - -impl Display for Lt { - fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { - write!(f, "<") - } -} - -impl Display for Geq { - fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { - write!(f, ">=") - } -} - -impl Display for Leq { - fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { - write!(f, "<=") - } -} - -impl Display for And { - fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { - write!(f, "&&") - } -} - -impl Display for Or { - fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { - write!(f, "||") - } -} - -impl Display for Not { - fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { - write!(f, "!") - } -} - -impl Display for Tuple { - fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { - write!(f, ", ") - } -} - -impl Display for Assign { - fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { - write!(f, "; ") - } -} - -impl Display for Chain { - fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { - write!(f, " = ") - } -} - -impl Display for Const { - fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { - write!(f, "{}", self.value) - } -} - -impl Display for VariableIdentifier { - fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { - write!(f, "{}", self.identifier) - } -} - -impl Display for FunctionIdentifier { - fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { - write!(f, "{}", self.identifier) + Const { value } => write!(f, "{}", value), + VariableIdentifier { identifier } => write!(f, "{}", identifier), + FunctionIdentifier { identifier } => write!(f, "{}", identifier), + } } } diff --git a/src/operator/mod.rs b/src/operator/mod.rs index 04b1e45..a86eb53 100644 --- a/src/operator/mod.rs +++ b/src/operator/mod.rs @@ -1,778 +1,497 @@ -use std::fmt::{Debug, Display}; - use function::builtin::builtin_function; use crate::{context::Context, error::*, value::Value}; mod display; -pub trait Operator: Debug + Display { +#[derive(Debug)] +pub enum Operator { + RootNode, + + Add, + Sub, + Neg, + Mul, + Div, + Mod, + Exp, + + Eq, + Neq, + Gt, + Lt, + Geq, + Leq, + And, + Or, + Not, + + Tuple, + Assign, + + Chain, + + Const { value: Value }, + VariableIdentifier { identifier: String }, + FunctionIdentifier { identifier: String }, +} + +impl Operator { + pub(crate) fn value(value: Value) -> Self { + Operator::Const { value } + } + + pub(crate) fn variable_identifier(identifier: String) -> Self { + Operator::VariableIdentifier { identifier } + } + + pub(crate) fn function_identifier(identifier: String) -> Self { + Operator::FunctionIdentifier { identifier } + } + /// Returns the precedence of the operator. /// A high precedence means that the operator has priority to be deeper in the tree. // Make this a const fn once #57563 is resolved - fn precedence(&self) -> i32; + pub(crate) fn precedence(&self) -> i32 { + use crate::operator::Operator::*; + match self { + RootNode => 200, + + Add | Sub => 95, + Neg => 110, + Mul | Div | Mod => 100, + Exp => 120, + + Eq | Neq | Gt | Lt | Geq | Leq => 80, + And => 75, + Or => 70, + Not => 110, + + Tuple => 40, + Assign => 50, + + Chain => 0, + + Const { value: _ } => 200, + VariableIdentifier { identifier: _ } => 200, + FunctionIdentifier { identifier: _ } => 190, + } + } /// Returns true if chains of operators with the same precedence as this one should be evaluated left-to-right, /// and false if they should be evaluated right-to-left. /// Left-to-right chaining has priority if operators with different order but same precedence are chained. // Make this a const fn once #57563 is resolved - fn is_left_to_right(&self) -> bool { - true + pub(crate) fn is_left_to_right(&self) -> bool { + use crate::operator::Operator::*; + match self { + Assign => false, + FunctionIdentifier { identifier: _ } => false, + _ => true, + } } /// True if this operator is a leaf, meaning it accepts no arguments. // Make this a const fn once #57563 is resolved - fn is_leaf(&self) -> bool { + pub(crate) fn is_leaf(&self) -> bool { self.max_argument_amount() == 0 } /// Returns the maximum amount of arguments required by this operator. // Make this a const fn once #57563 is resolved - fn max_argument_amount(&self) -> usize; + pub(crate) fn max_argument_amount(&self) -> usize { + use crate::operator::Operator::*; + match self { + Add | Sub | Mul | Div | Mod | Exp | Eq | Neq | Gt | Lt | Geq | Leq | And | Or + | Tuple | Assign | Chain => 2, + Not | Neg | RootNode => 1, + Const { value: _ } => 0, + VariableIdentifier { identifier: _ } => 0, + FunctionIdentifier { identifier: _ } => 1, + } + } /// Evaluates the operator with the given arguments and context. - fn eval(&self, arguments: &[Value], context: &dyn Context) -> EvalexprResult; + pub(crate) fn eval(&self, arguments: &[Value], context: &dyn Context) -> EvalexprResult { + use crate::operator::Operator::*; + match self { + RootNode => { + if let Some(first) = arguments.first() { + Ok(first.clone()) + } else { + Ok(Value::Empty) + } + } + Add => { + expect_operator_argument_amount(arguments.len(), 2)?; + expect_number_or_string(&arguments[0])?; + expect_number_or_string(&arguments[1])?; + + if let (Ok(a), Ok(b)) = (arguments[0].as_string(), arguments[1].as_string()) { + let mut result = String::with_capacity(a.len() + b.len()); + result.push_str(&a); + result.push_str(&b); + Ok(Value::String(result)) + } else if let (Ok(a), Ok(b)) = (arguments[0].as_int(), arguments[1].as_int()) { + let result = a.checked_add(b); + if let Some(result) = result { + Ok(Value::Int(result)) + } else { + Err(EvalexprError::addition_error( + arguments[0].clone(), + arguments[1].clone(), + )) + } + } else { + Ok(Value::Float( + arguments[0].as_number().unwrap() + arguments[1].as_number().unwrap(), + )) + } + } + Sub => { + expect_operator_argument_amount(arguments.len(), 2)?; + expect_number(&arguments[0])?; + expect_number(&arguments[1])?; + + if let (Ok(a), Ok(b)) = (arguments[0].as_int(), arguments[1].as_int()) { + let result = a.checked_sub(b); + if let Some(result) = result { + Ok(Value::Int(result)) + } else { + Err(EvalexprError::subtraction_error( + arguments[0].clone(), + arguments[1].clone(), + )) + } + } else { + Ok(Value::Float( + arguments[0].as_number().unwrap() - arguments[1].as_number().unwrap(), + )) + } + } + Neg => { + expect_operator_argument_amount(arguments.len(), 1)?; + expect_number(&arguments[0])?; + + if let Ok(a) = arguments[0].as_int() { + let result = a.checked_neg(); + if let Some(result) = result { + Ok(Value::Int(result)) + } else { + Err(EvalexprError::negation_error(arguments[0].clone())) + } + } else { + Ok(Value::Float(-arguments[0].as_number().unwrap())) + } + } + Mul => { + expect_operator_argument_amount(arguments.len(), 2)?; + expect_number(&arguments[0])?; + expect_number(&arguments[1])?; + + if let (Ok(a), Ok(b)) = (arguments[0].as_int(), arguments[1].as_int()) { + let result = a.checked_mul(b); + if let Some(result) = result { + Ok(Value::Int(result)) + } else { + Err(EvalexprError::multiplication_error( + arguments[0].clone(), + arguments[1].clone(), + )) + } + } else { + Ok(Value::Float( + arguments[0].as_number().unwrap() * arguments[1].as_number().unwrap(), + )) + } + } + Div => { + expect_operator_argument_amount(arguments.len(), 2)?; + expect_number(&arguments[0])?; + expect_number(&arguments[1])?; + + if let (Ok(a), Ok(b)) = (arguments[0].as_int(), arguments[1].as_int()) { + let result = a.checked_div(b); + if let Some(result) = result { + Ok(Value::Int(result)) + } else { + Err(EvalexprError::division_error( + arguments[0].clone(), + arguments[1].clone(), + )) + } + } else { + Ok(Value::Float( + arguments[0].as_number().unwrap() / arguments[1].as_number().unwrap(), + )) + } + } + Mod => { + expect_operator_argument_amount(arguments.len(), 2)?; + expect_number(&arguments[0])?; + expect_number(&arguments[1])?; + + if let (Ok(a), Ok(b)) = (arguments[0].as_int(), arguments[1].as_int()) { + let result = a.checked_rem(b); + if let Some(result) = result { + Ok(Value::Int(result)) + } else { + Err(EvalexprError::modulation_error( + arguments[0].clone(), + arguments[1].clone(), + )) + } + } else { + Ok(Value::Float( + arguments[0].as_number().unwrap() % arguments[1].as_number().unwrap(), + )) + } + } + Exp => { + expect_operator_argument_amount(arguments.len(), 2)?; + expect_number(&arguments[0])?; + expect_number(&arguments[1])?; + + Ok(Value::Float( + arguments[0] + .as_number() + .unwrap() + .powf(arguments[1].as_number().unwrap()), + )) + } + Eq => { + expect_operator_argument_amount(arguments.len(), 2)?; + + if arguments[0] == arguments[1] { + Ok(Value::Boolean(true)) + } else { + Ok(Value::Boolean(false)) + } + } + Neq => { + expect_operator_argument_amount(arguments.len(), 2)?; + + if arguments[0] != arguments[1] { + Ok(Value::Boolean(true)) + } else { + Ok(Value::Boolean(false)) + } + } + Gt => { + expect_operator_argument_amount(arguments.len(), 2)?; + expect_number_or_string(&arguments[0])?; + expect_number_or_string(&arguments[1])?; + + if let (Ok(a), Ok(b)) = (arguments[0].as_string(), arguments[1].as_string()) { + if a > b { + Ok(Value::Boolean(true)) + } else { + Ok(Value::Boolean(false)) + } + } else if let (Ok(a), Ok(b)) = (arguments[0].as_int(), arguments[1].as_int()) { + if a > b { + Ok(Value::Boolean(true)) + } else { + Ok(Value::Boolean(false)) + } + } else { + if arguments[0].as_number().unwrap() > arguments[1].as_number().unwrap() { + Ok(Value::Boolean(true)) + } else { + Ok(Value::Boolean(false)) + } + } + } + Lt => { + expect_operator_argument_amount(arguments.len(), 2)?; + expect_number_or_string(&arguments[0])?; + expect_number_or_string(&arguments[1])?; + + if let (Ok(a), Ok(b)) = (arguments[0].as_string(), arguments[1].as_string()) { + if a < b { + Ok(Value::Boolean(true)) + } else { + Ok(Value::Boolean(false)) + } + } else if let (Ok(a), Ok(b)) = (arguments[0].as_int(), arguments[1].as_int()) { + if a < b { + Ok(Value::Boolean(true)) + } else { + Ok(Value::Boolean(false)) + } + } else { + if arguments[0].as_number().unwrap() < arguments[1].as_number().unwrap() { + Ok(Value::Boolean(true)) + } else { + Ok(Value::Boolean(false)) + } + } + } + Geq => { + expect_operator_argument_amount(arguments.len(), 2)?; + expect_number_or_string(&arguments[0])?; + expect_number_or_string(&arguments[1])?; + + if let (Ok(a), Ok(b)) = (arguments[0].as_string(), arguments[1].as_string()) { + if a >= b { + Ok(Value::Boolean(true)) + } else { + Ok(Value::Boolean(false)) + } + } else if let (Ok(a), Ok(b)) = (arguments[0].as_int(), arguments[1].as_int()) { + if a >= b { + Ok(Value::Boolean(true)) + } else { + Ok(Value::Boolean(false)) + } + } else { + if arguments[0].as_number().unwrap() >= arguments[1].as_number().unwrap() { + Ok(Value::Boolean(true)) + } else { + Ok(Value::Boolean(false)) + } + } + } + Leq => { + expect_operator_argument_amount(arguments.len(), 2)?; + expect_number_or_string(&arguments[0])?; + expect_number_or_string(&arguments[1])?; + + if let (Ok(a), Ok(b)) = (arguments[0].as_string(), arguments[1].as_string()) { + if a <= b { + Ok(Value::Boolean(true)) + } else { + Ok(Value::Boolean(false)) + } + } else if let (Ok(a), Ok(b)) = (arguments[0].as_int(), arguments[1].as_int()) { + if a <= b { + Ok(Value::Boolean(true)) + } else { + Ok(Value::Boolean(false)) + } + } else { + if arguments[0].as_number().unwrap() <= arguments[1].as_number().unwrap() { + Ok(Value::Boolean(true)) + } else { + Ok(Value::Boolean(false)) + } + } + } + And => { + expect_operator_argument_amount(arguments.len(), 2)?; + let a = expect_boolean(&arguments[0])?; + let b = expect_boolean(&arguments[1])?; + + if a && b { + Ok(Value::Boolean(true)) + } else { + Ok(Value::Boolean(false)) + } + } + Or => { + expect_operator_argument_amount(arguments.len(), 2)?; + let a = expect_boolean(&arguments[0])?; + let b = expect_boolean(&arguments[1])?; + + if a || b { + Ok(Value::Boolean(true)) + } else { + Ok(Value::Boolean(false)) + } + } + Not => { + expect_operator_argument_amount(arguments.len(), 1)?; + let a = expect_boolean(&arguments[0])?; + + if !a { + Ok(Value::Boolean(true)) + } else { + Ok(Value::Boolean(false)) + } + } + Tuple => { + expect_operator_argument_amount(arguments.len(), 2)?; + if let Value::Tuple(tuple) = &arguments[0] { + let mut tuple = tuple.clone(); + if let Value::Tuple(tuple2) = &arguments[1] { + tuple.extend(tuple2.iter().cloned()); + } else { + tuple.push(arguments[1].clone()); + } + Ok(Value::from(tuple)) + } else { + if let Value::Tuple(tuple) = &arguments[1] { + let mut tuple = tuple.clone(); + tuple.insert(0, arguments[0].clone()); + Ok(Value::from(tuple)) + } else { + Ok(Value::from(vec![ + arguments[0].clone(), + arguments[1].clone(), + ])) + } + } + } + Assign => Err(EvalexprError::ContextNotManipulable), + Chain => { + if arguments.is_empty() { + return Err(EvalexprError::wrong_operator_argument_amount(0, 1)); + } + + Ok(arguments.get(1).cloned().unwrap_or(Value::Empty)) + } + Const { value } => { + expect_operator_argument_amount(arguments.len(), 0)?; + + Ok(value.clone()) + } + VariableIdentifier { identifier } => { + if let Some(value) = context.get_value(&identifier).cloned() { + Ok(value) + } else { + Err(EvalexprError::VariableIdentifierNotFound( + identifier.clone(), + )) + } + } + FunctionIdentifier { identifier } => { + expect_operator_argument_amount(arguments.len(), 1)?; + + let arguments = if let Value::Tuple(arguments) = &arguments[0] { + arguments + } else { + arguments + }; + + if let Some(function) = context.get_function(&identifier) { + function.call(arguments) + } else if let Some(builtin_function) = builtin_function(&identifier) { + builtin_function.call(arguments) + } else { + Err(EvalexprError::FunctionIdentifierNotFound( + identifier.clone(), + )) + } + } + } + } /// Evaluates the operator with the given arguments and mutable context. - fn eval_mut(&self, arguments: &[Value], context: &mut dyn Context) -> EvalexprResult { - self.eval(arguments, context) - } + pub(crate) fn eval_mut( + &self, + arguments: &[Value], + context: &mut dyn Context, + ) -> EvalexprResult { + use crate::operator::Operator::*; + match self { + Assign => { + expect_operator_argument_amount(arguments.len(), 2)?; + let target = expect_string(&arguments[0])?; + context.set_value(target.into(), arguments[1].clone())?; - /// Returns an identifier if this operator is a function or variable identifier, or `None` otherwise. - fn identifier(&self) -> Option<&str> { - None - } - - /// Returns a variable identifier if this operator is a variable identifier, or `None` otherwise. - fn variable_identifier(&self) -> Option<&str> { - None - } - - /// Returns a function identifier if this operator is a function identifier, or `None` otherwise. - fn function_identifier(&self) -> Option<&str> { - None - } -} - -#[derive(Debug)] -pub struct RootNode; - -#[derive(Debug)] -pub struct Add; -#[derive(Debug)] -pub struct Sub; -#[derive(Debug)] -pub struct Neg; -#[derive(Debug)] -pub struct Mul; -#[derive(Debug)] -pub struct Div; -#[derive(Debug)] -pub struct Mod; -#[derive(Debug)] -pub struct Exp; - -#[derive(Debug)] -pub struct Eq; -#[derive(Debug)] -pub struct Neq; -#[derive(Debug)] -pub struct Gt; -#[derive(Debug)] -pub struct Lt; -#[derive(Debug)] -pub struct Geq; -#[derive(Debug)] -pub struct Leq; -#[derive(Debug)] -pub struct And; -#[derive(Debug)] -pub struct Or; -#[derive(Debug)] -pub struct Not; - -#[derive(Debug)] -pub struct Tuple; -#[derive(Debug)] -pub struct Assign; - -#[derive(Debug)] -pub struct Chain; - -#[derive(Debug)] -pub struct Const { - value: Value, -} - -impl Const { - pub fn new(value: Value) -> Self { - Self { value } - } -} - -#[derive(Debug)] -pub struct VariableIdentifier { - identifier: String, -} - -impl VariableIdentifier { - pub fn new(identifier: String) -> Self { - Self { identifier } - } -} - -#[derive(Debug)] -pub struct FunctionIdentifier { - identifier: String, -} - -impl FunctionIdentifier { - pub fn new(identifier: String) -> Self { - Self { identifier } - } -} - -impl Operator for RootNode { - fn precedence(&self) -> i32 { - 200 - } - - fn max_argument_amount(&self) -> usize { - 1 - } - - fn eval(&self, arguments: &[Value], _context: &Context) -> EvalexprResult { - if let Some(first) = arguments.first() { - Ok(first.clone()) - } else { - Ok(Value::Empty) + Ok(Value::Empty) + } + _ => self.eval(arguments, context), } } } - -impl Operator for Add { - fn precedence(&self) -> i32 { - 95 - } - - fn max_argument_amount(&self) -> usize { - 2 - } - - fn eval(&self, arguments: &[Value], _context: &Context) -> EvalexprResult { - expect_operator_argument_amount(arguments.len(), 2)?; - expect_number_or_string(&arguments[0])?; - expect_number_or_string(&arguments[1])?; - - if let (Ok(a), Ok(b)) = (arguments[0].as_string(), arguments[1].as_string()) { - let mut result = String::with_capacity(a.len() + b.len()); - result.push_str(&a); - result.push_str(&b); - Ok(Value::String(result)) - } else if let (Ok(a), Ok(b)) = (arguments[0].as_int(), arguments[1].as_int()) { - let result = a.checked_add(b); - if let Some(result) = result { - Ok(Value::Int(result)) - } else { - Err(EvalexprError::addition_error( - arguments[0].clone(), - arguments[1].clone(), - )) - } - } else { - Ok(Value::Float( - arguments[0].as_number().unwrap() + arguments[1].as_number().unwrap(), - )) - } - } -} - -impl Operator for Sub { - fn precedence(&self) -> i32 { - 95 - } - - fn max_argument_amount(&self) -> usize { - 2 - } - - fn eval(&self, arguments: &[Value], _context: &Context) -> EvalexprResult { - expect_operator_argument_amount(arguments.len(), 2)?; - expect_number(&arguments[0])?; - expect_number(&arguments[1])?; - - if let (Ok(a), Ok(b)) = (arguments[0].as_int(), arguments[1].as_int()) { - let result = a.checked_sub(b); - if let Some(result) = result { - Ok(Value::Int(result)) - } else { - Err(EvalexprError::subtraction_error( - arguments[0].clone(), - arguments[1].clone(), - )) - } - } else { - Ok(Value::Float( - arguments[0].as_number().unwrap() - arguments[1].as_number().unwrap(), - )) - } - } -} - -impl Operator for Neg { - fn precedence(&self) -> i32 { - 110 - } - - fn max_argument_amount(&self) -> usize { - 1 - } - - fn eval(&self, arguments: &[Value], _context: &Context) -> EvalexprResult { - expect_operator_argument_amount(arguments.len(), 1)?; - expect_number(&arguments[0])?; - - if let Ok(a) = arguments[0].as_int() { - let result = a.checked_neg(); - if let Some(result) = result { - Ok(Value::Int(result)) - } else { - Err(EvalexprError::negation_error(arguments[0].clone())) - } - } else { - Ok(Value::Float(-arguments[0].as_number().unwrap())) - } - } -} - -impl Operator for Mul { - fn precedence(&self) -> i32 { - 100 - } - - fn max_argument_amount(&self) -> usize { - 2 - } - - fn eval(&self, arguments: &[Value], _context: &Context) -> EvalexprResult { - expect_operator_argument_amount(arguments.len(), 2)?; - expect_number(&arguments[0])?; - expect_number(&arguments[1])?; - - if let (Ok(a), Ok(b)) = (arguments[0].as_int(), arguments[1].as_int()) { - let result = a.checked_mul(b); - if let Some(result) = result { - Ok(Value::Int(result)) - } else { - Err(EvalexprError::multiplication_error( - arguments[0].clone(), - arguments[1].clone(), - )) - } - } else { - Ok(Value::Float( - arguments[0].as_number().unwrap() * arguments[1].as_number().unwrap(), - )) - } - } -} - -impl Operator for Div { - fn precedence(&self) -> i32 { - 100 - } - - fn max_argument_amount(&self) -> usize { - 2 - } - - fn eval(&self, arguments: &[Value], _context: &Context) -> EvalexprResult { - expect_operator_argument_amount(arguments.len(), 2)?; - expect_number(&arguments[0])?; - expect_number(&arguments[1])?; - - if let (Ok(a), Ok(b)) = (arguments[0].as_int(), arguments[1].as_int()) { - let result = a.checked_div(b); - if let Some(result) = result { - Ok(Value::Int(result)) - } else { - Err(EvalexprError::division_error( - arguments[0].clone(), - arguments[1].clone(), - )) - } - } else { - Ok(Value::Float( - arguments[0].as_number().unwrap() / arguments[1].as_number().unwrap(), - )) - } - } -} - -impl Operator for Mod { - fn precedence(&self) -> i32 { - 100 - } - - fn max_argument_amount(&self) -> usize { - 2 - } - - fn eval(&self, arguments: &[Value], _context: &Context) -> EvalexprResult { - expect_operator_argument_amount(arguments.len(), 2)?; - expect_number(&arguments[0])?; - expect_number(&arguments[1])?; - - if let (Ok(a), Ok(b)) = (arguments[0].as_int(), arguments[1].as_int()) { - let result = a.checked_rem(b); - if let Some(result) = result { - Ok(Value::Int(result)) - } else { - Err(EvalexprError::modulation_error( - arguments[0].clone(), - arguments[1].clone(), - )) - } - } else { - Ok(Value::Float( - arguments[0].as_number().unwrap() % arguments[1].as_number().unwrap(), - )) - } - } -} - -impl Operator for Exp { - fn precedence(&self) -> i32 { - 120 - } - - fn max_argument_amount(&self) -> usize { - 2 - } - - fn eval(&self, arguments: &[Value], _context: &Context) -> EvalexprResult { - expect_operator_argument_amount(arguments.len(), 2)?; - expect_number(&arguments[0])?; - expect_number(&arguments[1])?; - - Ok(Value::Float( - arguments[0] - .as_number() - .unwrap() - .powf(arguments[1].as_number().unwrap()), - )) - } -} - -impl Operator for Eq { - fn precedence(&self) -> i32 { - 80 - } - - fn max_argument_amount(&self) -> usize { - 2 - } - - fn eval(&self, arguments: &[Value], _context: &Context) -> EvalexprResult { - expect_operator_argument_amount(arguments.len(), 2)?; - - if arguments[0] == arguments[1] { - Ok(Value::Boolean(true)) - } else { - Ok(Value::Boolean(false)) - } - } -} - -impl Operator for Neq { - fn precedence(&self) -> i32 { - 80 - } - - fn max_argument_amount(&self) -> usize { - 2 - } - - fn eval(&self, arguments: &[Value], _context: &Context) -> EvalexprResult { - expect_operator_argument_amount(arguments.len(), 2)?; - - if arguments[0] != arguments[1] { - Ok(Value::Boolean(true)) - } else { - Ok(Value::Boolean(false)) - } - } -} - -impl Operator for Gt { - fn precedence(&self) -> i32 { - 80 - } - - fn max_argument_amount(&self) -> usize { - 2 - } - - fn eval(&self, arguments: &[Value], _context: &Context) -> EvalexprResult { - expect_operator_argument_amount(arguments.len(), 2)?; - expect_number_or_string(&arguments[0])?; - expect_number_or_string(&arguments[1])?; - - if let (Ok(a), Ok(b)) = (arguments[0].as_string(), arguments[1].as_string()) { - if a > b { - Ok(Value::Boolean(true)) - } else { - Ok(Value::Boolean(false)) - } - } else if let (Ok(a), Ok(b)) = (arguments[0].as_int(), arguments[1].as_int()) { - if a > b { - Ok(Value::Boolean(true)) - } else { - Ok(Value::Boolean(false)) - } - } else { - if arguments[0].as_number().unwrap() > arguments[1].as_number().unwrap() { - Ok(Value::Boolean(true)) - } else { - Ok(Value::Boolean(false)) - } - } - } -} - -impl Operator for Lt { - fn precedence(&self) -> i32 { - 80 - } - - fn max_argument_amount(&self) -> usize { - 2 - } - - fn eval(&self, arguments: &[Value], _context: &Context) -> EvalexprResult { - expect_operator_argument_amount(arguments.len(), 2)?; - expect_number_or_string(&arguments[0])?; - expect_number_or_string(&arguments[1])?; - - if let (Ok(a), Ok(b)) = (arguments[0].as_string(), arguments[1].as_string()) { - if a < b { - Ok(Value::Boolean(true)) - } else { - Ok(Value::Boolean(false)) - } - } else if let (Ok(a), Ok(b)) = (arguments[0].as_int(), arguments[1].as_int()) { - if a < b { - Ok(Value::Boolean(true)) - } else { - Ok(Value::Boolean(false)) - } - } else { - if arguments[0].as_number().unwrap() < arguments[1].as_number().unwrap() { - Ok(Value::Boolean(true)) - } else { - Ok(Value::Boolean(false)) - } - } - } -} - -impl Operator for Geq { - fn precedence(&self) -> i32 { - 80 - } - - fn max_argument_amount(&self) -> usize { - 2 - } - - fn eval(&self, arguments: &[Value], _context: &Context) -> EvalexprResult { - expect_operator_argument_amount(arguments.len(), 2)?; - expect_number_or_string(&arguments[0])?; - expect_number_or_string(&arguments[1])?; - - if let (Ok(a), Ok(b)) = (arguments[0].as_string(), arguments[1].as_string()) { - if a >= b { - Ok(Value::Boolean(true)) - } else { - Ok(Value::Boolean(false)) - } - } else if let (Ok(a), Ok(b)) = (arguments[0].as_int(), arguments[1].as_int()) { - if a >= b { - Ok(Value::Boolean(true)) - } else { - Ok(Value::Boolean(false)) - } - } else { - if arguments[0].as_number().unwrap() >= arguments[1].as_number().unwrap() { - Ok(Value::Boolean(true)) - } else { - Ok(Value::Boolean(false)) - } - } - } -} - -impl Operator for Leq { - fn precedence(&self) -> i32 { - 80 - } - - fn max_argument_amount(&self) -> usize { - 2 - } - - fn eval(&self, arguments: &[Value], _context: &Context) -> EvalexprResult { - expect_operator_argument_amount(arguments.len(), 2)?; - expect_number_or_string(&arguments[0])?; - expect_number_or_string(&arguments[1])?; - - if let (Ok(a), Ok(b)) = (arguments[0].as_string(), arguments[1].as_string()) { - if a <= b { - Ok(Value::Boolean(true)) - } else { - Ok(Value::Boolean(false)) - } - } else if let (Ok(a), Ok(b)) = (arguments[0].as_int(), arguments[1].as_int()) { - if a <= b { - Ok(Value::Boolean(true)) - } else { - Ok(Value::Boolean(false)) - } - } else { - if arguments[0].as_number().unwrap() <= arguments[1].as_number().unwrap() { - Ok(Value::Boolean(true)) - } else { - Ok(Value::Boolean(false)) - } - } - } -} - -impl Operator for And { - fn precedence(&self) -> i32 { - 75 - } - - fn max_argument_amount(&self) -> usize { - 2 - } - - fn eval(&self, arguments: &[Value], _context: &Context) -> EvalexprResult { - expect_operator_argument_amount(arguments.len(), 2)?; - let a = expect_boolean(&arguments[0])?; - let b = expect_boolean(&arguments[1])?; - - if a && b { - Ok(Value::Boolean(true)) - } else { - Ok(Value::Boolean(false)) - } - } -} - -impl Operator for Or { - fn precedence(&self) -> i32 { - 70 - } - - fn max_argument_amount(&self) -> usize { - 2 - } - - fn eval(&self, arguments: &[Value], _context: &Context) -> EvalexprResult { - expect_operator_argument_amount(arguments.len(), 2)?; - let a = expect_boolean(&arguments[0])?; - let b = expect_boolean(&arguments[1])?; - - if a || b { - Ok(Value::Boolean(true)) - } else { - Ok(Value::Boolean(false)) - } - } -} - -impl Operator for Not { - fn precedence(&self) -> i32 { - 110 - } - - fn max_argument_amount(&self) -> usize { - 1 - } - - fn eval(&self, arguments: &[Value], _context: &Context) -> EvalexprResult { - expect_operator_argument_amount(arguments.len(), 1)?; - let a = expect_boolean(&arguments[0])?; - - if !a { - Ok(Value::Boolean(true)) - } else { - Ok(Value::Boolean(false)) - } - } -} - -impl Operator for Tuple { - fn precedence(&self) -> i32 { - 40 - } - - fn max_argument_amount(&self) -> usize { - 2 - } - - fn eval(&self, arguments: &[Value], _context: &Context) -> EvalexprResult { - expect_operator_argument_amount(arguments.len(), 2)?; - if let Value::Tuple(tuple) = &arguments[0] { - let mut tuple = tuple.clone(); - if let Value::Tuple(tuple2) = &arguments[1] { - tuple.extend(tuple2.iter().cloned()); - } else { - tuple.push(arguments[1].clone()); - } - Ok(Value::from(tuple)) - } else { - if let Value::Tuple(tuple) = &arguments[1] { - let mut tuple = tuple.clone(); - tuple.insert(0, arguments[0].clone()); - Ok(Value::from(tuple)) - } else { - Ok(Value::from(vec![ - arguments[0].clone(), - arguments[1].clone(), - ])) - } - } - } -} - -impl Operator for Assign { - fn precedence(&self) -> i32 { - 50 - } - - fn is_left_to_right(&self) -> bool { - false - } - - fn max_argument_amount(&self) -> usize { - 2 - } - - fn eval(&self, _arguments: &[Value], _context: &Context) -> EvalexprResult { - Err(EvalexprError::ContextNotManipulable) - } - - fn eval_mut(&self, arguments: &[Value], context: &mut Context) -> EvalexprResult { - expect_operator_argument_amount(arguments.len(), 2)?; - let target = expect_string(&arguments[0])?; - context.set_value(target.into(), arguments[1].clone())?; - - Ok(Value::Empty) - } -} - -impl Operator for Chain { - fn precedence(&self) -> i32 { - 0 - } - - fn max_argument_amount(&self) -> usize { - 2 - } - - fn eval(&self, arguments: &[Value], _context: &Context) -> Result { - if arguments.is_empty() { - return Err(EvalexprError::wrong_operator_argument_amount(0, 1)); - } - - Ok(arguments.get(1).cloned().unwrap_or(Value::Empty)) - } -} - -impl Operator for Const { - fn precedence(&self) -> i32 { - 200 - } - - fn max_argument_amount(&self) -> usize { - 0 - } - - fn eval(&self, arguments: &[Value], _context: &Context) -> EvalexprResult { - expect_operator_argument_amount(arguments.len(), 0)?; - - Ok(self.value.clone()) - } -} - -impl Operator for VariableIdentifier { - fn precedence(&self) -> i32 { - 200 - } - - fn max_argument_amount(&self) -> usize { - 0 - } - - fn eval(&self, _arguments: &[Value], context: &Context) -> EvalexprResult { - if let Some(value) = context.get_value(&self.identifier).cloned() { - Ok(value) - } else { - Err(EvalexprError::VariableIdentifierNotFound( - self.identifier.clone(), - )) - } - } - - fn identifier(&self) -> Option<&str> { - Some(&self.identifier) - } - - fn variable_identifier(&self) -> Option<&str> { - Some(&self.identifier) - } -} - -impl Operator for FunctionIdentifier { - fn precedence(&self) -> i32 { - 190 - } - - fn is_left_to_right(&self) -> bool { - false - } - - fn max_argument_amount(&self) -> usize { - 1 - } - - fn eval(&self, arguments: &[Value], context: &Context) -> EvalexprResult { - expect_operator_argument_amount(arguments.len(), 1)?; - - let arguments = if let Value::Tuple(arguments) = &arguments[0] { - arguments - } else { - arguments - }; - - if let Some(function) = context.get_function(&self.identifier) { - function.call(arguments) - } else if let Some(builtin_function) = builtin_function(&self.identifier) { - builtin_function.call(arguments) - } else { - Err(EvalexprError::FunctionIdentifierNotFound( - self.identifier.clone(), - )) - } - } - - fn identifier(&self) -> Option<&str> { - Some(&self.identifier) - } - - fn function_identifier(&self) -> Option<&str> { - Some(&self.identifier) - } -} diff --git a/src/token/mod.rs b/src/token/mod.rs index d3a3fe4..0b77c06 100644 --- a/src/token/mod.rs +++ b/src/token/mod.rs @@ -83,7 +83,7 @@ fn char_to_partial_token(c: char) -> PartialToken { } else { PartialToken::Literal(c.to_string()) } - }, + } } } @@ -233,7 +233,7 @@ fn partial_tokens_to_tokens(mut tokens: &[PartialToken]) -> EvalexprResult { cutoff = 1; Some(token) - }, + } PartialToken::Literal(literal) => { cutoff = 1; if let Ok(number) = literal.parse::() { @@ -245,38 +245,38 @@ fn partial_tokens_to_tokens(mut tokens: &[PartialToken]) -> EvalexprResult { cutoff = 1; None - }, + } PartialToken::Eq => match second { Some(PartialToken::Eq) => Some(Token::Eq), _ => { cutoff = 1; Some(Token::Assign) - }, + } }, PartialToken::ExclamationMark => match second { Some(PartialToken::Eq) => Some(Token::Eq), _ => { cutoff = 1; Some(Token::Not) - }, + } }, PartialToken::Gt => match second { Some(PartialToken::Eq) => Some(Token::Geq), _ => { cutoff = 1; Some(Token::Gt) - }, + } }, PartialToken::Lt => match second { Some(PartialToken::Eq) => Some(Token::Leq), _ => { cutoff = 1; Some(Token::Lt) - }, + } }, PartialToken::Ampersand => match second { Some(PartialToken::Ampersand) => Some(Token::And), diff --git a/src/tree/iter.rs b/src/tree/iter.rs index 672261f..f2481e1 100644 --- a/src/tree/iter.rs +++ b/src/tree/iter.rs @@ -1,5 +1,5 @@ -use Node; use std::slice::Iter; +use Node; /// An iterator that traverses an operator tree in pre-order. pub struct NodeIter<'a> { @@ -47,7 +47,7 @@ impl<'a> Iterator for NodeIter<'a> { impl Node { /// Returns an iterator over all nodes in this tree. - pub fn iter(&self) -> impl Iterator { + pub fn iter(&self) -> impl Iterator { NodeIter::new(self) } -} \ No newline at end of file +} diff --git a/src/tree/mod.rs b/src/tree/mod.rs index fb65b25..0d728d2 100644 --- a/src/tree/mod.rs +++ b/src/tree/mod.rs @@ -35,19 +35,19 @@ mod iter; #[derive(Debug)] pub struct Node { children: Vec, - operator: Box, + operator: Operator, } impl Node { - fn new(operator: T) -> Self { + fn new(operator: Operator) -> Self { Self { children: Vec::new(), - operator: Box::new(operator), + operator, } } fn root_node() -> Self { - Self::new(RootNode) + Self::new(Operator::RootNode) } /// Returns an iterator over all identifiers in this expression. @@ -67,7 +67,11 @@ impl Node { /// assert_eq!(iter.next(), None); /// ``` pub fn iter_identifiers(&self) -> impl Iterator { - self.iter().filter_map(|node| node.operator.identifier()) + self.iter().filter_map(|node| match node.operator() { + Operator::VariableIdentifier { identifier } + | Operator::FunctionIdentifier { identifier } => Some(identifier.as_str()), + _ => None, + }) } /// Returns an iterator over all variable identifiers in this expression. @@ -86,7 +90,10 @@ impl Node { /// assert_eq!(iter.next(), None); /// ``` pub fn iter_variable_identifiers(&self) -> impl Iterator { - self.iter().filter_map(|node| node.operator.variable_identifier()) + self.iter().filter_map(|node| match node.operator() { + Operator::VariableIdentifier { identifier } => Some(identifier.as_str()), + _ => None, + }) } /// Returns an iterator over all function identifiers in this expression. @@ -103,7 +110,10 @@ impl Node { /// assert_eq!(iter.next(), None); /// ``` pub fn iter_function_identifiers(&self) -> impl Iterator { - self.iter().filter_map(|node| node.operator.function_identifier()) + self.iter().filter_map(|node| match node.operator() { + Operator::FunctionIdentifier { identifier } => Some(identifier.as_str()), + _ => None, + }) } /// Evaluates the operator tree rooted at this node with the given context. @@ -347,7 +357,7 @@ impl Node { &self.children } - fn operator(&self) -> &Box { + fn operator(&self) -> &Operator { &self.operator } @@ -404,60 +414,60 @@ pub(crate) fn tokens_to_operator_tree(tokens: Vec) -> EvalexprResult Some(Node::new(Add)), + Token::Plus => Some(Node::new(Operator::Add)), Token::Minus => { if last_token_is_rightsided_value { - Some(Node::new(Sub)) + Some(Node::new(Operator::Sub)) } else { - Some(Node::new(Neg)) + Some(Node::new(Operator::Neg)) } - }, - Token::Star => Some(Node::new(Mul)), - Token::Slash => Some(Node::new(Div)), - Token::Percent => Some(Node::new(Mod)), - Token::Hat => Some(Node::new(Exp)), + } + Token::Star => Some(Node::new(Operator::Mul)), + Token::Slash => Some(Node::new(Operator::Div)), + Token::Percent => Some(Node::new(Operator::Mod)), + Token::Hat => Some(Node::new(Operator::Exp)), - Token::Eq => Some(Node::new(Eq)), - Token::Neq => Some(Node::new(Neq)), - Token::Gt => Some(Node::new(Gt)), - Token::Lt => Some(Node::new(Lt)), - Token::Geq => Some(Node::new(Geq)), - Token::Leq => Some(Node::new(Leq)), - Token::And => Some(Node::new(And)), - Token::Or => Some(Node::new(Or)), - Token::Not => Some(Node::new(Not)), + Token::Eq => Some(Node::new(Operator::Eq)), + Token::Neq => Some(Node::new(Operator::Neq)), + Token::Gt => Some(Node::new(Operator::Gt)), + Token::Lt => Some(Node::new(Operator::Lt)), + Token::Geq => Some(Node::new(Operator::Geq)), + Token::Leq => Some(Node::new(Operator::Leq)), + Token::And => Some(Node::new(Operator::And)), + Token::Or => Some(Node::new(Operator::Or)), + Token::Not => Some(Node::new(Operator::Not)), Token::LBrace => { root.push(Node::root_node()); None - }, + } Token::RBrace => { if root.len() < 2 { return Err(EvalexprError::UnmatchedRBrace); } else { root.pop() } - }, + } - Token::Comma => Some(Node::new(Tuple)), - Token::Assign => Some(Node::new(Assign)), - Token::Semicolon => Some(Node::new(Chain)), + Token::Comma => Some(Node::new(Operator::Tuple)), + Token::Assign => Some(Node::new(Operator::Assign)), + Token::Semicolon => Some(Node::new(Operator::Chain)), Token::Identifier(identifier) => { - let mut result = Some(Node::new(VariableIdentifier::new(identifier.clone()))); + let mut result = Some(Node::new(Operator::variable_identifier(identifier.clone()))); if let Some(next) = next { if next == &Token::Assign { - result = Some(Node::new(Const::new(identifier.clone().into()))); + result = Some(Node::new(Operator::value(identifier.clone().into()))); } else if next.is_leftsided_value() { - result = Some(Node::new(FunctionIdentifier::new(identifier))); + result = Some(Node::new(Operator::function_identifier(identifier))); } } result - }, - Token::Float(float) => Some(Node::new(Const::new(Value::Float(float)))), - Token::Int(int) => Some(Node::new(Const::new(Value::Int(int)))), - Token::Boolean(boolean) => Some(Node::new(Const::new(Value::Boolean(boolean)))), - Token::String(string) => Some(Node::new(Const::new(Value::String(string)))), + } + Token::Float(float) => Some(Node::new(Operator::value(Value::Float(float)))), + Token::Int(int) => Some(Node::new(Operator::value(Value::Int(int)))), + Token::Boolean(boolean) => Some(Node::new(Operator::value(Value::Boolean(boolean)))), + Token::String(string) => Some(Node::new(Operator::value(Value::String(string)))), }; if let Some(node) = node { diff --git a/src/value/display.rs b/src/value/display.rs index 4e98d39..63991e4 100644 --- a/src/value/display.rs +++ b/src/value/display.rs @@ -21,7 +21,7 @@ impl Display for Value { value.fmt(f)?; } write!(f, ")") - }, + } Value::Empty => write!(f, "()"), } } diff --git a/tests/integration.rs b/tests/integration.rs index 2c90c9f..4aedc2a 100644 --- a/tests/integration.rs +++ b/tests/integration.rs @@ -279,18 +279,9 @@ fn test_n_ary_functions() { #[test] fn test_builtin_functions() { - assert_eq!( - eval("min(4.0, 3)"), - Ok(Value::Int(3)) - ); - assert_eq!( - eval("max(4.0, 3)"), - Ok(Value::Float(4.0)) - ); - assert_eq!( - eval("len(\"foobar\")"), - Ok(Value::Int(6)) - ); + assert_eq!(eval("min(4.0, 3)"), Ok(Value::Int(3))); + assert_eq!(eval("max(4.0, 3)"), Ok(Value::Float(4.0))); + assert_eq!(eval("len(\"foobar\")"), Ok(Value::Int(6))); assert_eq!( eval("str::to_lowercase(\"FOOBAR\")"), Ok(Value::from("foobar")) @@ -317,10 +308,10 @@ fn test_regex_functions() { Ok(Value::Boolean(false)) ); match eval("str::regex_matches(\"foo\", \"[\")") { - Err(EvalexprError::InvalidRegex{ regex, message }) => { + Err(EvalexprError::InvalidRegex { regex, message }) => { assert_eq!(regex, "["); assert!(message.contains("unclosed character class")); - }, + } v => panic!(v), }; assert_eq!(