use crate::defines::{LiteralFloat, LiteralInt}; use crate::parsing::lex_tokens::LexToken; use itertools::MultiPeek; use std::str::Chars; #[inline(always)] fn get_decimal_value(c: char) -> Option { match c { '0' => Some(0), '1' => Some(1), '2' => Some(2), '3' => Some(3), '4' => Some(4), '5' => Some(5), '6' => Some(6), '7' => Some(7), '8' => Some(8), '9' => Some(9), _ => None, } } #[inline(always)] fn lex_numeric_default(chars: &mut MultiPeek) -> LexToken { let mut int_value: LiteralInt = 0; let mut decimal_value: LiteralInt = 0; let mut exponent_value: LiteralInt = 0; let mut decimal_length: LiteralInt = 0; let mut is_decimal = false; let mut is_exponent = false; let mut is_reading = true; let mut c: Option = chars.peek().cloned(); while c.is_some() && is_reading { let v = get_decimal_value(c.unwrap()); match v { None => { if c.unwrap() == '_' { chars.next(); c = chars.peek().cloned(); continue; } if !is_decimal && c.unwrap() == '.' { is_decimal = true; chars.next(); c = chars.peek().cloned(); continue; } if is_decimal && c.unwrap() == 'e' || c.unwrap() == 'E' { is_decimal = false; is_exponent = true; chars.next(); c = chars.peek().cloned(); continue; } c = chars.peek().cloned(); is_reading = false; continue; } Some(i) => { chars.next(); if is_decimal { decimal_value *= 10; decimal_value += i; decimal_length += 1; } else if is_exponent { exponent_value *= 10; exponent_value += i; } else { int_value *= 10; int_value += i; } } } c = chars.peek().cloned(); } chars.reset_peek(); if is_decimal || is_exponent { let mut val = int_value as LiteralFloat + (decimal_value as LiteralFloat / 10_i64.pow(decimal_length as u32) as LiteralFloat); if is_exponent { val *= exponent_value.pow(10) as LiteralFloat; } LexToken::FloatLiteral(val) } else { LexToken::IntegerLiteral(int_value) } } #[inline(always)] fn get_hexadecimal_value(c: char) -> Option { match c { '0' => Some(0), '1' => Some(1), '2' => Some(2), '3' => Some(3), '4' => Some(4), '5' => Some(5), '6' => Some(6), '7' => Some(7), '8' => Some(8), '9' => Some(9), 'A' | 'a' => Some(10), 'B' | 'b' => Some(11), 'C' | 'c' => Some(12), 'D' | 'd' => Some(13), 'E' | 'e' => Some(14), 'F' | 'f' => Some(15), _ => None, } } #[inline(always)] fn lex_numeric_hexadecimal(chars: &mut MultiPeek) -> LexToken { let mut int_value: LiteralInt = 0; let mut reading = true; let mut n = chars.peek().cloned(); while n.is_some() && reading { match get_hexadecimal_value(n.unwrap()) { Some(i) => { int_value <<= 4; int_value += i; chars.next(); } None => { if n.unwrap() == '_' { chars.next(); } else { reading = false } } } n = chars.peek().cloned(); } LexToken::IntegerLiteral(int_value) } #[inline(always)] fn get_octal_value(c: char) -> Option { match c { '0' => Some(0), '1' => Some(1), '2' => Some(2), '3' => Some(3), '4' => Some(4), '5' => Some(5), '6' => Some(6), '7' => Some(7), _ => None, } } #[inline(always)] fn lex_numeric_octal(chars: &mut MultiPeek) -> LexToken { let mut int_value: LiteralInt = 0; let mut reading = true; let mut n = chars.peek().cloned(); while n.is_some() && reading { match get_octal_value(n.unwrap()) { Some(i) => { int_value <<= 3; int_value += i; chars.next(); } None => { if n.unwrap() == '_' { chars.next(); } else { reading = false } } } n = chars.peek().cloned(); } LexToken::IntegerLiteral(int_value) } #[inline(always)] fn get_binary_value(c: char) -> Option { match c { '0' => Some(0), '1' => Some(1), _ => None, } } #[inline(always)] fn lex_numeric_binary(chars: &mut MultiPeek) -> LexToken { let mut int_value: LiteralInt = 0; let mut reading = true; let mut n = chars.peek().cloned(); while n.is_some() && reading { match get_binary_value(n.unwrap()) { Some(i) => { int_value <<= 1; int_value += i; chars.next(); } None => { if n.unwrap() == '_' { chars.next(); } else { reading = false } } } n = chars.peek().cloned(); } LexToken::IntegerLiteral(int_value) } #[inline(always)] pub fn lex_numeric(chars: &mut MultiPeek) -> LexToken { chars.reset_peek(); if chars.peek() == Some(&'0') { match chars.peek() { Some(&'D') | Some(&'d') => { chars.next(); chars.next(); return lex_numeric_default(chars); } Some(&'X') | Some(&'x') => { chars.next(); chars.next(); return lex_numeric_hexadecimal(chars); } Some(&'O') | Some(&'o') => { chars.next(); chars.next(); return lex_numeric_octal(chars); } Some(&'B') | Some(&'b') => { chars.next(); chars.next(); return lex_numeric_binary(chars); } _ => {} } } chars.reset_peek(); lex_numeric_default(chars) }