From 1aab77df1cc924a13f9e6a0c9054a04903550912 Mon Sep 17 00:00:00 2001 From: John-John Tedro Date: Sat, 25 Jul 2020 08:32:43 +0200 Subject: [PATCH] Avoid scanning over slices to validate numerical literals --- src/token.rs | 43 ++++++++++++++++++++++++++++------------ tests/number_literals.rs | 3 +++ 2 files changed, 33 insertions(+), 13 deletions(-) diff --git a/src/token.rs b/src/token.rs index f2719a7a..1248d742 100644 --- a/src/token.rs +++ b/src/token.rs @@ -810,6 +810,32 @@ pub fn get_next_token( result } +/// Test if the given character is a hex character. +fn is_hex_char(c: char) -> bool { + match c { + 'a'..='f' => true, + 'A'..='F' => true, + '0'..='9' => true, + _ => false, + } +} + +/// Test if the given character is an octal character. +fn is_octal_char(c: char) -> bool { + match c { + '0'..='7' => true, + _ => false, + } +} + +/// Test if the given character is a binary character. +fn is_binary_char(c: char) -> bool { + match c { + '0' | '1' => true, + _ => false, + } +} + /// Get the next token. fn get_next_token_inner( stream: &mut impl InputStream, @@ -872,18 +898,9 @@ fn get_next_token_inner( eat_next(stream, pos); let valid = match ch { - 'x' | 'X' => [ - 'a', 'b', 'c', 'd', 'e', 'f', 'A', 'B', 'C', 'D', 'E', 'F', - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '_', - ], - 'o' | 'O' => [ - '0', '1', '2', '3', '4', '5', '6', '7', '_', '_', '_', '_', - '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', - ], - 'b' | 'B' => [ - '0', '1', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', - '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_', - ], + 'x' | 'X' => is_hex_char, + 'o' | 'O' => is_octal_char, + 'b' | 'B' => is_binary_char, _ => unreachable!(), }; @@ -895,7 +912,7 @@ fn get_next_token_inner( }); while let Some(next_char_in_escape_seq) = stream.peek_next() { - if !valid.contains(&next_char_in_escape_seq) { + if !valid(next_char_in_escape_seq) { break; } diff --git a/tests/number_literals.rs b/tests/number_literals.rs index 699de19a..ce19b52d 100644 --- a/tests/number_literals.rs +++ b/tests/number_literals.rs @@ -14,6 +14,7 @@ fn test_hex_literal() -> Result<(), Box> { let engine = Engine::new(); assert_eq!(engine.eval::("let x = 0xf; x")?, 15); + assert_eq!(engine.eval::("let x = 0Xf; x")?, 15); assert_eq!(engine.eval::("let x = 0xff; x")?, 255); Ok(()) @@ -24,6 +25,7 @@ fn test_octal_literal() -> Result<(), Box> { let engine = Engine::new(); assert_eq!(engine.eval::("let x = 0o77; x")?, 63); + assert_eq!(engine.eval::("let x = 0O77; x")?, 63); assert_eq!(engine.eval::("let x = 0o1234; x")?, 668); Ok(()) @@ -34,6 +36,7 @@ fn test_binary_literal() -> Result<(), Box> { let engine = Engine::new(); assert_eq!(engine.eval::("let x = 0b1111; x")?, 15); + assert_eq!(engine.eval::("let x = 0B1111; x")?, 15); assert_eq!( engine.eval::("let x = 0b0011_1100_1010_0101; x")?, 15525