Scan and keywords
This commit is contained in:
parent
e580167682
commit
f3ee68fcf1
@ -1,4 +1,14 @@
|
|||||||
use crate::lexic::{token, utils, LexResult};
|
use crate::{lexic::{token, utils, LexResult}, token::TokenType};
|
||||||
|
|
||||||
|
/// Checks if a String is a keyword, and returns its TokenType
|
||||||
|
fn str_is_keyword(s: &String) -> Option<TokenType> {
|
||||||
|
match s.as_str() {
|
||||||
|
"var" => Some(TokenType::VAR),
|
||||||
|
"val" => Some(TokenType::VAL),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn scan(start_char: char, chars: &Vec<char>, start_pos: usize) -> LexResult {
|
pub fn scan(start_char: char, chars: &Vec<char>, start_pos: usize) -> LexResult {
|
||||||
scan_impl(chars, start_pos + 1, format!("{}", start_char))
|
scan_impl(chars, start_pos + 1, format!("{}", start_char))
|
||||||
@ -10,7 +20,12 @@ pub fn scan_impl(chars: &Vec<char>, start_pos: usize, current: String) -> LexRes
|
|||||||
scan_impl(chars, start_pos + 1, utils::str_append(current, *c))
|
scan_impl(chars, start_pos + 1, utils::str_append(current, *c))
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
LexResult::Some(token::new_identifier(current, start_pos as i32), start_pos)
|
if let Some(token_type) = str_is_keyword(¤t) {
|
||||||
|
LexResult::Some(token::new(current, start_pos as i32, token_type), start_pos)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
LexResult::Some(token::new_identifier(current, start_pos as i32), start_pos)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -119,4 +134,25 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Should scan keywords
|
||||||
|
#[test]
|
||||||
|
fn test_4() {
|
||||||
|
let input = str_to_vec("var");
|
||||||
|
let start_pos = 0;
|
||||||
|
if let LexResult::Some(token, next) = scan(*input.get(0).unwrap(), &input, start_pos) {
|
||||||
|
assert_eq!(3, next);
|
||||||
|
assert_eq!(TokenType::VAR, token.token_type);
|
||||||
|
assert_eq!("var", token.value);
|
||||||
|
} else {panic!()}
|
||||||
|
|
||||||
|
|
||||||
|
let input = str_to_vec("val");
|
||||||
|
let start_pos = 0;
|
||||||
|
if let LexResult::Some(token, next) = scan(*input.get(0).unwrap(), &input, start_pos) {
|
||||||
|
assert_eq!(3, next);
|
||||||
|
assert_eq!(TokenType::VAL, token.token_type);
|
||||||
|
assert_eq!("val", token.value);
|
||||||
|
} else {panic!()}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,7 @@ pub fn grouping_sign(c: char, _: &Vec<char>, start_pos: usize) -> Option<LexResu
|
|||||||
_ => return None,
|
_ => return None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let token = token::new_grouping_sign(
|
let token = token::new(
|
||||||
c.to_string(),
|
c.to_string(),
|
||||||
start_pos as i32,
|
start_pos as i32,
|
||||||
token_type,
|
token_type,
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
use crate::lexic::{token::{Token, self}, utils, LexResult};
|
use crate::lexic::{
|
||||||
|
token::{self, Token},
|
||||||
|
utils, LexResult,
|
||||||
|
};
|
||||||
|
|
||||||
/// Function to scan a number
|
/// Function to scan a number
|
||||||
///
|
///
|
||||||
/// This function assumes that the character at `start_pos` is a number [0-9],
|
/// This function assumes that the character at `start_pos` is a number [0-9],
|
||||||
/// if not it will panic
|
/// if not it will panic
|
||||||
pub fn scan(chars: &Vec<char>, start_pos: usize) -> LexResult {
|
pub fn scan(chars: &Vec<char>, start_pos: usize) -> LexResult {
|
||||||
@ -12,35 +15,29 @@ pub fn scan(chars: &Vec<char>, start_pos: usize) -> LexResult {
|
|||||||
// Test if the input contains a hex number
|
// Test if the input contains a hex number
|
||||||
(Some(c1), Some(c2)) if *c1 == '0' && (*c2 == 'x' || *c2 == 'X') => {
|
(Some(c1), Some(c2)) if *c1 == '0' && (*c2 == 'x' || *c2 == 'X') => {
|
||||||
scan_hex(chars, start_pos + 2, String::from("0x"))
|
scan_hex(chars, start_pos + 2, String::from("0x"))
|
||||||
},
|
}
|
||||||
// Scan decimal/double/scientific otherwise
|
// Scan decimal/double/scientific otherwise
|
||||||
_ => scan_decimal(chars, start_pos, String::from(""))
|
_ => scan_decimal(chars, start_pos, String::from("")),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Recursively scans an integer. If a dot `.` is found, scans a double,
|
/// Recursively scans an integer. If a dot `.` is found, scans a double,
|
||||||
/// if a `e` is found, scans a number in scientific notation
|
/// if a `e` is found, scans a number in scientific notation
|
||||||
fn scan_decimal(chars: &Vec<char>, start_pos: usize, current: String) -> LexResult {
|
fn scan_decimal(chars: &Vec<char>, start_pos: usize, current: String) -> LexResult {
|
||||||
match chars.get(start_pos) {
|
match chars.get(start_pos) {
|
||||||
Some(c) if *c == '.' => {
|
Some(c) if *c == '.' => scan_double(chars, start_pos + 1, utils::str_append(current, *c)),
|
||||||
scan_double(chars, start_pos + 1, utils::str_append(current, *c))
|
|
||||||
},
|
|
||||||
Some(c) if *c == 'e' => {
|
Some(c) if *c == 'e' => {
|
||||||
scan_scientific(chars, start_pos + 1, utils::str_append(current, *c))
|
scan_scientific(chars, start_pos + 1, utils::str_append(current, *c))
|
||||||
},
|
}
|
||||||
Some(c) if utils::is_digit(*c) => {
|
Some(c) if utils::is_digit(*c) => {
|
||||||
scan_decimal(chars, start_pos + 1, utils::str_append(current, *c))
|
scan_decimal(chars, start_pos + 1, utils::str_append(current, *c))
|
||||||
},
|
|
||||||
_ => {
|
|
||||||
LexResult::Some(token::new_number(current, start_pos as i32), start_pos)
|
|
||||||
}
|
}
|
||||||
|
_ => LexResult::Some(token::new_number(current, start_pos as i32), start_pos),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Recursively scans a hex number
|
/// Recursively scans a hex number
|
||||||
///
|
///
|
||||||
/// This function expects the following on the first call:
|
/// This function expects the following on the first call:
|
||||||
/// - The char at `start_pos` is a value between [0-9a-fA-F]. If not, will return an error.
|
/// - The char at `start_pos` is a value between [0-9a-fA-F]. If not, will return an error.
|
||||||
/// - `current == "0x"`. If not will return an incorrect value, or panic.
|
/// - `current == "0x"`. If not will return an incorrect value, or panic.
|
||||||
@ -49,52 +46,45 @@ fn scan_hex(chars: &Vec<char>, start_pos: usize, current: String) -> LexResult {
|
|||||||
Some(c) if utils::is_hex_digit(*c) => {
|
Some(c) if utils::is_hex_digit(*c) => {
|
||||||
let (t, next) = scan_hex_digits(chars, start_pos + 1, utils::str_append(current, *c));
|
let (t, next) = scan_hex_digits(chars, start_pos + 1, utils::str_append(current, *c));
|
||||||
LexResult::Some(t, next)
|
LexResult::Some(t, next)
|
||||||
},
|
}
|
||||||
_ => LexResult::Err(String::from("Tried to scan an incomplete hex value"))
|
_ => LexResult::Err(String::from("Tried to scan an incomplete hex value")),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Scans a floating point number, with or without an exponent
|
/// Scans a floating point number, with or without an exponent
|
||||||
///
|
///
|
||||||
/// This function expects the following:
|
/// This function expects the following:
|
||||||
/// - `start_pos` is the position after the dot. E.g., if the input is `3.22` then `start_pos == 2`.
|
/// - `start_pos` is the position after the dot. E.g., if the input is `3.22` then `start_pos == 2`.
|
||||||
///
|
///
|
||||||
/// Returns a syntax error if the char at `start_pos` is not a value between [0-9]
|
/// Returns a syntax error if the char at `start_pos` is not a value between [0-9]
|
||||||
fn scan_double(chars: &Vec<char>, start_pos: usize, current: String) -> LexResult {
|
fn scan_double(chars: &Vec<char>, start_pos: usize, current: String) -> LexResult {
|
||||||
match chars.get(start_pos) {
|
match chars.get(start_pos) {
|
||||||
Some(c) if utils::is_digit(*c) => {
|
Some(c) if utils::is_digit(*c) => scan_double_impl(chars, start_pos, current),
|
||||||
scan_double_impl(chars, start_pos, current)
|
Some(_) => LexResult::Err(String::from(
|
||||||
},
|
"The character after the dot when scanning a double is not a number.",
|
||||||
Some(_) => {
|
)),
|
||||||
LexResult::Err(String::from("The character after the dot when scanning a double is not a number."))
|
_ => LexResult::Err(String::from("EOF when scanning a double number.")),
|
||||||
},
|
|
||||||
_ => LexResult::Err(String::from("EOF when scanning a double number."))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Implementation of scan_double
|
// Implementation of scan_double
|
||||||
fn scan_double_impl(chars: &Vec<char>, start_pos: usize, current: String) -> LexResult {
|
fn scan_double_impl(chars: &Vec<char>, start_pos: usize, current: String) -> LexResult {
|
||||||
match chars.get(start_pos) {
|
match chars.get(start_pos) {
|
||||||
Some(c) if utils::is_digit(*c) => {
|
Some(c) if utils::is_digit(*c) => {
|
||||||
scan_double_impl(chars, start_pos + 1, utils::str_append(current, *c))
|
scan_double_impl(chars, start_pos + 1, utils::str_append(current, *c))
|
||||||
},
|
}
|
||||||
Some(c) if *c == 'e' => {
|
Some(c) if *c == 'e' => {
|
||||||
scan_scientific(chars, start_pos + 1, utils::str_append(current, *c))
|
scan_scientific(chars, start_pos + 1, utils::str_append(current, *c))
|
||||||
}
|
}
|
||||||
_ => {
|
_ => LexResult::Some(token::new_number(current, start_pos as i32), start_pos),
|
||||||
LexResult::Some(token::new_number(current, start_pos as i32), start_pos)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Scans a double in scientific notation
|
/// Scans a double in scientific notation
|
||||||
///
|
///
|
||||||
/// This function expects the following:
|
/// This function expects the following:
|
||||||
/// - `start_pos` is the position after the `e`. E.g., if the input is `3e+10` then `start_pos == 2`
|
/// - `start_pos` is the position after the `e`. E.g., if the input is `3e+10` then `start_pos == 2`
|
||||||
///
|
///
|
||||||
/// Returns a syntax error if:
|
/// Returns a syntax error if:
|
||||||
/// - The char at `start_pos` is not `+` or `-`
|
/// - The char at `start_pos` is not `+` or `-`
|
||||||
/// - The char at `start_pos + 1` is not between [0-9]
|
/// - The char at `start_pos + 1` is not between [0-9]
|
||||||
@ -107,36 +97,33 @@ fn scan_scientific(chars: &Vec<char>, start_pos: usize, current: String) -> LexR
|
|||||||
let new_value = format!("{}{}{}", current, *c1, *c2);
|
let new_value = format!("{}{}{}", current, *c1, *c2);
|
||||||
let (t, next) = scan_digits(chars, start_pos + 2, new_value);
|
let (t, next) = scan_digits(chars, start_pos + 2, new_value);
|
||||||
LexResult::Some(t, next)
|
LexResult::Some(t, next)
|
||||||
},
|
}
|
||||||
_ => LexResult::Err(String::from("The characters after 'e' are not + or -, or are not followed by a number"))
|
_ => LexResult::Err(String::from(
|
||||||
|
"The characters after 'e' are not + or -, or are not followed by a number",
|
||||||
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Scans chars between [0-9], returns when none is found
|
/// Scans chars between [0-9], returns when none is found
|
||||||
fn scan_digits(chars: &Vec<char>, start_pos: usize, current: String) -> (Token, usize) {
|
fn scan_digits(chars: &Vec<char>, start_pos: usize, current: String) -> (Token, usize) {
|
||||||
match chars.get(start_pos) {
|
match chars.get(start_pos) {
|
||||||
Some(c) if utils::is_digit(*c) => {
|
Some(c) if utils::is_digit(*c) => {
|
||||||
scan_digits(chars, start_pos + 1, utils::str_append(current, *c))
|
scan_digits(chars, start_pos + 1, utils::str_append(current, *c))
|
||||||
},
|
}
|
||||||
_ => (token::new_number(current, start_pos as i32), start_pos)
|
_ => (token::new_number(current, start_pos as i32), start_pos),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Scans chars between [0-9a-fA-F], returns when none is found
|
/// Scans chars between [0-9a-fA-F], returns when none is found
|
||||||
fn scan_hex_digits(chars: &Vec<char>, start_pos: usize, current: String) -> (Token, usize) {
|
fn scan_hex_digits(chars: &Vec<char>, start_pos: usize, current: String) -> (Token, usize) {
|
||||||
match chars.get(start_pos) {
|
match chars.get(start_pos) {
|
||||||
Some(c) if utils::is_hex_digit(*c) => {
|
Some(c) if utils::is_hex_digit(*c) => {
|
||||||
scan_hex_digits(chars, start_pos + 1, utils::str_append(current, *c))
|
scan_hex_digits(chars, start_pos + 1, utils::str_append(current, *c))
|
||||||
},
|
}
|
||||||
_ => (token::new_number(current, start_pos as i32), start_pos)
|
_ => (token::new_number(current, start_pos as i32), start_pos),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::lexic::token::TokenType;
|
use crate::lexic::token::TokenType;
|
||||||
@ -153,30 +140,34 @@ mod tests {
|
|||||||
let start_pos = 0;
|
let start_pos = 0;
|
||||||
|
|
||||||
if let LexResult::Some(token, next) = scan(&input, start_pos) {
|
if let LexResult::Some(token, next) = scan(&input, start_pos) {
|
||||||
assert_eq!(3, next);
|
assert_eq!(3, next);
|
||||||
assert_eq!(TokenType::Number, token.token_type);
|
assert_eq!(TokenType::Number, token.token_type);
|
||||||
assert_eq!("123", token.value);
|
assert_eq!("123", token.value);
|
||||||
} else {panic!()}
|
} else {
|
||||||
|
panic!()
|
||||||
|
}
|
||||||
|
|
||||||
let input = str_to_vec("0123 ");
|
let input = str_to_vec("0123 ");
|
||||||
let start_pos = 0;
|
let start_pos = 0;
|
||||||
|
|
||||||
if let LexResult::Some(token, next) = scan(&input, start_pos) {
|
if let LexResult::Some(token, next) = scan(&input, start_pos) {
|
||||||
assert_eq!(4, next);
|
assert_eq!(4, next);
|
||||||
assert_eq!(TokenType::Number, token.token_type);
|
assert_eq!(TokenType::Number, token.token_type);
|
||||||
assert_eq!("0123", token.value);
|
assert_eq!("0123", token.value);
|
||||||
} else {panic!()}
|
} else {
|
||||||
|
panic!()
|
||||||
|
}
|
||||||
|
|
||||||
let input = str_to_vec(" 123456 789");
|
let input = str_to_vec(" 123456 789");
|
||||||
let start_pos = 2;
|
let start_pos = 2;
|
||||||
|
|
||||||
if let LexResult::Some(token, next) = scan(&input, start_pos) {
|
if let LexResult::Some(token, next) = scan(&input, start_pos) {
|
||||||
assert_eq!(8, next);
|
assert_eq!(8, next);
|
||||||
assert_eq!(TokenType::Number, token.token_type);
|
assert_eq!(TokenType::Number, token.token_type);
|
||||||
assert_eq!("123456", token.value);
|
assert_eq!("123456", token.value);
|
||||||
} else {panic!()}
|
} else {
|
||||||
|
panic!()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Should not scan whitespace after the number
|
// Should not scan whitespace after the number
|
||||||
@ -186,10 +177,12 @@ mod tests {
|
|||||||
let start_pos = 0;
|
let start_pos = 0;
|
||||||
|
|
||||||
if let LexResult::Some(token, next) = scan(&input, start_pos) {
|
if let LexResult::Some(token, next) = scan(&input, start_pos) {
|
||||||
assert_eq!(3, next);
|
assert_eq!(3, next);
|
||||||
assert_eq!(TokenType::Number, token.token_type);
|
assert_eq!(TokenType::Number, token.token_type);
|
||||||
assert_eq!("123", token.value);
|
assert_eq!("123", token.value);
|
||||||
} else {panic!()}
|
} else {
|
||||||
|
panic!()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -198,20 +191,23 @@ mod tests {
|
|||||||
let start_pos = 0;
|
let start_pos = 0;
|
||||||
|
|
||||||
if let LexResult::Some(token, next) = scan(&input, start_pos) {
|
if let LexResult::Some(token, next) = scan(&input, start_pos) {
|
||||||
assert_eq!(4, next);
|
assert_eq!(4, next);
|
||||||
assert_eq!(TokenType::Number, token.token_type);
|
assert_eq!(TokenType::Number, token.token_type);
|
||||||
assert_eq!("0x20", token.value);
|
assert_eq!("0x20", token.value);
|
||||||
} else {panic!()}
|
} else {
|
||||||
|
panic!()
|
||||||
|
}
|
||||||
|
|
||||||
let input = str_to_vec(" 0Xff23DA ");
|
let input = str_to_vec(" 0Xff23DA ");
|
||||||
let start_pos = 4;
|
let start_pos = 4;
|
||||||
|
|
||||||
if let LexResult::Some(token, next) = scan(&input, start_pos) {
|
if let LexResult::Some(token, next) = scan(&input, start_pos) {
|
||||||
assert_eq!(12, next);
|
assert_eq!(12, next);
|
||||||
assert_eq!(TokenType::Number, token.token_type);
|
assert_eq!(TokenType::Number, token.token_type);
|
||||||
assert_eq!("0xff23DA", token.value);
|
assert_eq!("0xff23DA", token.value);
|
||||||
} else {panic!()}
|
} else {
|
||||||
|
panic!()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Should not scan an incomplete hex value
|
// Should not scan an incomplete hex value
|
||||||
@ -225,13 +221,14 @@ mod tests {
|
|||||||
_ => panic!(),
|
_ => panic!(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
let input = str_to_vec("0 x20 ");
|
let input = str_to_vec("0 x20 ");
|
||||||
let start_pos = 0;
|
let start_pos = 0;
|
||||||
if let LexResult::Some(token, _) = scan(&input, start_pos) {
|
if let LexResult::Some(token, _) = scan(&input, start_pos) {
|
||||||
assert_eq!(TokenType::Number, token.token_type);
|
assert_eq!(TokenType::Number, token.token_type);
|
||||||
assert_eq!("0", token.value);
|
assert_eq!("0", token.value);
|
||||||
} else {panic!()}
|
} else {
|
||||||
|
panic!()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Should not scan a hex value if it doesn't start with 0x
|
// Should not scan a hex value if it doesn't start with 0x
|
||||||
@ -240,9 +237,11 @@ mod tests {
|
|||||||
let input = str_to_vec("1x20");
|
let input = str_to_vec("1x20");
|
||||||
let start_pos = 0;
|
let start_pos = 0;
|
||||||
if let LexResult::Some(token, _) = scan(&input, start_pos) {
|
if let LexResult::Some(token, _) = scan(&input, start_pos) {
|
||||||
assert_eq!(TokenType::Number, token.token_type);
|
assert_eq!(TokenType::Number, token.token_type);
|
||||||
assert_eq!("1", token.value);
|
assert_eq!("1", token.value);
|
||||||
} else {panic!()}
|
} else {
|
||||||
|
panic!()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Should scan a double
|
// Should scan a double
|
||||||
@ -251,22 +250,24 @@ mod tests {
|
|||||||
let input = str_to_vec("3.22");
|
let input = str_to_vec("3.22");
|
||||||
let start_pos = 0;
|
let start_pos = 0;
|
||||||
if let LexResult::Some(token, next) = scan(&input, start_pos) {
|
if let LexResult::Some(token, next) = scan(&input, start_pos) {
|
||||||
assert_eq!(4, next);
|
assert_eq!(4, next);
|
||||||
assert_eq!(TokenType::Number, token.token_type);
|
assert_eq!(TokenType::Number, token.token_type);
|
||||||
assert_eq!("3.22", token.value);
|
assert_eq!("3.22", token.value);
|
||||||
} else {panic!()}
|
} else {
|
||||||
|
panic!()
|
||||||
|
}
|
||||||
|
|
||||||
let input = str_to_vec("123456.7890 ");
|
let input = str_to_vec("123456.7890 ");
|
||||||
let start_pos = 0;
|
let start_pos = 0;
|
||||||
if let LexResult::Some(token, next) = scan(&input, start_pos) {
|
if let LexResult::Some(token, next) = scan(&input, start_pos) {
|
||||||
assert_eq!(11, next);
|
assert_eq!(11, next);
|
||||||
assert_eq!(TokenType::Number, token.token_type);
|
assert_eq!(TokenType::Number, token.token_type);
|
||||||
assert_eq!("123456.7890", token.value);
|
assert_eq!("123456.7890", token.value);
|
||||||
} else {panic!()}
|
} else {
|
||||||
|
panic!()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Should not scan an incomplete double
|
// Should not scan an incomplete double
|
||||||
#[test]
|
#[test]
|
||||||
fn test_double_2() {
|
fn test_double_2() {
|
||||||
@ -274,11 +275,13 @@ mod tests {
|
|||||||
let start_pos = 0;
|
let start_pos = 0;
|
||||||
|
|
||||||
match scan(&input, start_pos) {
|
match scan(&input, start_pos) {
|
||||||
LexResult::Err(reason) => assert_eq!("The character after the dot when scanning a double is not a number.", reason),
|
LexResult::Err(reason) => assert_eq!(
|
||||||
|
"The character after the dot when scanning a double is not a number.",
|
||||||
|
reason
|
||||||
|
),
|
||||||
_ => panic!(),
|
_ => panic!(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
let input = str_to_vec("322.");
|
let input = str_to_vec("322.");
|
||||||
let start_pos = 0;
|
let start_pos = 0;
|
||||||
|
|
||||||
@ -294,54 +297,65 @@ mod tests {
|
|||||||
let input = str_to_vec("1e+0");
|
let input = str_to_vec("1e+0");
|
||||||
let start_pos = 0;
|
let start_pos = 0;
|
||||||
if let LexResult::Some(token, next) = scan(&input, start_pos) {
|
if let LexResult::Some(token, next) = scan(&input, start_pos) {
|
||||||
assert_eq!("1e+0", token.value);
|
assert_eq!("1e+0", token.value);
|
||||||
assert_eq!(4, next);
|
assert_eq!(4, next);
|
||||||
assert_eq!(TokenType::Number, token.token_type);
|
assert_eq!(TokenType::Number, token.token_type);
|
||||||
} else {panic!()}
|
} else {
|
||||||
|
panic!()
|
||||||
|
}
|
||||||
|
|
||||||
let input = str_to_vec("1e-0");
|
let input = str_to_vec("1e-0");
|
||||||
let start_pos = 0;
|
let start_pos = 0;
|
||||||
if let LexResult::Some(token, next) = scan(&input, start_pos) {
|
if let LexResult::Some(token, next) = scan(&input, start_pos) {
|
||||||
assert_eq!(4, next);
|
assert_eq!(4, next);
|
||||||
assert_eq!(TokenType::Number, token.token_type);
|
assert_eq!(TokenType::Number, token.token_type);
|
||||||
assert_eq!("1e-0", token.value);
|
assert_eq!("1e-0", token.value);
|
||||||
} else {panic!()}
|
} else {
|
||||||
|
panic!()
|
||||||
|
}
|
||||||
|
|
||||||
let input = str_to_vec("0e+0");
|
let input = str_to_vec("0e+0");
|
||||||
let start_pos = 0;
|
let start_pos = 0;
|
||||||
if let LexResult::Some(token, next) = scan(&input, start_pos) {
|
if let LexResult::Some(token, next) = scan(&input, start_pos) {
|
||||||
assert_eq!(4, next);
|
assert_eq!(4, next);
|
||||||
assert_eq!(TokenType::Number, token.token_type);
|
assert_eq!(TokenType::Number, token.token_type);
|
||||||
assert_eq!("0e+0", token.value);
|
assert_eq!("0e+0", token.value);
|
||||||
} else {panic!()}
|
} else {
|
||||||
|
panic!()
|
||||||
|
}
|
||||||
|
|
||||||
let input = str_to_vec("123498790e+12349870");
|
let input = str_to_vec("123498790e+12349870");
|
||||||
let start_pos = 0;
|
let start_pos = 0;
|
||||||
if let LexResult::Some(token, next) = scan(&input, start_pos) {
|
if let LexResult::Some(token, next) = scan(&input, start_pos) {
|
||||||
assert_eq!(19, next);
|
assert_eq!(19, next);
|
||||||
assert_eq!(TokenType::Number, token.token_type);
|
assert_eq!(TokenType::Number, token.token_type);
|
||||||
assert_eq!("123498790e+12349870", token.value);
|
assert_eq!("123498790e+12349870", token.value);
|
||||||
} else {panic!()}
|
} else {
|
||||||
|
panic!()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Should scan a double with decimal part and exponent
|
// Should scan a double with decimal part and exponent
|
||||||
#[test]
|
#[test]
|
||||||
fn test_exp_2(){
|
fn test_exp_2() {
|
||||||
let input = str_to_vec("1.24e+1");
|
let input = str_to_vec("1.24e+1");
|
||||||
let start_pos = 0;
|
let start_pos = 0;
|
||||||
if let LexResult::Some(token, next) = scan(&input, start_pos) {
|
if let LexResult::Some(token, next) = scan(&input, start_pos) {
|
||||||
assert_eq!("1.24e+1", token.value);
|
assert_eq!("1.24e+1", token.value);
|
||||||
assert_eq!(7, next);
|
assert_eq!(7, next);
|
||||||
assert_eq!(TokenType::Number, token.token_type);
|
assert_eq!(TokenType::Number, token.token_type);
|
||||||
} else {panic!()}
|
} else {
|
||||||
|
panic!()
|
||||||
|
}
|
||||||
|
|
||||||
let input = str_to_vec("0.00000000000001e+1");
|
let input = str_to_vec("0.00000000000001e+1");
|
||||||
let start_pos = 0;
|
let start_pos = 0;
|
||||||
if let LexResult::Some(token, next) = scan(&input, start_pos) {
|
if let LexResult::Some(token, next) = scan(&input, start_pos) {
|
||||||
assert_eq!("0.00000000000001e+1", token.value);
|
assert_eq!("0.00000000000001e+1", token.value);
|
||||||
assert_eq!(19, next);
|
assert_eq!(19, next);
|
||||||
assert_eq!(TokenType::Number, token.token_type);
|
assert_eq!(TokenType::Number, token.token_type);
|
||||||
} else {panic!()}
|
} else {
|
||||||
|
panic!()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#[derive(PartialEq, Debug)]
|
#[derive(PartialEq, Debug, Clone)]
|
||||||
pub enum TokenType {
|
pub enum TokenType {
|
||||||
NewLine,
|
NewLine,
|
||||||
Identifier,
|
Identifier,
|
||||||
@ -52,7 +52,7 @@ pub fn new_operator(value: String, position: i32) -> Token {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_grouping_sign(value: String, position: i32, token_type: TokenType) -> Token {
|
pub fn new(value: String, position: i32, token_type: TokenType) -> Token {
|
||||||
Token {token_type, value, position}
|
Token {token_type, value, position}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user