aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNerdyPepper <[email protected]>2019-03-23 04:01:07 +0000
committerNerdyPepper <[email protected]>2019-03-23 04:01:07 +0000
commit58f603506ee55fe78ce3b3a6cec473083f347eb5 (patch)
tree0d25c7b6af05959e78dcbd20faeb536aa06e05a5
parent86ba4458cfddf1d8db5231d7e0240c2374abc770 (diff)
fix unary operator lexing
-rw-r--r--src/lex/mod.rs25
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