diff options
Diffstat (limited to 'src/parse')
-rw-r--r-- | src/parse/mod.rs | 105 |
1 files changed, 0 insertions, 105 deletions
diff --git a/src/parse/mod.rs b/src/parse/mod.rs deleted file mode 100644 index aa8bd4b..0000000 --- a/src/parse/mod.rs +++ /dev/null | |||
@@ -1,105 +0,0 @@ | |||
1 | /* Copyright (C) 2019 Akshay Oppiliappan <[email protected]> | ||
2 | * Refer to LICENCE for more information. | ||
3 | * */ | ||
4 | |||
5 | use crate::error::CalcError; | ||
6 | use crate::lex::Token; | ||
7 | |||
8 | pub fn to_postfix(tokens: Vec<Token>) -> Result<Vec<Token>, CalcError> { | ||
9 | let mut postfixed: Vec<Token> = vec![]; | ||
10 | let mut op_stack: Vec<Token> = vec![]; | ||
11 | for token in tokens { | ||
12 | match token { | ||
13 | Token::Num(_) => { | ||
14 | postfixed.push(token); | ||
15 | } | ||
16 | Token::Function(_) => { | ||
17 | op_stack.push(token); | ||
18 | } | ||
19 | Token::Operator(current_op) => { | ||
20 | while let Some(top_op) = op_stack.last() { | ||
21 | match top_op { | ||
22 | Token::LParen => { | ||
23 | break; | ||
24 | } | ||
25 | Token::Operator(x) => { | ||
26 | let tp = x.precedence; | ||
27 | let cp = current_op.precedence; | ||
28 | if tp > cp || (tp == cp && x.is_left_associative) { | ||
29 | postfixed.push(op_stack.pop().unwrap()); | ||
30 | } else { | ||
31 | break; | ||
32 | } | ||
33 | } | ||
34 | Token::Function(_) => { | ||
35 | postfixed.push(op_stack.pop().unwrap()); | ||
36 | } | ||
37 | _ => { | ||
38 | unreachable!(); | ||
39 | } | ||
40 | } | ||
41 | } | ||
42 | op_stack.push(token); | ||
43 | } | ||
44 | Token::LParen => { | ||
45 | op_stack.push(token); | ||
46 | } | ||
47 | Token::RParen => { | ||
48 | let mut push_until_paren: bool = false; | ||
49 | while let Some(token) = op_stack.pop() { | ||
50 | if token == Token::LParen { | ||
51 | push_until_paren = true; | ||
52 | break; | ||
53 | } | ||
54 | postfixed.push(token) | ||
55 | } | ||
56 | if !push_until_paren { | ||
57 | return Err(CalcError::Syntax("Mismatched parentheses!".into())); | ||
58 | } | ||
59 | } | ||
60 | } | ||
61 | } | ||
62 | while let Some(op) = op_stack.pop() { | ||
63 | postfixed.push(op); | ||
64 | } | ||
65 | Ok(postfixed) | ||
66 | } | ||
67 | |||
68 | pub fn eval_postfix(postfixed: Vec<Token>) -> Result<f64, CalcError> { | ||
69 | let mut num_stack: Vec<f64> = vec![]; | ||
70 | for token in postfixed { | ||
71 | match token { | ||
72 | Token::Num(n) => { | ||
73 | num_stack.push(n); | ||
74 | } | ||
75 | Token::Operator(op) => { | ||
76 | if let Some(n2) = num_stack.pop() { | ||
77 | if let Some(n1) = num_stack.pop() { | ||
78 | num_stack.push(op.operate(n1, n2)?); | ||
79 | } else { | ||
80 | return Err(CalcError::Parser( | ||
81 | "Too many operators, Too little operands".to_string(), | ||
82 | )); | ||
83 | } | ||
84 | } else { | ||
85 | return Err(CalcError::Parser( | ||
86 | "Too many operators, Too little operands".to_string(), | ||
87 | )); | ||
88 | } | ||
89 | } | ||
90 | Token::Function(funct) => { | ||
91 | if let Some(arg) = num_stack.pop() { | ||
92 | num_stack.push(funct.apply(arg)?) | ||
93 | } | ||
94 | } | ||
95 | _ => unreachable!("wut"), | ||
96 | } | ||
97 | } | ||
98 | if num_stack.len() == 1 { | ||
99 | Ok(num_stack.pop().unwrap()) | ||
100 | } else { | ||
101 | Err(CalcError::Parser( | ||
102 | "Too many operators, Too little operands".to_string(), | ||
103 | )) | ||
104 | } | ||
105 | } | ||