Scan a number token which can represent either an integer or floating point number. Accept the following forms: - `10`: Integer - `-10`: Integer - `0xff_00`: Integer - `0.0`: Float - `0x1.f`: Float - `-0x2.4`: Float - `0x0.4p-34`: Float This function does not filter out all invalid numbers. It depends in the context-sensitive decoding of the text for that. For example, the number of allowed dig
(&mut self)
| 259 | // decoding of the text for that. For example, the number of allowed digits in an `Ieee32` and |
| 260 | // an `Ieee64` constant are different. |
| 261 | fn scan_number(&mut self) -> Result<LocatedToken<'a>, LocatedError> { |
| 262 | let begin = self.pos; |
| 263 | let loc = self.loc(); |
| 264 | let mut is_float = false; |
| 265 | |
| 266 | // Skip a leading sign. |
| 267 | match self.lookahead { |
| 268 | Some('-') => { |
| 269 | self.next_ch(); |
| 270 | if !self.looking_at_numeric() { |
| 271 | // If the next characters won't parse as a number, we return Token::Minus |
| 272 | return token(Token::Minus, loc); |
| 273 | } |
| 274 | } |
| 275 | Some('+') => { |
| 276 | self.next_ch(); |
| 277 | if !self.looking_at_numeric() { |
| 278 | // If the next characters won't parse as a number, we return Token::Plus |
| 279 | return token(Token::Plus, loc); |
| 280 | } |
| 281 | } |
| 282 | _ => {} |
| 283 | } |
| 284 | |
| 285 | // Check for NaNs with payloads. |
| 286 | if self.looking_at("NaN:") || self.looking_at("sNaN:") { |
| 287 | // Skip the `NaN:` prefix, the loop below won't accept it. |
| 288 | // We expect a hexadecimal number to follow the colon. |
| 289 | while self.next_ch() != Some(':') {} |
| 290 | is_float = true; |
| 291 | } else if self.looking_at("NaN") || self.looking_at("Inf") { |
| 292 | // This is Inf or a default quiet NaN. |
| 293 | is_float = true; |
| 294 | } |
| 295 | |
| 296 | // Look for the end of this number. Detect the radix point if there is one. |
| 297 | loop { |
| 298 | match self.next_ch() { |
| 299 | Some('-') | Some('_') => {} |
| 300 | Some('.') => is_float = true, |
| 301 | Some('0'..='9') | Some('a'..='z') | Some('A'..='Z') => {} |
| 302 | _ => break, |
| 303 | } |
| 304 | } |
| 305 | let text = &self.source[begin..self.pos]; |
| 306 | if is_float { |
| 307 | token(Token::Float(text), loc) |
| 308 | } else { |
| 309 | token(Token::Integer(text), loc) |
| 310 | } |
| 311 | } |
| 312 | |
| 313 | // Scan a 'word', which is an identifier-like sequence of characters beginning with '_' or an |
| 314 | // alphabetic char, followed by zero or more alphanumeric or '_' characters. |
no test coverage detected