1use std::fmt::Display;
2
3use anyhow::bail;
4use thiserror::Error;
5#[derive(Debug, Clone, PartialEq)]
6pub enum Expression {
7 Number(f64),
8 Addition,
9 Subtraction,
10 Division,
11 Multiplication,
12 Power,
13
14 Variable,
16
17 Bracket(Vec<Expression>),
18
19 BracketOpen,
20 BracketClose,
21}
22
23impl Expression {
24 pub fn get_number(&self) -> anyhow::Result<f64> {
25 if let Expression::Number(num) = self {
26 return Ok(*num);
27 } else {
28 bail!("Expression is not a number.");
29 }
30 }
31}
32
33impl ToString for Expression {
34 fn to_string(&self) -> String {
35 match self {
36 Expression::Number(num) => num.to_string(),
37 Expression::Addition => String::from("+"),
38 Expression::Subtraction => String::from("-"),
39 Expression::Division => String::from("/"),
40 Expression::Multiplication => String::from("*"),
41 Expression::Power => String::from("^"),
42 Expression::Variable => String::from("x"),
43 Expression::Bracket(inner) => inner
44 .iter()
45 .map(|expr| format!("{} ", expr.to_string()))
46 .collect::<Vec<String>>()
47 .concat(),
48 Expression::BracketOpen => String::from("("),
49 Expression::BracketClose => String::from(")"),
50 }
51 }
52}
53
54#[derive(Default, Debug)]
55pub struct Calculator {
56 inner: Vec<Expression>,
57}
58
59impl Calculator {
60 pub fn new(input: impl ToString) -> anyhow::Result<Self> {
62 let calculator_instance = Self {
63 inner: Self::parse(input.to_string())?,
64 };
65
66 Ok(calculator_instance)
67 }
68
69 pub fn into_inner(&self) -> Vec<Expression> {
71 self.inner.clone()
72 }
73
74 fn parse(input: String) -> anyhow::Result<Vec<Expression>> {
76 let unparsed_tokens = Self::tokenize(input)?;
77 let parsed_tokens = Self::evaluate(unparsed_tokens)?;
78
79 Ok(parsed_tokens)
80 }
81
82 fn tokenize(input: String) -> anyhow::Result<Vec<Expression>> {
84 let mut tokens: Vec<Expression> = vec![];
85
86 let mut num_buffer: String = String::new();
87
88 let mut last_expr: Option<Expression> = None;
89
90 for (idx, char) in input.chars().enumerate() {
91 let expression = match char.to_ascii_lowercase() {
92 '+' => Expression::Addition,
93 '-' => {
94 Expression::Subtraction
95
96 },
97 '*' => Expression::Multiplication,
98 '/' | ':' => Expression::Division,
99 '^' => Expression::Power,
100 ' ' => {
101 if !num_buffer.is_empty() {
102 tokens.push(Expression::Number(num_buffer.parse()?));
103
104 num_buffer.clear();
105 }
106
107 continue;
108 }
109 'x' => Expression::Variable,
110 '(' => Expression::BracketOpen,
111 ')' => Expression::BracketClose,
112 _ => {
113 if let Some(digit) = char.to_digit(10) {
114 num_buffer.push_str(&digit.to_string());
115
116 continue;
117 } else if char == '.' {
118 num_buffer.push('.');
119
120 continue;
121 }
122 else {
123 bail!(CalculatorError::new(
124 String::from(
125 "If you meant to define an unknown, only 'X' is available"
126 ),
127 input,
128 idx
129 ));
130 }
131 }
132 };
133
134 last_expr = Some(expression.clone());
135
136 if !num_buffer.is_empty() {
137 tokens.push(Expression::Number(num_buffer.parse::<f64>()?));
138
139 num_buffer.clear();
140 }
141
142 tokens.push(expression);
143 }
144
145 if !num_buffer.is_empty() {
146 tokens.push(Expression::Number(num_buffer.parse::<f64>()?));
147 }
148
149 Ok(tokens)
150 }
151
152 fn evaluate(mut input: Vec<Expression>) -> anyhow::Result<Vec<Expression>> {
155 let mut eval_buf: Vec<Expression> = vec![];
156 let mut equation_buf: Vec<Expression> = vec![];
157
158 let mut bracket_counter = 0;
159 let mut bracket_pos: (usize, usize) = (0, 0);
160
161 let mut iter_idx = 0;
162
163 while input.len() > iter_idx {
164 let expr = input[iter_idx].clone();
165
166 match &expr {
167 Expression::BracketOpen => {
168 if bracket_counter == 0 {
169 bracket_pos.0 = iter_idx;
170 } else {
171 equation_buf.push(Expression::BracketOpen);
172 }
173
174 bracket_counter += 1;
175 }
176 Expression::BracketClose => {
177 bracket_counter -= 1;
178
179 if bracket_counter == 0 {
180 bracket_pos.1 = iter_idx;
181
182 input.drain(bracket_pos.0..bracket_pos.1);
183
184 eval_buf.insert(
185 bracket_pos.0,
186 Expression::Bracket(Self::evaluate(equation_buf.clone())?),
187 );
188
189 iter_idx = bracket_pos.0;
190
191 equation_buf.clear();
192 } else {
193 equation_buf.push(Expression::BracketClose);
194 }
195 }
196 _ => {
197 if bracket_counter > 0 {
198 equation_buf.push(expr.clone());
199 } else {
200 eval_buf.push(expr.clone());
201 }
202 }
203 }
204
205 iter_idx += 1;
206 }
207
208 Ok(eval_buf)
209 }
210
211 pub fn calculate(&self, variable_value: Option<f64>) -> anyhow::Result<f64> {
213 return Self::__calc(self.inner.clone(), variable_value);
214 }
215
216 fn __calc(mut input: Vec<Expression>, variable_value: Option<f64>) -> anyhow::Result<f64> {
218 let mut iter_idx = 0;
219 let mut last_expr: Option<Expression> = None;
220
221 while input.len() > iter_idx {
222 let expr = input[iter_idx].clone();
223
224 match expr {
225 Expression::Bracket(ref inner) => {
226 input.remove(iter_idx);
227 input.insert(
228 iter_idx,
229 Expression::Number(Self::__calc(inner.to_vec(), variable_value)?),
230 );
231
232 if matches!(last_expr, Some(Expression::Bracket(_)))
233 || matches!(last_expr, Some(Expression::Number(_)))
234 {
235 input.insert(iter_idx, Expression::Multiplication);
236 last_expr = None;
237 }
238
239 continue;
240 }
241 Expression::Variable => {
242 let variable_value = &variable_value.ok_or_else(|| {
243 CalculatorError::from_expression_list(
244 String::from("A variable was used in the equation, but a default value has not been set."),
245 input.clone(),
246 iter_idx
247 )
248 })?;
249
250 input[iter_idx] = Expression::Number(*variable_value);
251
252 continue;
253 }
254 Expression::BracketOpen => unreachable!(),
255 Expression::BracketClose => unreachable!(),
256 Expression::Number(_) => (),
257 _ => {
258 let lhs = match input.clone().get(iter_idx - 1).ok_or(
259 CalculatorError::from_expression_list(
260 String::from("Expression not found."),
261 input.clone(),
262 iter_idx,
263 ),
264 )? {
265 Expression::Bracket(inner) => Self::__calc(inner.to_vec(), variable_value)?,
266 Expression::Number(inner) => inner.clone(),
267 _ => {
268 bail!(CalculatorError::from_expression_list(
269 String::from("Expression can not be turned into a number."),
270 input.clone(),
271 iter_idx
272 ))
273 }
274 };
275
276 let input_clone = input.clone();
277 let rhs = match input_clone.get(iter_idx + 1).ok_or(
278 CalculatorError::from_expression_list(
279 String::from("Expression not found."),
280 input.clone(),
281 iter_idx,
282 ),
283 )? {
284 Expression::Bracket(inner) => Self::__calc(inner.to_vec(), variable_value)?,
285 Expression::Number(inner) => *inner,
286 _ => {
287 bail!(CalculatorError::from_expression_list(
288 String::from("Expression can not be turned into a number."),
289 input.clone(),
290 iter_idx
291 ))
292 }
293 };
294
295 if expr == Expression::Multiplication {
296 input.drain(iter_idx - 1..=iter_idx + 1);
297 input.insert(iter_idx - 1, Expression::Number(lhs * rhs));
298 iter_idx -= 1;
299 } else if expr == Expression::Division {
300 input.drain(iter_idx - 1..=iter_idx + 1);
301 input.insert(iter_idx - 1, Expression::Number(lhs / rhs));
302 iter_idx -= 1;
303 } else if expr == Expression::Power {
304 input.drain(iter_idx - 1..=iter_idx + 1);
305 input.insert(iter_idx - 1, Expression::Number(lhs.powf(rhs)));
306 iter_idx -= 1;
307 }
308 }
309 }
310
311 last_expr = Some(expr);
312 iter_idx += 1;
313 }
314
315 iter_idx = 0;
316
317 while input.len() > iter_idx {
318 let expr = input[iter_idx].clone();
319
320 match expr {
321 Expression::Bracket(ref inner) => {
322 input.remove(iter_idx);
323 input.insert(
324 iter_idx,
325 Expression::Number(Self::__calc(inner.to_vec(), variable_value)?),
326 );
327
328 if matches!(last_expr, Some(Expression::Bracket(_)))
329 || matches!(last_expr, Some(Expression::Number(_)))
330 {
331 input.insert(iter_idx, Expression::Multiplication);
332 last_expr = None;
333 }
334
335 continue;
336 }
337 Expression::Variable => {
338 let variable_value = &variable_value.ok_or_else(|| {
339 CalculatorError::from_expression_list(
340 String::from("A variable was used in the equation, but a default value has not been set."),
341 input.clone(),
342 iter_idx
343 )
344 })?;
345
346 input[iter_idx] = Expression::Number(*variable_value);
347
348 continue;
349 }
350 Expression::BracketOpen => unreachable!(),
351 Expression::BracketClose => unreachable!(),
352 Expression::Number(_) => (),
353 _ => {
354 let lhs = match input.clone().get(iter_idx - 1).ok_or(
355 CalculatorError::from_expression_list(
356 String::from("Expression not found."),
357 input.clone(),
358 iter_idx,
359 ),
360 )? {
361 Expression::Bracket(inner) => Self::__calc(inner.to_vec(), variable_value)?,
362 Expression::Number(inner) => *inner,
363 _ => {
364 bail!(CalculatorError::from_expression_list(
365 String::from("Expression can not be turned into a number."),
366 input.clone(),
367 iter_idx
368 ))
369 }
370 };
371
372 let input_clone = input.clone();
373 let rhs = match input_clone.get(iter_idx + 1).ok_or(
374 CalculatorError::from_expression_list(
375 String::from("Expression not found."),
376 input.clone(),
377 iter_idx,
378 ),
379 )? {
380 Expression::Bracket(inner) => Self::__calc(inner.to_vec(), variable_value)?,
381 Expression::Number(inner) => *inner,
382 _ => {
383 bail!(CalculatorError::from_expression_list(
384 String::from("Expression can not be turned into a number."),
385 input.clone(),
386 iter_idx
387 ))
388 }
389 };
390
391 if expr == Expression::Addition {
392 input.drain(iter_idx - 1..=iter_idx + 1);
393 input.insert(iter_idx - 1, Expression::Number(lhs + rhs));
394 iter_idx -= 1;
395 } else if expr == Expression::Subtraction {
396 input.drain(iter_idx - 1..=iter_idx + 1);
397 input.insert(iter_idx - 1, Expression::Number(lhs - rhs));
398 iter_idx -= 1;
399 } else if expr == Expression::Variable {
400 input.drain(iter_idx - 1..=iter_idx + 1);
401 input.insert(iter_idx - 1, Expression::Number(0.0));
402 iter_idx -= 1;
403 }
404 }
405 }
406
407 last_expr = Some(expr);
408 iter_idx += 1;
409 }
410
411 if input.is_empty() || input.len() != 1 {
412 bail!(CalculatorError::from_expression_list(
413 String::from("Empty equation or invalid equation."),
414 input.clone(),
415 1
416 ));
417 }
418
419 Ok(input[0].get_number()?)
420 }
421}
422
423#[derive(Error, Debug)]
424pub struct CalculatorError {
425 message: String,
426
427 equation: String,
428
429 error_idx: usize,
430}
431
432impl Display for CalculatorError {
433 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
434 f.write_str(&format!(
435 "Syntax error!\nMessage: {}\n{}\n{}",
436 self.message,
437 self.equation,
438 {
439 let mut indentation = String::new();
440
441 for _ in 0..self.error_idx {
442 indentation.push(' ');
443 }
444
445 indentation.push('^');
446
447 indentation
448 }
449 ))
450 }
451}
452
453impl CalculatorError {
454 pub fn new(message: String, equation: String, error_idx: usize) -> Self {
455 Self {
456 message,
457 equation,
458 error_idx,
459 }
460 }
461
462 pub fn from_expression_list(
463 message: String,
464 equation: Vec<Expression>,
465 error_idx: usize,
466 ) -> Self {
467 let mut equation_string = String::new();
468
469 for expr in equation {
470 equation_string.push_str(&format!("{} ", expr.to_string()));
471 }
472
473 Self {
474 message,
475 equation: equation_string,
476 error_idx: {
477 if error_idx != 0 {
478 error_idx * 2 - 1
479 } else {
480 0
481 }
482 },
483 }
484 }
485}