From 25a230b297e2912c83cc291bedbd592dd20a5eb5 Mon Sep 17 00:00:00 2001 From: John Lapeyre Date: Mon, 28 Oct 2024 21:11:57 -0400 Subject: [PATCH] Support prefixes 0X, 0O, 0B for hex, octal, binary literals Closes #226 Previously, literals with prefix `0x` were parsed and analyzed correctly. But literals with prefix `0X` were analyzed as value `0`. This is now fixed. Prefixes `0B` and `0O` were broken in the same way and are now fixed. This fix also uncovers a bug that will be opened and fixed separately: Illegal (nonsense) integer literals, with prefixes such as 0Q will be analyzed as valid, decimal, literals. Instead they should cause an error to be logged. A lex, or possibly parse, error. --- .../oq3_semantics/tests/from_string_tests.rs | 72 +++++++++++++++++++ crates/oq3_syntax/src/ast/token_ext.rs | 6 +- 2 files changed, 75 insertions(+), 3 deletions(-) diff --git a/crates/oq3_semantics/tests/from_string_tests.rs b/crates/oq3_semantics/tests/from_string_tests.rs index f97ecfa..72d4b93 100644 --- a/crates/oq3_semantics/tests/from_string_tests.rs +++ b/crates/oq3_semantics/tests/from_string_tests.rs @@ -521,6 +521,78 @@ fn test_from_string_neg_spc_lit_float() { assert_eq!(expr, "-1.23"); } +#[test] +fn test_from_string_hex_literal() { + let code = r##" +0xFF; +"##; + let (program, errors, _symbol_table) = parse_string(code); + assert!(errors.is_empty()); + assert_eq!(program.len(), 1); + let expr = literal_value(&program[0]).unwrap(); + assert_eq!(expr, "255"); +} + +#[test] +fn test_from_string_hex_literal_capital() { + let code = r##" +0XFF; +"##; + let (program, errors, _symbol_table) = parse_string(code); + assert!(errors.is_empty()); + assert_eq!(program.len(), 1); + let expr = literal_value(&program[0]).unwrap(); + assert_eq!(expr, "255"); +} + +#[test] +fn test_from_string_octal_literal() { + let code = r##" +0o77; +"##; + let (program, errors, _symbol_table) = parse_string(code); + assert!(errors.is_empty()); + assert_eq!(program.len(), 1); + let expr = literal_value(&program[0]).unwrap(); + assert_eq!(expr, "63"); +} + +#[test] +fn test_from_string_octal_literal_capital() { + let code = r##" +0O77; +"##; + let (program, errors, _symbol_table) = parse_string(code); + assert!(errors.is_empty()); + assert_eq!(program.len(), 1); + let expr = literal_value(&program[0]).unwrap(); + assert_eq!(expr, "63"); +} + +#[test] +fn test_from_string_binary_literal() { + let code = r##" +0b11; +"##; + let (program, errors, _symbol_table) = parse_string(code); + assert!(errors.is_empty()); + assert_eq!(program.len(), 1); + let expr = literal_value(&program[0]).unwrap(); + assert_eq!(expr, "3"); +} + +#[test] +fn test_from_string_binary_literal_capital() { + let code = r##" +0B11; +"##; + let (program, errors, _symbol_table) = parse_string(code); + assert!(errors.is_empty()); + assert_eq!(program.len(), 1); + let expr = literal_value(&program[0]).unwrap(); + assert_eq!(expr, "3"); +} + // PR #91 #[test] fn test_from_string_bin_expr_no_spc() { diff --git a/crates/oq3_syntax/src/ast/token_ext.rs b/crates/oq3_syntax/src/ast/token_ext.rs index 3f62d1f..4c8ab4c 100644 --- a/crates/oq3_syntax/src/ast/token_ext.rs +++ b/crates/oq3_syntax/src/ast/token_ext.rs @@ -259,9 +259,9 @@ impl ast::BitString { impl ast::IntNumber { pub fn radix(&self) -> Radix { match self.text().get(..2).unwrap_or_default() { - "0b" => Radix::Binary, - "0o" => Radix::Octal, - "0x" => Radix::Hexadecimal, + "0b" | "0B" => Radix::Binary, + "0o" | "0O" => Radix::Octal, + "0x" | "0X" => Radix::Hexadecimal, _ => Radix::Decimal, } }