equation_solver/
equation.rs1use std::collections::HashSet;
2
3use crate::{
4 error::{EquationError, EquationErrorType},
5 item::{Item, Operator},
6 parse::ParseStream,
7};
8
9#[derive(Debug)]
11pub struct Equation {
12 inner: Group,
13}
14
15#[derive(Debug, Clone)]
17pub struct Group {
18 items: Vec<Item>,
19}
20
21enum Previous {
23 Function,
24 Value,
25 None,
26}
27
28impl Group {
29 pub fn new() -> Group {
31 Group { items: Vec::new() }
32 }
33 pub fn validate(&self) -> Result<(), EquationError> {
35 let mut previous = Previous::None;
36 let mut x = self.items.iter();
37 while let Some(next) = x.next() {
38 match (&previous, next) {
39 (Previous::None, Item::Value(_) | Item::Variable(_) | Item::Group(_)) => {
40 previous = Previous::Value
41 }
42 (Previous::None, Item::Operator(Operator::Functional(_))) => {
43 previous = Previous::Function
44 }
45 (Previous::Value, Item::Operator(Operator::LeftAssociative(_))) => {
46 previous = Previous::Function
47 }
48 (Previous::Function, Item::Group(_) | Item::Variable(_) | Item::Value(_)) => {
49 previous = Previous::Value
50 }
51
52 (_, _) => {
53 return Err(EquationError::new(
54 "Unexpected token".to_string(),
55 EquationErrorType::UnexpectedToken,
56 ))
57 }
58 }
59 }
60 Ok(())
61 }
62 pub fn set_value(&mut self, variable: &str, item: Item) {
64 let mut x = self.items.iter_mut();
65 while let Some(next) = x.next() {
66 match next {
67 Item::Variable(val) if val == variable => {
68 *next = item.clone();
69 }
70 Item::Group(val) => {
71 val.set_value(variable, item.clone());
72 }
73 _ => {}
74 }
75 }
76 }
77 pub fn evaluate(&self) -> Result<f64, EquationError> {
79 let mut items = self.items.clone();
81 let mut i = 0;
82 while i < items.len() {
83 if let Some(Item::Group(val)) = items.get(i) {
84 let val = val.evaluate()?;
86 items[i] = Item::Value(val);
87 }
88 i += 1;
89 }
90 let mut i = 0;
92 while i < items.len() - 1 {
93 let next = items.get(i).unwrap().clone();
94 if let Item::Operator(Operator::Functional(func)) = next {
95 let to_eval = items.remove(i + 1);
96 if let Item::Value(to_eval) = to_eval {
97 let val = func.evaluate(to_eval);
98 items[i] = Item::Value(val);
99 } else if let Item::Variable(var) = to_eval {
100 return Err(EquationError::new(
101 format!("Variable {} not set", var),
102 EquationErrorType::UnsetVariable,
103 ));
104 } else {
105 return Err(EquationError::new(
106 format!("Unexpected token {:?}", to_eval),
107 EquationErrorType::UnexpectedToken,
108 ));
109 }
110 }
111 i += 1;
112 }
113 let mut i = 1;
115 for order in 0..3 {
116 while i < items.len() - 1 {
117 let next = items.get(i).unwrap().clone();
118 if let Item::Operator(Operator::LeftAssociative(op)) = next {
119 if op.is_of_order(&order) {
120 let right = items.remove(i + 1);
121 let left = items.remove(i - 1);
122 let x = (left, right);
123 if let (Item::Value(left), Item::Value(right)) = x.clone() {
125 let val = op.eval(left, right);
126 items[i - 1] = Item::Value(val);
127 } else {
128 return Err(EquationError::new(
129 "Incorrect Tokens".to_string(),
130 EquationErrorType::UnexpectedToken,
131 ));
132 }
133 continue;
134 }
135 }
136 i += 1;
137 }
138 i = 1;
139 }
140 if let Some(Item::Value(val)) = items.get(0) {
141 Ok(*val)
142 } else {
143 Err(EquationError::new(
144 "Unexpected Tokens".to_string(),
145 EquationErrorType::UnexpectedToken,
146 ))
147 }
148 }
149 pub fn list_vars(&self) -> HashSet<String> {
151 let mut vars = HashSet::new();
152 for item in self.items.iter() {
153 match item {
154 Item::Variable(val) => {
155 vars.insert(val.clone());
156 }
157 Item::Group(val) => {
158 vars.extend(val.list_vars());
159 }
160 _ => {}
161 }
162 }
163 vars
164 }
165}
166
167impl From<Vec<Item>> for Group {
168 fn from(val: Vec<Item>) -> Self {
169 Group { items: val }
170 }
171}
172
173impl Equation {
174 pub fn new(s: impl Into<String>) -> Result<Equation, EquationError> {
176 let parse_stream = ParseStream::new(s.into());
177 let mut group: Group = parse_stream.parse_items()?.into();
178 group.set_value("pi", std::f64::consts::PI.into());
181 group.set_value("e", std::f64::consts::E.into());
182 group.set_value("tau", std::f64::consts::TAU.into());
183 group.set_value("deg", (std::f64::consts::PI / 180.0).into());
184 Ok(Equation { inner: group })
185 }
186 pub fn set_value(&mut self, variable: &str, value: f64) -> &mut Self {
188 self.inner.set_value(variable, Item::Value(value));
189 self
190 }
191 pub fn set_equation(&mut self, variable: &str, equation: Self) -> &mut Self {
193 self.inner.set_value(variable, Item::Group(equation.inner));
194 self
195 }
196 pub fn evaluate(&self) -> Result<f64, EquationError> {
198 self.inner.evaluate()
199 }
200 pub fn list_vars(&self) -> HashSet<String> {
202 self.inner.list_vars()
203 }
204}