1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
pub mod ast;
pub mod types;
use ast::{
parser::{AnnotatedExprParser, ExprParser},
AnnotatedError, ParseError as UserParseError,
};
use lalrpop_util::ParseError;
use num_runtime_fmt::Numeric;
use types::Calcable;
#[derive(Default)]
pub struct Context<N> {
pub history: Vec<N>,
}
#[derive(Debug, thiserror::Error)]
pub enum Error<N>
where
N: std::fmt::Debug + Calcable,
<N as Calcable>::Err: 'static,
{
#[error("Parsing")]
Parse(#[from] ParseError<usize, &'static str, UserParseError>),
#[error("Evaluating")]
Eval(#[source] <N as Calcable>::Err),
#[error("Formatting")]
Format(#[source] num_runtime_fmt::Error),
}
impl<N> From<AnnotatedError<N>> for Error<N>
where
N: std::fmt::Debug + Calcable,
<N as Calcable>::Err: 'static,
{
fn from(err: AnnotatedError<N>) -> Self {
match err {
AnnotatedError::Calculation(err) => Self::Eval(err),
AnnotatedError::Format(err) => Self::Format(err),
}
}
}
impl<N> Context<N>
where
N: std::fmt::Debug + Calcable,
<N as Calcable>::Err: 'static,
{
pub fn evaluate(&mut self, expr: &str) -> Result<N, Error<N>> {
let parser = ExprParser::new();
let expr = parser.parse(expr).map_err(|err| err.map_token(|_| ""))?;
let result = expr.evaluate(self).map_err(Error::Eval)?;
self.history.push(result.clone());
Ok(result)
}
}
impl<N> Context<N>
where
N: std::fmt::Debug + Calcable + Numeric,
<N as Calcable>::Err: 'static,
{
pub fn evaluate_annotated(&mut self, expr: &str) -> Result<String, Error<N>> {
let parser = AnnotatedExprParser::new();
let expr = parser.parse(expr).map_err(|err| err.map_token(|_| ""))?;
let (result, formatted) = expr.evaluate(self)?;
self.history.push(result);
Ok(formatted)
}
}