diff --git a/SLS_Rust/sls/src/lexer.rs b/SLS_Rust/sls/src/lexer.rs index 62a9af9..0e0ae86 100644 --- a/SLS_Rust/sls/src/lexer.rs +++ b/SLS_Rust/sls/src/lexer.rs @@ -153,6 +153,15 @@ pub struct LexError { pub type LexResult = Result; +#[derive(Debug, Clone, Copy)] +enum NumericLiteralType { + Binary, + Octal, + Decimal, + Hexadecimal, + Float, +} + impl LexerInfo { fn make_error(&self, message: impl Into, start_line: usize, start_col: usize) -> LexError { LexError { @@ -316,6 +325,10 @@ impl LexerInfo { c = self.advance(); } + if c == ':' { + return self.parse_numeric_type(start, start_line, start_col, NumericLiteralType::Binary); + } + let value = self.create_binary_integer(start); Ok(Token::I64(value as i64)) } @@ -326,6 +339,10 @@ impl LexerInfo { c = self.advance(); } + if c == ':' { + return self.parse_numeric_type(start, start_line, start_col, NumericLiteralType::Octal); + } + let value = self.create_octal_integer(start); Ok(Token::I64(value as i64)) } @@ -341,6 +358,10 @@ impl LexerInfo { return self.parse_float(start, start_line, start_col); } + if c == ':' { + return self.parse_numeric_type(start, start_line, start_col, NumericLiteralType::Decimal); + } + let value = self.create_decimal_integer(start); Ok(Token::I64(value as i64)) } @@ -351,6 +372,10 @@ impl LexerInfo { c = self.advance(); } + if c == ':' { + return self.parse_numeric_type(start, start_line, start_col, NumericLiteralType::Hexadecimal); + } + let value = self.create_hexadecimal_integer(start); Ok(Token::I64(value as i64)) } @@ -361,10 +386,157 @@ impl LexerInfo { c = self.advance(); } + if c == ':' { + return self.parse_numeric_type(start, start_line, start_col, NumericLiteralType::Float); + } + let value = self.create_float(start); Ok(Token::Double(value)) } + fn parse_numeric_type(&mut self, start: usize, start_line: usize, start_col: usize, literal_type: NumericLiteralType) -> LexResult { + let mut c = self.advance(); // skip ':' + + let mut is_float = false; + let mut is_unsigned = false; + let mut bit_size = 64; // default + + if c == 'f' { + is_float = true; + if !matches!(literal_type, NumericLiteralType::Decimal | NumericLiteralType::Float) { + return Err(self.make_error("Invalid numeric literal: float type not allowed.", start_line, start_col)); + } + c = self.advance(); + if c == '6' && self.far_peek(1) == '4' { + bit_size = 64; + self.advance(); + self.advance(); + } else if c == '3' && self.far_peek(1) == '2' { + bit_size = 32; + self.advance(); + self.advance(); + } else { + return Err(self.make_error("Invalid float type: must be of type 'f64' or 'f32'.", start_line, start_col)); + } + } else if c == 'i' || c == 'u' { + if matches!(literal_type, NumericLiteralType::Float) { + return Err(self.make_error("Invalid float type: must be of type 'f64' or 'f32'.", start_line, start_col)); + } + is_unsigned = c == 'u'; + c = self.advance(); + if c == '6' && self.far_peek(1) == '4' { + bit_size = 64; + self.advance(); + self.advance(); + } else if c == '3' && self.far_peek(1) == '2' { + bit_size = 32; + self.advance(); + self.advance(); + } else if c == '1' && self.far_peek(1) == '6' { + bit_size = 16; + self.advance(); + self.advance(); + } else if c == '8' { + bit_size = 8; + self.advance(); + } else { + let type_name = if is_unsigned { "unsigned" } else { "signed" }; + return Err(self.make_error( + format!("Invalid {} integer type: must be of type '{}64', '{}32', '{}16', or '{}8'.", + type_name, if is_unsigned { "u" } else { "i" }, + if is_unsigned { "u" } else { "i" }, + if is_unsigned { "u" } else { "i" }, + if is_unsigned { "u" } else { "i" }), + start_line, start_col)); + } + } else { + return Err(self.make_error("Invalid numeric type: type must start with 'f', 'i', or 'u'.", start_line, start_col)); + } + + // Create the token based on the parsed type + if is_float { + let value = self.create_float(start); + match bit_size { + 32 => Ok(Token::Float(value as f32)), + 64 => Ok(Token::Double(value)), + _ => unreachable!() + } + } else { + let value = match literal_type { + NumericLiteralType::Binary => self.create_binary_integer(start), + NumericLiteralType::Octal => self.create_octal_integer(start), + NumericLiteralType::Decimal => self.create_decimal_integer(start), + NumericLiteralType::Hexadecimal => self.create_hexadecimal_integer(start), + NumericLiteralType::Float => return Err(self.make_error("Internal error: float literal in integer path", start_line, start_col)), + }; + + self.create_integer_token(value, is_unsigned, bit_size, start, start_line, start_col) + } + } + + fn create_integer_token(&self, value: u64, is_unsigned: bool, bit_size: u32, start: usize, start_line: usize, start_col: usize) -> LexResult { + let is_negative = self.source[start..].starts_with('-'); + + match (is_unsigned, bit_size) { + (false, 64) => Ok(Token::I64(value as i64)), + (false, 32) => { + let signed = value as i64; + if signed < i32::MIN as i64 || signed > i32::MAX as i64 { + return Err(self.make_error("Integer overflow: value exceeds range for i32.", start_line, start_col)); + } + Ok(Token::I32(value as i32)) + } + (false, 16) => { + let signed = value as i64; + if signed < i16::MIN as i64 || signed > i16::MAX as i64 { + return Err(self.make_error("Integer overflow: value exceeds range for i16.", start_line, start_col)); + } + Ok(Token::I16(value as i16)) + } + (false, 8) => { + let signed = value as i64; + if signed < i8::MIN as i64 || signed > i8::MAX as i64 { + return Err(self.make_error("Integer overflow: value exceeds range for i8.", start_line, start_col)); + } + Ok(Token::I8(value as i8)) + } + (true, 64) => { + if is_negative { + return Err(self.make_error("Integer overflow: value exceeds range for u64.", start_line, start_col)); + } + Ok(Token::U64(value)) + } + (true, 32) => { + if is_negative { + return Err(self.make_error("Integer overflow: value exceeds range for u32.", start_line, start_col)); + } + if value > u32::MAX as u64 { + return Err(self.make_error("Integer overflow: value exceeds range for u32.", start_line, start_col)); + } + Ok(Token::U32(value as u32)) + } + (true, 16) => { + if is_negative { + return Err(self.make_error("Integer overflow: value exceeds range for u16.", start_line, start_col)); + } + if value > u16::MAX as u64 { + return Err(self.make_error("Integer overflow: value exceeds range for u16.", start_line, start_col)); + } + Ok(Token::U16(value as u16)) + } + (true, 8) => { + if is_negative { + return Err(self.make_error("Integer overflow: value exceeds range for u8.", start_line, start_col)); + } + if value > u8::MAX as u64 { + return Err(self.make_error("Integer overflow: value exceeds range for u8.", start_line, start_col)); + } + Ok(Token::U8(value as u8)) + } + _ => Err(self.make_error("Invalid bit size for integer type.", start_line, start_col)) + } + } + fn create_binary_integer(&self, start: usize) -> u64 { let token = &self.source[start..self.pos]; let mut value = 0u64;