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}