Avoid scanning over slices to validate numerical literals

This commit is contained in:
John-John Tedro 2020-07-25 08:32:43 +02:00
parent 8109e26538
commit 1aab77df1c
2 changed files with 33 additions and 13 deletions

View File

@ -810,6 +810,32 @@ pub fn get_next_token(
result 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. /// Get the next token.
fn get_next_token_inner( fn get_next_token_inner(
stream: &mut impl InputStream, stream: &mut impl InputStream,
@ -872,18 +898,9 @@ fn get_next_token_inner(
eat_next(stream, pos); eat_next(stream, pos);
let valid = match ch { let valid = match ch {
'x' | 'X' => [ 'x' | 'X' => is_hex_char,
'a', 'b', 'c', 'd', 'e', 'f', 'A', 'B', 'C', 'D', 'E', 'F', 'o' | 'O' => is_octal_char,
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '_', 'b' | 'B' => is_binary_char,
],
'o' | 'O' => [
'0', '1', '2', '3', '4', '5', '6', '7', '_', '_', '_', '_',
'_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_',
],
'b' | 'B' => [
'0', '1', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_',
'_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_',
],
_ => unreachable!(), _ => unreachable!(),
}; };
@ -895,7 +912,7 @@ fn get_next_token_inner(
}); });
while let Some(next_char_in_escape_seq) = stream.peek_next() { 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; break;
} }

View File

@ -14,6 +14,7 @@ fn test_hex_literal() -> Result<(), Box<EvalAltResult>> {
let engine = Engine::new(); let engine = Engine::new();
assert_eq!(engine.eval::<INT>("let x = 0xf; x")?, 15); assert_eq!(engine.eval::<INT>("let x = 0xf; x")?, 15);
assert_eq!(engine.eval::<INT>("let x = 0Xf; x")?, 15);
assert_eq!(engine.eval::<INT>("let x = 0xff; x")?, 255); assert_eq!(engine.eval::<INT>("let x = 0xff; x")?, 255);
Ok(()) Ok(())
@ -24,6 +25,7 @@ fn test_octal_literal() -> Result<(), Box<EvalAltResult>> {
let engine = Engine::new(); let engine = Engine::new();
assert_eq!(engine.eval::<INT>("let x = 0o77; x")?, 63); assert_eq!(engine.eval::<INT>("let x = 0o77; x")?, 63);
assert_eq!(engine.eval::<INT>("let x = 0O77; x")?, 63);
assert_eq!(engine.eval::<INT>("let x = 0o1234; x")?, 668); assert_eq!(engine.eval::<INT>("let x = 0o1234; x")?, 668);
Ok(()) Ok(())
@ -34,6 +36,7 @@ fn test_binary_literal() -> Result<(), Box<EvalAltResult>> {
let engine = Engine::new(); let engine = Engine::new();
assert_eq!(engine.eval::<INT>("let x = 0b1111; x")?, 15); assert_eq!(engine.eval::<INT>("let x = 0b1111; x")?, 15);
assert_eq!(engine.eval::<INT>("let x = 0B1111; x")?, 15);
assert_eq!( assert_eq!(
engine.eval::<INT>("let x = 0b0011_1100_1010_0101; x")?, engine.eval::<INT>("let x = 0b0011_1100_1010_0101; x")?,
15525 15525