From c724c9157dbc4721fa8ed93033cd9699c9652277 Mon Sep 17 00:00:00 2001 From: Ben Bridle Date: Sat, 12 Apr 2025 10:08:09 +1200 Subject: Implement negative integer literals Negative literals take the forms -29, -0x1D, and -0b11101 for decimal, hexadecimal, and binary. --- src/stages/syntactic.rs | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/stages/syntactic.rs b/src/stages/syntactic.rs index 14f8815..45d5e60 100644 --- a/src/stages/syntactic.rs +++ b/src/stages/syntactic.rs @@ -168,22 +168,27 @@ fn parse_syntactic_from_tokeniser(mut t: Tokeniser) -> Result { let token = format!("{c}{}", t.eat_token()); - if let Some(hex_string) = token.strip_prefix("0x") { + let (stripped, neg) = match token.strip_prefix('-') { + Some(stripped) => (stripped, true), + None => (token.as_str(), false), + }; + if let Some(hex_string) = stripped.strip_prefix("0x") { let hex_string = hex_string.to_string(); - match parse_integer_literal(&hex_string, 16) { + match parse_integer_literal(&hex_string, 16, neg) { Ok(value) => SyntacticToken::IntegerLiteral(value), Err(_) => err!(SyntacticError::InvalidHexadecimalLiteral(hex_string)), } - } else if let Some(binary_string) = token.strip_prefix("0b") { + } else if let Some(binary_string) = stripped.strip_prefix("0b") { let binary_string = binary_string.to_string(); - match parse_integer_literal(&binary_string, 2) { + match parse_integer_literal(&binary_string, 2, neg) { Ok(value) => SyntacticToken::IntegerLiteral(value), Err(_) => err!(SyntacticError::InvalidBinaryLiteral(binary_string)), } } else { - match parse_integer_literal(&token, 10) { + let decimal_string = stripped.to_string(); + match parse_integer_literal(&decimal_string, 10, neg) { Ok(value) => SyntacticToken::IntegerLiteral(value), - Err(true) => err!(SyntacticError::InvalidDecimalLiteral(token)), + Err(true) => err!(SyntacticError::InvalidDecimalLiteral(decimal_string)), Err(false) => SyntacticToken::Symbol(ScopedSymbol::Global(token)), } } @@ -200,10 +205,13 @@ fn parse_syntactic_from_tokeniser(mut t: Tokeniser) -> Result Result { +fn parse_integer_literal(token: &str, radix: u32, neg: bool) -> Result { match usize::from_str_radix(&token.replace('_', ""), radix) { Ok(value) => match isize::try_from(value) { - Ok(value) => Ok(value), + Ok(value) => match neg { + true => Ok(-value), + false => Ok(value), + } Err(_) => Err(true), } Err(_) => Err(false), -- cgit v1.2.3-70-g09d2