use super::Lexer;
use crate::ast::Token;
impl Lexer {
pub(super) fn parse_number(&mut self) -> Token {
let mut num = self.consume_digits();
let mut is_float = false;
if self.peek() == Some('.') {
let next = self.peek_ahead(1);
let has_leading_zero = num.starts_with('0');
let has_multiple_leading_zeroes = has_leading_zero && num.len() > 1;
if next.is_some_and(|c| c.is_ascii_digit()) && !has_multiple_leading_zeroes {
is_float = true;
num.push('.');
self.advance();
num.push_str(&self.consume_digits());
} else if next.is_none_or(|c| !c.is_ascii_digit()) && !num.is_empty() && num != "0" {
is_float = true;
num.push('.');
self.advance();
}
}
if is_float {
if let Some(exp) = self.parse_exponent() {
num.push_str(&exp);
}
return Token::Float(num.into());
}
Token::Integer(num.into())
}
pub(super) fn parse_exponent(&mut self) -> Option<String> {
if !matches!(self.peek(), Some('e' | 'E')) {
return None;
}
self.try_with_cursor(|this| {
let mut exponent = String::new();
exponent.push(this.advance().unwrap());
if matches!(this.peek(), Some('+' | '-')) {
exponent.push(this.advance().unwrap());
}
if this.peek().is_some_and(|c| c.is_ascii_digit()) {
exponent.push_str(&this.consume_digits());
Some(exponent)
} else {
None
}
})
}
pub(super) fn consume_digits(&mut self) -> String {
self.take_ascii_while(|b| b.is_ascii_digit()).to_owned()
}
}