aboutsummaryrefslogtreecommitdiff
path: root/src/main.rs
diff options
context:
space:
mode:
authorNerdyPepper <[email protected]>2019-03-21 05:24:29 +0000
committerNerdyPepper <[email protected]>2019-03-21 05:24:29 +0000
commita050178c692c59861cb0fb9666321fbef7578039 (patch)
tree9747261773daa52075fe4befa841e0c261eecc1e /src/main.rs
parent38c23d8102ffcdc7763da51a17fbc39296e127c7 (diff)
refactor into modules
Diffstat (limited to 'src/main.rs')
-rw-r--r--src/main.rs241
1 files changed, 6 insertions, 235 deletions
diff --git a/src/main.rs b/src/main.rs
index 71251e2..63d0eb2 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,57 +1,11 @@
1use std::io::{ stdin };
1use std::f64; 2use std::f64;
2 3
3#[derive(Debug, Copy, Clone, PartialEq)] 4mod lex;
4pub struct Operator { 5use crate::lex::*;
5 token: char,
6 operation: fn(f64, f64) -> f64,
7 precedence: u8,
8 is_left_associative: bool,
9}
10
11#[derive(Debug, Clone, PartialEq)]
12pub struct Function {
13 token: String,
14 relation: fn(f64) -> f64,
15}
16
17#[derive(Debug, Clone, PartialEq)]
18pub enum Token {
19 Operator(Operator),
20 Num(f64),
21 Function(Function),
22 LParen,
23 RParen
24}
25
26impl Operator {
27 fn token_from_op(token: char, operation: fn(f64, f64) -> f64, precedence: u8, is_left_associative: bool) -> Token {
28 Token::Operator(
29 Operator {
30 token,
31 operation,
32 precedence,
33 is_left_associative
34 }
35 )
36 }
37 fn operate(self, x: f64, y: f64) -> f64 {
38 (self.operation)(x, y)
39 }
40}
41 6
42impl Function { 7mod parse;
43 fn token_from_fn(token: String, relation: fn(f64) -> f64) -> Token { 8use crate::parse::*;
44 Token::Function(
45 Function {
46 token,
47 relation
48 }
49 )
50 }
51 fn apply(self, arg: f64) -> f64 {
52 (self.relation)(arg)
53 }
54}
55 9
56fn main() { 10fn main() {
57 loop { 11 loop {
@@ -69,191 +23,8 @@ fn main() {
69 let postfixed = to_postfix(lexed.unwrap()); 23 let postfixed = to_postfix(lexed.unwrap());
70 let evaled = eval_postfix(postfixed.unwrap()); 24 let evaled = eval_postfix(postfixed.unwrap());
71 println!("ans: {}", evaled.unwrap()); 25 println!("ans: {}", evaled.unwrap());
26 println!();
72 } 27 }
73} 28}
74 29
75fn lexer(input: &str) -> Result<Vec<Token>, String> {
76 let mut num_vec: String = String::new();
77 let mut char_vec: String = String::new();
78 let mut result: Vec<Token> = vec![];
79 for letter in input.chars() {
80 match letter {
81 '0'...'9' | '.' => {
82 num_vec.push(letter);
83 },
84 'a'...'z' | 'A'...'Z' => {
85 let parse_num = num_vec.parse::<f64>().ok();
86 if let Some(x) = parse_num {
87 result.push(Token::Num(x));
88 result.push(Operator::token_from_op('*', |x, y| x * y, 3, true));
89 num_vec.clear();
90 }
91 char_vec.push(letter);
92 },
93 '+' | '-' | '/' | '*' | '^' => {
94 let parse_num = num_vec.parse::<f64>().ok();
95 if let Some(x) = parse_num {
96 result.push(Token::Num(x));
97 num_vec.clear();
98 }
99 let operator_token: Token = match letter {
100 '+' => Operator::token_from_op('+', |x, y| x + y, 2, true),
101 '-' => Operator::token_from_op('-', |x, y| x - y, 2, true),
102 '/' => Operator::token_from_op('/', |x, y| x / y, 3, true),
103 '*' => Operator::token_from_op('*', |x, y| x * y, 3, true),
104 '^' => Operator::token_from_op('^', |x, y| x.powf(y), 4, false),
105 _ => panic!("unexpected op whuuu"),
106 };
107 result.push(operator_token);
108 },
109 '(' => {
110 if char_vec.len() > 0 {
111 let funct = char_vec.clone();
112 match &funct[..] {
113 "sin" | "sine" => result.push(Function::token_from_fn("sin".into(), |x| x.to_radians().sin())),
114 "cos" | "cosine" => result.push(Function::token_from_fn("cos".into(), |x| x.to_radians().cos())),
115 "tan" | "tangent" => result.push(Function::token_from_fn("tan".into(), |x| x.to_radians().tan())),
116 "csc" | "cosec" => result.push(Function::token_from_fn("csc".into(), |x| 1f64 / x.to_radians().sin())),
117 "sec" | "secant" => result.push(Function::token_from_fn("sec".into(), |x| 1f64 / x.to_radians().cos())),
118 "cot" | "cotangent" => result.push(Function::token_from_fn("cot".into(), |x| 1f64 / x.to_radians().tan())),
119 "ln" => result.push(Function::token_from_fn("ln".into(), |x| x.ln())),
120 "log" => result.push(Function::token_from_fn("log".into(), |x| x.log10())),
121 _ => {}
122 }
123 char_vec.clear();
124 } else {
125 let parse_num = num_vec.parse::<f64>().ok();
126 if let Some(x) = parse_num {
127 result.push(Token::Num(x));
128 result.push(Operator::token_from_op('*', |x, y| x * y, 3, true));
129 num_vec.clear();
130 }
131 }
132 30
133 if let Some(x) = result.last() {
134 match x {
135 Token::RParen => {
136 result.push(Operator::token_from_op('*', |x, y| x * y, 3, true));
137 },
138 _ => {}
139 };
140 }
141 result.push(Token::LParen);
142 },
143 ')' => {
144 let parse_num = num_vec.parse::<f64>().ok();
145 if let Some(x) = parse_num {
146 result.push(Token::Num(x));
147 num_vec.clear();
148 }
149 result.push(Token::RParen);
150 }
151 ' ' => {}
152 _ => {
153 return Err(format!("Unexpected character: {}", letter))
154 }
155 }
156 }
157 let parse_num = num_vec.parse::<f64>().ok();
158 if let Some(x) = parse_num {
159 result.push(Token::Num(x));
160 num_vec.clear();
161 }
162 Ok(result)
163}
164
165fn to_postfix(tokens: Vec<Token>) -> Result<Vec<Token>, String> {
166 let mut postfixed: Vec<Token> = vec![];
167 let mut op_stack: Vec<Token> = vec![];
168 for token in tokens {
169 match token {
170 Token::Num(_) => {
171 postfixed.push(token);
172 },
173 Token::Function(_) => {
174 op_stack.push(token);
175 }
176 Token::Operator(current_op) => {
177 while let Some(top_op) = op_stack.last() {
178 match top_op {
179 Token::LParen => {
180 break;
181 }
182 Token::Operator(x) => {
183 let tp = x.precedence;
184 let cp = current_op.precedence;
185 if tp > cp || (tp == cp && x.is_left_associative) {
186 postfixed.push(op_stack.pop().unwrap());
187 } else {
188 break;
189 }
190 }
191 Token::Function(_) => {
192 postfixed.push(op_stack.pop().unwrap());
193 }
194 _ => {
195 return Err(format!("{:?} must not be on operator stack", top_op))
196 }
197 }
198 }
199 op_stack.push(token);
200 },
201 Token::LParen => {
202 op_stack.push(token);
203 },
204 Token::RParen => {
205 let mut push_until_paren: bool = false;
206 while let Some(token) = op_stack.pop() {
207 if token == Token::LParen {
208 push_until_paren = true;
209 break;
210 }
211 postfixed.push(token)
212 }
213 if !push_until_paren {
214 return Err(String::from("Mismatched ')'"));
215 }
216 }
217
218 }
219 }
220 while let Some(op) = op_stack.pop() {
221 postfixed.push(op);
222 }
223 Ok(postfixed)
224}
225
226fn eval_postfix(postfixed: Vec<Token>) -> Result<f64, String> {
227 let mut num_stack: Vec<f64> = vec![];
228 for token in postfixed {
229 match token {
230 Token::Num(n) => {
231 num_stack.push(n);
232 },
233 Token::Operator(op) => {
234 if let Some(n2) = num_stack.pop() {
235 if let Some(n1) = num_stack.pop() {
236 num_stack.push(op.operate(n1, n2))
237 } else {
238 return Err(format!("Too many operators, Too little operands"))
239 }
240 } else {
241 return Err(format!("Too many operators, Too little operands"))
242 }
243 },
244 Token::Function(funct) => {
245 if let Some(arg) = num_stack.pop() {
246 num_stack.push(funct.apply(arg))
247 }
248 }
249 _ => {
250 return Err(format!("Yo nibba how did this get here"))
251 }
252 }
253 }
254 if num_stack.len() == 1 {
255 Ok(num_stack.pop().unwrap())
256 } else {
257 Err(format!("Parser Error"))
258 }
259}