diff options
Diffstat (limited to 'src/parse')
-rw-r--r-- | src/parse/mod.rs | 96 |
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 @@ | |||
1 | use crate::lex::Token; | ||
2 | |||
3 | pub 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 | |||
63 | pub 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 | } | ||