blob: aa8bd4b618a732dedfcc1ab77d03ce5a01df01c9 (
plain)
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
99
100
101
102
103
104
105
|
/* Copyright (C) 2019 Akshay Oppiliappan <[email protected]>
* Refer to LICENCE for more information.
* */
use crate::error::CalcError;
use crate::lex::Token;
pub fn to_postfix(tokens: Vec<Token>) -> Result<Vec<Token>, CalcError> {
let mut postfixed: Vec<Token> = vec![];
let mut op_stack: Vec<Token> = vec![];
for token in tokens {
match token {
Token::Num(_) => {
postfixed.push(token);
}
Token::Function(_) => {
op_stack.push(token);
}
Token::Operator(current_op) => {
while let Some(top_op) = op_stack.last() {
match top_op {
Token::LParen => {
break;
}
Token::Operator(x) => {
let tp = x.precedence;
let cp = current_op.precedence;
if tp > cp || (tp == cp && x.is_left_associative) {
postfixed.push(op_stack.pop().unwrap());
} else {
break;
}
}
Token::Function(_) => {
postfixed.push(op_stack.pop().unwrap());
}
_ => {
unreachable!();
}
}
}
op_stack.push(token);
}
Token::LParen => {
op_stack.push(token);
}
Token::RParen => {
let mut push_until_paren: bool = false;
while let Some(token) = op_stack.pop() {
if token == Token::LParen {
push_until_paren = true;
break;
}
postfixed.push(token)
}
if !push_until_paren {
return Err(CalcError::Syntax("Mismatched parentheses!".into()));
}
}
}
}
while let Some(op) = op_stack.pop() {
postfixed.push(op);
}
Ok(postfixed)
}
pub fn eval_postfix(postfixed: Vec<Token>) -> Result<f64, CalcError> {
let mut num_stack: Vec<f64> = vec![];
for token in postfixed {
match token {
Token::Num(n) => {
num_stack.push(n);
}
Token::Operator(op) => {
if let Some(n2) = num_stack.pop() {
if let Some(n1) = num_stack.pop() {
num_stack.push(op.operate(n1, n2)?);
} else {
return Err(CalcError::Parser(
"Too many operators, Too little operands".to_string(),
));
}
} else {
return Err(CalcError::Parser(
"Too many operators, Too little operands".to_string(),
));
}
}
Token::Function(funct) => {
if let Some(arg) = num_stack.pop() {
num_stack.push(funct.apply(arg)?)
}
}
_ => unreachable!("wut"),
}
}
if num_stack.len() == 1 {
Ok(num_stack.pop().unwrap())
} else {
Err(CalcError::Parser(
"Too many operators, Too little operands".to_string(),
))
}
}
|