use crate::complex::Complex; use crate::context::Context; use crate::function::FunctionArgument; use crate::string::{ContainsAndSkipBrackets, SplitMatchingBracket}; pub struct Expression { repr: String, } impl Expression { pub fn from_string(str: &str) -> Self { Self { repr: str.replace(' ', ""), } } pub fn evaluate(&self, context: &Context) -> Result { let (repr, oprepr) = { if self.repr.starts_with('(') { let (oprepr, r) = self.repr.split_on_matching_bracket(); if r.is_empty() { let repr = oprepr[1..oprepr.len() - 1].to_string(); (repr.clone(), repr) } else { (self.repr.to_string(), r.to_string()) } } else { (self.repr.to_string(), self.repr.to_string()) } }; let curop: Option<_> = { let mut o = None; for op in context.operations() { if oprepr.contains_and_skip_brackets(op.sign().to_string().as_str()) { o = Some(op); break; } } o }; 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)?)) } else if let Ok(r) = repr.parse::() { Ok(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)?); } if let Some(func) = context.function(func) { Ok(func.eval(FunctionArgument::new(argv))?) } else { Err(format!("function '{func}' not found")) } } else if let Some(res) = context.variable(&repr) { Ok(*res) } else { Err(format!("variable '{repr}' not found")) } } }