Consumes the number at the current position, whose first digit is `first`.
(&mut self, first: CharSpan)
| 297 | |
| 298 | /// Consumes the number at the current position, whose first digit is `first`. |
| 299 | fn consume_number(&mut self, first: CharSpan) -> io::Result<TokenSpan> { |
| 300 | let mut s = String::new(); |
| 301 | let mut found_dot = false; |
| 302 | s.push(first.ch); |
| 303 | loop { |
| 304 | match self.input.peek() { |
| 305 | Some(Ok(ch_span)) => match ch_span.ch { |
| 306 | '.' => { |
| 307 | if found_dot { |
| 308 | self.input.next().unwrap()?; |
| 309 | return self |
| 310 | .handle_bad_read("Too many dots in numeric literal", first.pos); |
| 311 | } |
| 312 | s.push(self.input.next().unwrap()?.ch); |
| 313 | found_dot = true; |
| 314 | } |
| 315 | ch if ch.is_ascii_digit() => s.push(self.input.next().unwrap()?.ch), |
| 316 | ch if ch.is_separator() => break, |
| 317 | ch => { |
| 318 | self.input.next().unwrap()?; |
| 319 | let msg = format!("Unexpected character in numeric literal: {}", ch); |
| 320 | return self.handle_bad_read(msg, first.pos); |
| 321 | } |
| 322 | }, |
| 323 | Some(Err(_)) => return Err(self.input.next().unwrap().unwrap_err()), |
| 324 | None => break, |
| 325 | } |
| 326 | } |
| 327 | if found_dot { |
| 328 | if s.ends_with('.') { |
| 329 | // TODO(jmmv): Reconsider supporting double literals with a . that is not prefixed |
| 330 | // by a number or not followed by a number. For now, mimic the error we get when |
| 331 | // we encounter a dot not prefixed by a number. |
| 332 | return self.handle_bad_read("Unknown character: .", first.pos); |
| 333 | } |
| 334 | match s.parse::<f64>() { |
| 335 | Ok(d) => Ok(TokenSpan::new(Token::Double(d), first.pos, s.len())), |
| 336 | Err(e) => self.handle_bad_read(format!("Bad double {}: {}", s, e), first.pos), |
| 337 | } |
| 338 | } else { |
| 339 | match s.parse::<i32>() { |
| 340 | Ok(i) => Ok(TokenSpan::new(Token::Integer(i), first.pos, s.len())), |
| 341 | Err(e) => self.handle_bad_read(format!("Bad integer {}: {}", s, e), first.pos), |
| 342 | } |
| 343 | } |
| 344 | } |
| 345 | |
| 346 | /// Consumes the integer at the current position, whose first digit is `first` and which is |
| 347 | /// expected to be expressed in the given `base`. `prefix_len` indicates how many characters |
no test coverage detected