aboutsummaryrefslogtreecommitdiff
path: root/src/lex/mod.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/lex/mod.rs
parent38c23d8102ffcdc7763da51a17fbc39296e127c7 (diff)
refactor into modules
Diffstat (limited to 'src/lex/mod.rs')
-rw-r--r--src/lex/mod.rs145
1 files changed, 145 insertions, 0 deletions
diff --git a/src/lex/mod.rs b/src/lex/mod.rs
new file mode 100644
index 0000000..af5ff06
--- /dev/null
+++ b/src/lex/mod.rs
@@ -0,0 +1,145 @@
1use std::f64;
2#[derive(Debug, Copy, Clone, PartialEq)]
3pub struct Operator {
4 token: char,
5 pub operation: fn(f64, f64) -> f64,
6 pub precedence: u8,
7 pub is_left_associative: bool,
8}
9
10impl Operator {
11 fn token_from_op(token: char, operation: fn(f64, f64) -> f64, precedence: u8, is_left_associative: bool) -> Token {
12 Token::Operator(
13 Operator {
14 token,
15 operation,
16 precedence,
17 is_left_associative
18 }
19 )
20 }
21 pub fn operate(self, x: f64, y: f64) -> f64 {
22 (self.operation)(x, y)
23 }
24}
25
26#[derive(Debug, Clone, PartialEq)]
27pub struct Function {
28 token: String,
29 relation: fn(f64) -> f64,
30}
31
32impl Function {
33 fn token_from_fn(token: String, relation: fn(f64) -> f64) -> Token {
34 Token::Function(
35 Function {
36 token,
37 relation
38 }
39 )
40 }
41 pub fn apply(self, arg: f64) -> f64 {
42 (self.relation)(arg)
43 }
44}
45
46
47#[derive(Debug, Clone, PartialEq)]
48pub enum Token {
49 Operator(Operator),
50 Num(f64),
51 Function(Function),
52 LParen,
53 RParen
54}
55
56pub fn lexer(input: &str) -> Result<Vec<Token>, String> {
57 let mut num_vec: String = String::new();
58 let mut char_vec: String = String::new();
59 let mut result: Vec<Token> = vec![];
60 for letter in input.chars() {
61 match letter {
62 '0'...'9' | '.' => {
63 num_vec.push(letter);
64 },
65 'a'...'z' | 'A'...'Z' => {
66 let parse_num = num_vec.parse::<f64>().ok();
67 if let Some(x) = parse_num {
68 result.push(Token::Num(x));
69 result.push(Operator::token_from_op('*', |x, y| x * y, 3, true));
70 num_vec.clear();
71 }
72 char_vec.push(letter);
73 },
74 '+' | '-' | '/' | '*' | '^' => {
75 let parse_num = num_vec.parse::<f64>().ok();
76 if let Some(x) = parse_num {
77 result.push(Token::Num(x));
78 num_vec.clear();
79 }
80 let operator_token: Token = match letter {
81 '+' => Operator::token_from_op('+', |x, y| x + y, 2, true),
82 '-' => Operator::token_from_op('-', |x, y| x - y, 2, true),
83 '/' => Operator::token_from_op('/', |x, y| x / y, 3, true),
84 '*' => Operator::token_from_op('*', |x, y| x * y, 3, true),
85 '^' => Operator::token_from_op('^', |x, y| x.powf(y), 4, false),
86 _ => panic!("unexpected op whuuu"),
87 };
88 result.push(operator_token);
89 },
90 '(' => {
91 if char_vec.len() > 0 {
92 let funct = char_vec.clone();
93 match &funct[..] {
94 "sin" | "sine" => result.push(Function::token_from_fn("sin".into(), |x| x.to_radians().sin())),
95 "cos" | "cosine" => result.push(Function::token_from_fn("cos".into(), |x| x.to_radians().cos())),
96 "tan" | "tangent" => result.push(Function::token_from_fn("tan".into(), |x| x.to_radians().tan())),
97 "csc" | "cosec" => result.push(Function::token_from_fn("csc".into(), |x| 1f64 / x.to_radians().sin())),
98 "sec" | "secant" => result.push(Function::token_from_fn("sec".into(), |x| 1f64 / x.to_radians().cos())),
99 "cot" | "cotangent" => result.push(Function::token_from_fn("cot".into(), |x| 1f64 / x.to_radians().tan())),
100 "ln" => result.push(Function::token_from_fn("ln".into(), |x| x.ln())),
101 "log" => result.push(Function::token_from_fn("log".into(), |x| x.log10())),
102 "sqrt" => result.push(Function::token_from_fn("sqrt".into(), |x| x.sqrt())),
103 _ => return Err(format!("Unexpected function {}", funct))
104 }
105 char_vec.clear();
106 } else {
107 let parse_num = num_vec.parse::<f64>().ok();
108 if let Some(x) = parse_num {
109 result.push(Token::Num(x));
110 result.push(Operator::token_from_op('*', |x, y| x * y, 3, true));
111 num_vec.clear();
112 }
113 }
114
115 if let Some(x) = result.last() {
116 match x {
117 Token::RParen => {
118 result.push(Operator::token_from_op('*', |x, y| x * y, 3, true));
119 },
120 _ => {}
121 };
122 }
123 result.push(Token::LParen);
124 },
125 ')' => {
126 let parse_num = num_vec.parse::<f64>().ok();
127 if let Some(x) = parse_num {
128 result.push(Token::Num(x));
129 num_vec.clear();
130 }
131 result.push(Token::RParen);
132 }
133 ' ' => {}
134 _ => {
135 return Err(format!("Unexpected character: {}", letter))
136 }
137 }
138 }
139 let parse_num = num_vec.parse::<f64>().ok();
140 if let Some(x) = parse_num {
141 result.push(Token::Num(x));
142 num_vec.clear();
143 }
144 Ok(result)
145}