use lualexer::{FastLexer, FullLexer};
use lualexer::Token;
use rand::random;
macro_rules! test_single_token {
($($name:ident : $input:literal -> $token:expr),+) => {
$(
#[test]
fn $name() {
let output = lexer().parse($input);
assert_eq!(output, Ok(vec![$token]));
}
)+
};
}
macro_rules! test_lexer {
($name:ident, $tokenizer_type:ty) => {
mod $name {
use super::*;
const RANDOM_INTEGER_TEST_COUNT: usize = 10000;
const RANDOM_FLOAT_TEST_COUNT: usize = 10000;
const RANDOM_FLOAT_WITH_EXPONENT_TEST_COUNT: usize = 10000;
fn lexer() -> $tokenizer_type {
<$tokenizer_type>::new()
}
#[test]
fn empty_input_returns_no_token() {
assert_eq!(lexer().parse("").unwrap(), vec!());
}
mod numbers {
use super::*;
test_single_token!(
digit: "1" -> Token::new_number("1"),
integer: "123" -> Token::new_number("123"),
trailing_dot: "10." -> Token::new_number("10."),
single_decimal: "10.0" -> Token::new_number("10.0"),
multiple_decimal: "123.123" -> Token::new_number("123.123"),
leading_dot_float: ".123" -> Token::new_number(".123"),
digit_with_exponent: "1e10" -> Token::new_number("1e10"),
number_with_exponent: "123e456" -> Token::new_number("123e456"),
number_with_upper_exponent: "123E4" -> Token::new_number("123E4"),
float_with_exponent: "10.12e8" -> Token::new_number("10.12e8"),
trailing_dot_with_exponent: "10.e8" -> Token::new_number("10.e8"),
hex_number: "0x12" -> Token::new_number("0x12"),
hex_number_with_lowercase: "0x12a" -> Token::new_number("0x12a"),
hex_number_with_uppercase: "0x12A" -> Token::new_number("0x12A"),
hex_number_with_mixed_case: "0x1bF2A" -> Token::new_number("0x1bF2A"),
hex_with_exponent: "0x12p4" -> Token::new_number("0x12p4"),
hex_with_exponent_uppercase: "0xABP3" -> Token::new_number("0xABP3")
);
#[test]
fn test_random_integer() {
for _ in 0..RANDOM_INTEGER_TEST_COUNT {
let integer = random::<u32>();
let input = format!("{}", integer);
let output = lexer().parse(&input);
assert_eq!(output, Ok(vec![Token::new_number(&input)]));
}
}
#[test]
fn test_random_float() {
for _ in 0..RANDOM_FLOAT_TEST_COUNT {
let float = random::<u32>() as f64 + random::<f64>();
let input = format!("{}", float);
let output = lexer().parse(&input);
assert_eq!(output, Ok(vec![Token::new_number(&input)]));
}
}
#[test]
fn test_random_float_with_exponent() {
for _ in 0..RANDOM_FLOAT_WITH_EXPONENT_TEST_COUNT {
let float = random::<u32>() as f64 + random::<f64>();
let exponent = random::<u32>();
let symbol = if exponent % 2 == 0 { "e" } else { "E" };
let input = format!("{}{}{}", float, symbol, exponent);
let output = lexer().parse(&input);
assert_eq!(output, Ok(vec![Token::new_number(&input)]));
}
}
}
mod strings {
use super::*;
test_single_token!(
empty_double_quotes: r#""""# -> Token::new_string(r#""""#),
double_quoted_letters: r#""abcde""# -> Token::new_string(r#""abcde""#),
empty_single_quotes: "''" -> Token::new_string("''"),
single_quoted_letters: "'abcde'" -> Token::new_string("'abcde'"),
empty_bracket_string: "[[]]" -> Token::new_string("[[]]"),
empty_bracket_string_with_one_equal: "[=[]=]" -> Token::new_string("[=[]=]"),
empty_bracket_string_with_two_equals: "[==[]==]" -> Token::new_string("[==[]==]")
);
}
mod comments {
use super::*;
test_single_token!(
comment: "-- hello" -> Token::new_comment("-- hello"),
comment_with_brackets: "--[[ hello ]]" -> Token::new_comment("--[[ hello ]]"),
comment_with_brackets_and_equals: "--[==[ hello ]==]" -> Token::new_comment("--[==[ hello ]==]")
);
}
mod symbols {
use super::*;
test_single_token!(
minus: "-" -> Token::new_symbol("-"),
plus: "+" -> Token::new_symbol("+"),
asterisk: "*" -> Token::new_symbol("*"),
slash: "/" -> Token::new_symbol("/"),
caret: "^" -> Token::new_symbol("^"),
percent: "%" -> Token::new_symbol("%"),
hash: "#" -> Token::new_symbol("#"),
comma: "," -> Token::new_symbol(","),
dot: "." -> Token::new_symbol("."),
colon: ":" -> Token::new_symbol(":"),
semi_colon: ";" -> Token::new_symbol(";"),
opening_parenthese: "(" -> Token::new_symbol("("),
closing_parenthese: ")" -> Token::new_symbol(")"),
opening_brace: "{" -> Token::new_symbol("{"),
closing_brace: "}" -> Token::new_symbol("}"),
opening_bracket: "[" -> Token::new_symbol("["),
closing_bracket: "]" -> Token::new_symbol("]"),
equal: "=" -> Token::new_symbol("="),
less_than: "<" -> Token::new_symbol("<"),
more_than: ">" -> Token::new_symbol(">"),
double_equal: "==" -> Token::new_symbol("=="),
tilde_equal: "~=" -> Token::new_symbol("~="),
less_than_and_equal: "<=" -> Token::new_symbol("<="),
more_than_and_equal: ">=" -> Token::new_symbol(">="),
concat_dots: ".." -> Token::new_symbol(".."),
triple_dots: "..." -> Token::new_symbol("...")
);
}
}
}
}
test_lexer!(fast_tokenizer, FastLexer);
test_lexer!(full_tokenizer, FullLexer);