aboutsummaryrefslogtreecommitdiff
path: root/src/math/expression.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/math/expression.rs')
-rw-r--r--src/math/expression.rs80
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)?))
+ }
}
}
}