diff options
Diffstat (limited to 'src/math/expression.rs')
| -rw-r--r-- | src/math/expression.rs | 80 |
1 files changed, 57 insertions, 23 deletions
diff --git a/src/math/expression.rs b/src/math/expression.rs index 9d6d4f3..049886d 100644 --- a/src/math/expression.rs +++ b/src/math/expression.rs @@ -1,25 +1,42 @@ -use crate::math::complex::Complex; -use crate::math::context::Context; -use crate::math::function::FunctionArgument; -use crate::math::string::{ContainsAndSkipBrackets, SplitMatchingBracket}; +use super::complex::Complex; +use super::context::Context; +use super::function::FunctionArgument; +use super::string::{ContainsAndSkipBrackets, SplitMatchingBracket}; +use super::operation::Operation; + +enum ExpressionType { + Value(Complex), + Variable(String), + Function(String, FunctionArgument), + Operation(Operation, Box<Expression>, Box<Expression>), +} + +impl Default for ExpressionType { + fn default() -> Self { + ExpressionType::Value(Complex::default()) + } +} #[derive(Default)] pub struct Expression { + expr_type: ExpressionType, repr: String, } impl Expression { - pub fn from_string(str: &str) -> Self { - Self { - repr: str.replace(' ', ""), - } + pub fn from_string(str: &str, operations: &Vec<Operation>) -> Self { + let mut ex = Self::default(); + ex.repr = str.to_string(); + ex.set_operations(operations); + + ex } pub fn content(&self) -> &str { &self.repr } - pub fn evaluate(&self, context: &Context) -> Result<Complex, String> { + pub fn set_operations(&mut self, operations: &Vec<Operation>) { let (repr, oprepr) = { if self.repr.starts_with('(') { let (oprepr, r) = self.repr.split_on_matching_bracket(); @@ -36,7 +53,7 @@ impl Expression { let curop: Option<_> = { let mut o = None; - for op in context.operations() { + for op in operations { if oprepr.contains_and_skip_brackets(op.sign().to_string().as_str()) { o = Some(op); break; @@ -47,27 +64,44 @@ impl Expression { if let Some(op) = curop { let (first, rest) = repr.split_once_and_skipt_brackets(op.sign()).unwrap(); - let first_expr = Expression::from_string(first); - let rest_expr = Expression::from_string(rest); - Ok(op.evaluate(first_expr.evaluate(context)?, rest_expr.evaluate(context)?)) + let first_expr = Expression::from_string(first, operations); + let rest_expr = Expression::from_string(rest, operations); + self.expr_type = ExpressionType::Operation(op.clone(), Box::new(first_expr), Box::new(rest_expr)); } else if let Ok(r) = repr.parse::<Complex>() { - Ok(r) + self.expr_type = ExpressionType::Value(r); } else if let Some((func, args)) = repr.split_once('(') { let mut argv = Vec::new(); for arg in args[..args.len() - 1].split(',') { - argv.push(Expression::from_string(arg).evaluate(context)?); + argv.push(Expression::from_string(arg, operations)); } - if let Some(func) = context.function(func) { - Ok(func.eval(FunctionArgument::new(argv), context)?) - } else { - Err(format!("function '{func}' not found")) - } - } else if let Some(res) = context.variable(&repr) { - Ok(*res) + self.expr_type = ExpressionType::Function(func.to_string(), FunctionArgument::from_expressions(argv)); } else { - Err(format!("variable '{repr}' not found")) + self.expr_type = ExpressionType::Variable(repr); + } + } + + pub fn evaluate(&self, ctx: &Context) -> Result<Complex, String> { + match &self.expr_type { + ExpressionType::Value(v) => Ok(*v), + ExpressionType::Variable(var) => { + if let Some(v) = ctx.variable(&var) { + Ok(*v) + } else { + Err(format!("variable '{var}' not found")) + } + }, + ExpressionType::Function(func, args) => { + if let Some(f) = ctx.function(&func) { + f.eval(args, ctx) + } else { + Err(format!("function '{func}' not found")) + } + } + ExpressionType::Operation(op, a, b) => { + Ok(op.evaluate(a.evaluate(ctx)?, b.evaluate(ctx)?)) + } } } } |