Scan simple hex value
This commit is contained in:
parent
c2946e7a9b
commit
730c5391d9
@ -1,24 +1,65 @@
|
|||||||
use crate::syntax::{token::{Token, self}, utils};
|
use crate::syntax::{token::{Token, self}, utils};
|
||||||
|
|
||||||
pub fn scan(chars: &Vec<char>, start_pos: usize) -> (Token, usize) {
|
pub fn scan(chars: &Vec<char>, start_pos: usize) -> (Token, usize) {
|
||||||
|
let next_char = chars.get(start_pos);
|
||||||
|
|
||||||
|
// Try to scan a HEX value
|
||||||
|
if let Some(c) = next_char {
|
||||||
|
if *c == '0' {
|
||||||
|
// May be an 'x' or 'X'
|
||||||
|
let next_next_char = chars.get(start_pos + 1);
|
||||||
|
if let Some(c2) = next_next_char {
|
||||||
|
if *c2 == 'x' || *c2 == 'X' {
|
||||||
|
return scan_hex(chars, start_pos + 2, String::from("0x"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
scan_decimal(chars, start_pos, String::from(""))
|
scan_decimal(chars, start_pos, String::from(""))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Scans an integer.
|
||||||
fn scan_decimal(chars: &Vec<char>, start_pos: usize, current: String) -> (Token, usize) {
|
fn scan_decimal(chars: &Vec<char>, start_pos: usize, current: String) -> (Token, usize) {
|
||||||
let next_char = chars.get(start_pos);
|
let next_char = chars.get(start_pos);
|
||||||
|
|
||||||
|
// If a char is found
|
||||||
if let Some(c) = next_char {
|
if let Some(c) = next_char {
|
||||||
if utils::is_digit(*c) {
|
let c = *c;
|
||||||
let new_value = format!("{}{}", current, *c);
|
|
||||||
scan_decimal(chars, start_pos + 1, new_value)
|
// Scan a decimal number
|
||||||
} else {
|
if utils::is_digit(c) {
|
||||||
|
let new_value = format!("{}{}", current, c);
|
||||||
|
return scan_decimal(chars, start_pos + 1, new_value)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the current value
|
||||||
(token::new_number(current, start_pos as i32), start_pos)
|
(token::new_number(current, start_pos as i32), start_pos)
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
(token::new_number(current, start_pos as i32), start_pos)
|
/// Scans a hex number. If successful, always returns '0x...', never '0X...'
|
||||||
|
///
|
||||||
|
/// `current == ""`
|
||||||
|
///
|
||||||
|
/// `start_pos` indicates the start of the hex value
|
||||||
|
fn scan_hex(chars: &Vec<char>, start_pos: usize, current: String) -> (Token, usize) {
|
||||||
|
let next_char = chars.get(start_pos);
|
||||||
|
|
||||||
|
if let Some(c) = next_char {
|
||||||
|
let c = *c;
|
||||||
|
|
||||||
|
if utils::is_hex_digit(c) {
|
||||||
|
return scan_hex(chars, start_pos + 1, utils::str_append(current, c))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Return current value
|
||||||
|
(token::new_number(current, start_pos as i32), start_pos)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@ -59,4 +100,36 @@ mod tests {
|
|||||||
assert_eq!(TokenType::Number, token.token_type);
|
assert_eq!(TokenType::Number, token.token_type);
|
||||||
assert_eq!("123456", token.value);
|
assert_eq!("123456", token.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_hex() {
|
||||||
|
let input = str_to_vec("0x20");
|
||||||
|
let start_pos = 0;
|
||||||
|
|
||||||
|
let (token, next) = scan(&input, start_pos);
|
||||||
|
assert_eq!(4, next);
|
||||||
|
assert_eq!(TokenType::Number, token.token_type);
|
||||||
|
assert_eq!("0x20", token.value);
|
||||||
|
|
||||||
|
|
||||||
|
let input = str_to_vec(" 0Xff23DA");
|
||||||
|
let start_pos = 4;
|
||||||
|
|
||||||
|
let (token, next) = scan(&input, start_pos);
|
||||||
|
assert_eq!(12, next);
|
||||||
|
assert_eq!(TokenType::Number, token.token_type);
|
||||||
|
assert_eq!("0xff23DA", token.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Should not scan an incomplete hex value
|
||||||
|
#[test]
|
||||||
|
fn test_hex_2() {
|
||||||
|
let input = str_to_vec("0x20");
|
||||||
|
let start_pos = 0;
|
||||||
|
|
||||||
|
let (token, next) = scan(&input, start_pos);
|
||||||
|
assert_eq!(4, next);
|
||||||
|
assert_eq!(TokenType::Number, token.token_type);
|
||||||
|
assert_eq!("0x20", token.value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,4 +3,10 @@ pub fn is_digit(c: char) -> bool {
|
|||||||
'0' <= c && c <= '9'
|
'0' <= c && c <= '9'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_hex_digit(c: char) -> bool {
|
||||||
|
is_digit(c) || 'a' <= c && c <= 'f' || 'A' <= c && c <= 'F'
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn str_append(current: String, c: char) -> String {
|
||||||
|
format!("{}{}", current, c)
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user