From 22160b0802b219f330d962f51898d5f338ded61e Mon Sep 17 00:00:00 2001 From: sofia Date: Thu, 24 Jul 2025 21:33:03 +0300 Subject: [PATCH] Add octal, binary and hexadecimal representation --- examples/arithmetic.reid | 4 ++-- reid/src/ast/parse.rs | 18 ++++++++++++++++++ reid/src/lexer.rs | 28 ++++++++++++++++++++++++++-- 3 files changed, 46 insertions(+), 4 deletions(-) diff --git a/examples/arithmetic.reid b/examples/arithmetic.reid index 95223af..fea0607 100644 --- a/examples/arithmetic.reid +++ b/examples/arithmetic.reid @@ -2,8 +2,8 @@ fn main() -> u32 { - let value = 6; - let other = 15; + let value = 0b110; + let other = 0o17; return value * other + 7 * -value; } diff --git a/reid/src/ast/parse.rs b/reid/src/ast/parse.rs index f6c84d8..30cc031 100644 --- a/reid/src/ast/parse.rs +++ b/reid/src/ast/parse.rs @@ -153,6 +153,24 @@ impl Parse for PrimaryExpression { Expression(Kind::VariableName(v.clone()), stream.get_range().unwrap()) } } + Token::BinaryValue(v) => { + stream.next(); // Consume octal + Expression( + Kind::Literal(Literal::Integer( + u128::from_str_radix(&v, 2).expect("Binary is not parseable as u128!"), + )), + stream.get_range().unwrap(), + ) + } + Token::OctalValue(v) => { + stream.next(); // Consume octal + Expression( + Kind::Literal(Literal::Integer( + u128::from_str_radix(&v, 8).expect("Octal is not parseable as u128!"), + )), + stream.get_range().unwrap(), + ) + } Token::HexadecimalValue(v) => { stream.next(); // Consume hexadecimal Expression( diff --git a/reid/src/lexer.rs b/reid/src/lexer.rs index e786ae8..df426dd 100644 --- a/reid/src/lexer.rs +++ b/reid/src/lexer.rs @@ -19,6 +19,10 @@ pub enum Token { DecimalValue(String), /// Integer number in the hexadecimal base HexadecimalValue(String), + /// Integer number in the octal base + OctalValue(String), + /// Integer number in the binary base + BinaryValue(String), /// Some character literal that was surrounded by 'single-quotes'. CharLit(String), /// Some string literal that was surrounded by "double-quotes". @@ -141,7 +145,9 @@ impl ToString for Token { match &self { Token::Identifier(ident) => ident.clone(), Token::DecimalValue(val) => val.to_string(), - Token::HexadecimalValue(val) => val.to_string(), + Token::HexadecimalValue(val) => format!("0x{}", val), + Token::OctalValue(val) => format!("0o{}", val), + Token::BinaryValue(val) => format!("0b{}", val), Token::CharLit(lit) => format!("\'{}\'", lit), Token::StringLit(lit) => format!("\"{}\"", lit), Token::LetKeyword => String::from("let"), @@ -370,6 +376,18 @@ pub fn tokenize>(to_tokenize: T) -> Result, Error cursor.next(); value = NumberType::Hexadecimal(String::new()); numerics = HEXADECIMAL_NUMERICS; + } else if cursor.first() == Some('o') + && OCTAL_NUMERICS.contains(&second.to_lowercase().next().unwrap_or('.')) + { + cursor.next(); + value = NumberType::Octal(String::new()); + numerics = OCTAL_NUMERICS; + } else if cursor.first() == Some('b') + && BINARY_NUMERICS.contains(&second.to_lowercase().next().unwrap_or('.')) + { + cursor.next(); + value = NumberType::Binary(String::new()); + numerics = BINARY_NUMERICS; } } while let Some(c) = cursor.first() { @@ -380,8 +398,10 @@ pub fn tokenize>(to_tokenize: T) -> Result, Error cursor.next(); } match value { - NumberType::Decimal(value) => Token::DecimalValue(value), + NumberType::Decimal(dec) => Token::DecimalValue(dec), NumberType::Hexadecimal(hex) => Token::HexadecimalValue(hex), + NumberType::Octal(oct) => Token::OctalValue(oct), + NumberType::Binary(bin) => Token::BinaryValue(bin), } } '-' if cursor.first() == Some('>') => { @@ -440,6 +460,8 @@ fn escape_char(c: &char) -> char { enum NumberType { Decimal(String), Hexadecimal(String), + Octal(String), + Binary(String), } impl AddAssign for NumberType { @@ -449,6 +471,8 @@ impl AddAssign for NumberType { NumberType::Hexadecimal(val) => { NumberType::Hexadecimal(val.to_owned() + &rhs.to_string()) } + NumberType::Octal(val) => NumberType::Octal(val.to_owned() + &rhs.to_string()), + NumberType::Binary(val) => NumberType::Binary(val.to_owned() + &rhs.to_string()), }; } }