diff options
author | NerdyPepper <[email protected]> | 2019-03-23 04:01:07 +0000 |
---|---|---|
committer | NerdyPepper <[email protected]> | 2019-03-23 04:01:07 +0000 |
commit | 58f603506ee55fe78ce3b3a6cec473083f347eb5 (patch) | |
tree | 0d25c7b6af05959e78dcbd20faeb536aa06e05a5 | |
parent | 86ba4458cfddf1d8db5231d7e0240c2374abc770 (diff) |
fix unary operator lexing
-rw-r--r-- | src/lex/mod.rs | 25 |
1 files changed, 21 insertions, 4 deletions
diff --git a/src/lex/mod.rs b/src/lex/mod.rs index e6b2000..a4ea952 100644 --- a/src/lex/mod.rs +++ b/src/lex/mod.rs | |||
@@ -90,10 +90,14 @@ pub fn lexer(input: &str) -> Result<Vec<Token>, String> { | |||
90 | let mut num_vec: String = String::new(); | 90 | let mut num_vec: String = String::new(); |
91 | let mut char_vec: String = String::new(); | 91 | let mut char_vec: String = String::new(); |
92 | let mut result: Vec<Token> = vec![]; | 92 | let mut result: Vec<Token> = vec![]; |
93 | let mut last_char_is_op = true; | ||
94 | |||
93 | for letter in input.chars() { | 95 | for letter in input.chars() { |
94 | match letter { | 96 | match letter { |
95 | '0'...'9' | '.' => { | 97 | '0'...'9' | '.' => { |
96 | num_vec.push(letter); | 98 | num_vec.push(letter); |
99 | last_char_is_op = false; // 5 - 6 | ||
100 | // ^---- binary | ||
97 | }, | 101 | }, |
98 | 'a'...'z' | 'A'...'Z' => { | 102 | 'a'...'z' | 'A'...'Z' => { |
99 | let parse_num = num_vec.parse::<f64>().ok(); | 103 | let parse_num = num_vec.parse::<f64>().ok(); |
@@ -103,15 +107,19 @@ pub fn lexer(input: &str) -> Result<Vec<Token>, String> { | |||
103 | num_vec.clear(); | 107 | num_vec.clear(); |
104 | } | 108 | } |
105 | char_vec.push(letter); | 109 | char_vec.push(letter); |
110 | last_char_is_op = false; // + or - can never be encountered right after a character | ||
106 | }, | 111 | }, |
107 | '+' | '-' => { | 112 | '+' | '-' => { |
108 | let op_token = operators.get(&letter).unwrap().clone(); | 113 | let op_token = operators.get(&letter).unwrap().clone(); |
109 | let parse_num = num_vec.parse::<f64>().ok(); | 114 | let parse_num = num_vec.parse::<f64>().ok(); |
110 | if let Some(x) = parse_num { | 115 | if !last_char_is_op { |
111 | result.push(Token::Num(x)); | 116 | if let Some(x) = parse_num { |
112 | num_vec.clear(); | 117 | result.push(Token::Num(x)); |
118 | num_vec.clear(); | ||
119 | last_char_is_op = true; | ||
120 | } | ||
113 | result.push(op_token); | 121 | result.push(op_token); |
114 | } else { | 122 | } else if last_char_is_op { // act as unary only if an operator was parsed previously |
115 | result.push(Token::LParen); | 123 | result.push(Token::LParen); |
116 | result.push(Token::Num((letter.to_string() + "1").parse::<f64>().unwrap())); | 124 | result.push(Token::Num((letter.to_string() + "1").parse::<f64>().unwrap())); |
117 | result.push(Token::RParen); | 125 | result.push(Token::RParen); |
@@ -122,6 +130,8 @@ pub fn lexer(input: &str) -> Result<Vec<Token>, String> { | |||
122 | drain_num_stack(&mut num_vec, &mut result); | 130 | drain_num_stack(&mut num_vec, &mut result); |
123 | let operator_token: Token = operators.get(&letter).unwrap().clone(); | 131 | let operator_token: Token = operators.get(&letter).unwrap().clone(); |
124 | result.push(operator_token); | 132 | result.push(operator_token); |
133 | last_char_is_op = true; // 5 / -5 | ||
134 | // ^---- unary | ||
125 | }, | 135 | }, |
126 | '(' => { | 136 | '(' => { |
127 | if char_vec.len() > 0 { | 137 | if char_vec.len() > 0 { |
@@ -149,10 +159,16 @@ pub fn lexer(input: &str) -> Result<Vec<Token>, String> { | |||
149 | }; | 159 | }; |
150 | } | 160 | } |
151 | result.push(Token::LParen); | 161 | result.push(Token::LParen); |
162 | last_char_is_op = true; // unary + or - if a lparen was encountered | ||
163 | // (-5 + 6) or (+6 + 7) | ||
164 | // ^-----------^-----unary | ||
152 | }, | 165 | }, |
153 | ')' => { | 166 | ')' => { |
154 | drain_num_stack(&mut num_vec, &mut result); | 167 | drain_num_stack(&mut num_vec, &mut result); |
155 | result.push(Token::RParen); | 168 | result.push(Token::RParen); |
169 | last_char_is_op = false; // binary + or - if rparen was encountered | ||
170 | // (1 + 2) - (3 + 4) | ||
171 | // ^ binary minus | ||
156 | } | 172 | } |
157 | ' ' => {} | 173 | ' ' => {} |
158 | _ => { | 174 | _ => { |
@@ -161,6 +177,7 @@ pub fn lexer(input: &str) -> Result<Vec<Token>, String> { | |||
161 | } | 177 | } |
162 | } | 178 | } |
163 | drain_num_stack(&mut num_vec, &mut result); | 179 | drain_num_stack(&mut num_vec, &mut result); |
180 | println!("{:?}", result); | ||
164 | Ok(result) | 181 | Ok(result) |
165 | } | 182 | } |
166 | 183 | ||