aboutsummaryrefslogtreecommitdiff
path: root/src/parse
diff options
context:
space:
mode:
Diffstat (limited to 'src/parse')
-rw-r--r--src/parse/mod.rs96
1 files changed, 96 insertions, 0 deletions
diff --git a/src/parse/mod.rs b/src/parse/mod.rs
new file mode 100644
index 0000000..e5c28e6
--- /dev/null
+++ b/src/parse/mod.rs
@@ -0,0 +1,96 @@
1use crate::lex::Token;
2
3pub fn to_postfix(tokens: Vec<Token>) -> Result<Vec<Token>, String> {
4 let mut postfixed: Vec<Token> = vec![];
5 let mut op_stack: Vec<Token> = vec![];
6 for token in tokens {
7 match token {
8 Token::Num(_) => {
9 postfixed.push(token);
10 },
11 Token::Function(_) => {
12 op_stack.push(token);
13 }
14 Token::Operator(current_op) => {
15 while let Some(top_op) = op_stack.last() {
16 match top_op {
17 Token::LParen => {
18 break;
19 }
20 Token::Operator(x) => {
21 let tp = x.precedence;
22 let cp = current_op.precedence;
23 if tp > cp || (tp == cp && x.is_left_associative) {
24 postfixed.push(op_stack.pop().unwrap());
25 } else {
26 break;
27 }
28 }
29 Token::Function(_) => {
30 postfixed.push(op_stack.pop().unwrap());
31 }
32 _ => {
33 return Err(format!("{:?} must not be on operator stack", top_op))
34 }
35 }
36 }
37 op_stack.push(token);
38 },
39 Token::LParen => {
40 op_stack.push(token);
41 },
42 Token::RParen => {
43 let mut push_until_paren: bool = false;
44 while let Some(token) = op_stack.pop() {
45 if token == Token::LParen {
46 push_until_paren = true;
47 break;
48 }
49 postfixed.push(token)
50 }
51 if !push_until_paren {
52 return Err(String::from("Mismatched ')'"));
53 }
54 }
55 }
56 }
57 while let Some(op) = op_stack.pop() {
58 postfixed.push(op);
59 }
60 Ok(postfixed)
61}
62
63pub fn eval_postfix(postfixed: Vec<Token>) -> Result<f64, String> {
64 let mut num_stack: Vec<f64> = vec![];
65 for token in postfixed {
66 match token {
67 Token::Num(n) => {
68 num_stack.push(n);
69 },
70 Token::Operator(op) => {
71 if let Some(n2) = num_stack.pop() {
72 if let Some(n1) = num_stack.pop() {
73 num_stack.push(op.operate(n1, n2))
74 } else {
75 return Err(format!("Too many operators, Too little operands"))
76 }
77 } else {
78 return Err(format!("Too many operators, Too little operands"))
79 }
80 },
81 Token::Function(funct) => {
82 if let Some(arg) = num_stack.pop() {
83 num_stack.push(funct.apply(arg))
84 }
85 }
86 _ => {
87 return Err(format!("Yo nibba how did this get here"))
88 }
89 }
90 }
91 if num_stack.len() == 1 {
92 Ok(num_stack.pop().unwrap())
93 } else {
94 Err(format!("Parser Error"))
95 }
96}