Skip to main content

rl_lang/lexer/types/
number_literal.rs

1//! Integer and float literal scanner.
2//!
3//! Consumes a run of digits, checks for a `.` to decide between
4//! [`TokenType::NumberLiteral`] and [`TokenType::FloatLiteral`], and handles
5//! byte literals (`0b` prefix -> [`TokenType::ByteLiteral`]).
6use crate::lexer::{tokenizer::Tokenizer, tokentypes::TokenType};
7
8impl Tokenizer {
9    /// Scans an integer or float literal starting at the current position.
10    ///
11    /// A `.` followed by a digit switches to float parsing.
12    /// Integers in the range `0..=255` are emitted as [`TokenType::ByteLiteral`],
13    /// larger integers as [`TokenType::NumberLiteral`], and decimals as [`TokenType::FloatLiteral`].
14    ///
15    /// | Input   | Emitted token               |
16    /// |---------|-----------------------------|
17    /// | `1`     | `ByteLiteral(1)`            |
18    /// | `1000`  | `NumberLiteral(1000)`       |
19    /// | `3.14`  | `FloatLiteral(3.14)`        |
20    pub fn number_literal(&mut self) {
21        let mut is_float = false;
22        while self.peek().is_ascii_digit() {
23            self.advance();
24        }
25
26        if self.peek() == '.' && self.peek_next().is_ascii_digit() {
27            is_float = true;
28            self.advance();
29            while self.peek().is_ascii_digit() {
30                self.advance();
31            }
32        }
33
34        let value: String = self.source[self.start..self.current].iter().collect();
35
36        if is_float {
37            let parsed_value: f64 = value.parse().unwrap();
38            self.add_token(TokenType::FloatLiteral(parsed_value));
39        } else {
40            let parsed_value: i64 = value.parse().unwrap();
41            self.add_token(TokenType::NumberLiteral(parsed_value));
42        }
43    }
44}