lualexer 0.1.2

Read Lua code and produce tokens
Documentation
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);