ferric_lexer 0.1.0

Lexer for the ferric group of langueages
Documentation
use super::*;

macro_rules! test_lexer {
    ($name:ident, $input:expr, $expected_output:expr) => {
        #[test]
        fn $name() {
            let lexer = Lexer::new($input);
            assert_eq!(lexer.lex(), $expected_output);
        }
    };
}

test_lexer!(empty, "", vec![]);

test_lexer!(plus, "+", vec![Token::Operator(Operator::Plus)]);

test_lexer!(minus, "-", vec![Token::Operator(Operator::Minus)]);

test_lexer!(multiply, "*", vec![Token::Operator(Operator::Multiply)]);

test_lexer!(divide, "/", vec![Token::Operator(Operator::Divide)]);

test_lexer!(assign, "=", vec![Token::Assign]);
test_lexer!(equal, "==", vec![Token::Operator(Operator::Equal)]);
test_lexer!(not_equal, "!=", vec![Token::Operator(Operator::NotEqual)]);
test_lexer!(open_paren, "(", vec![Token::OpenParen]);
test_lexer!(close_paren, ")", vec![Token::CloseParen]);
test_lexer!(open_brace, "{", vec![Token::OpenBrace]);
test_lexer!(close_brace, "}", vec![Token::CloseBrace]);

test_lexer!(eol, ";", vec![Token::EoL]);

test_lexer!(number, "123", vec![Token::Number(123)]);

test_lexer!(
    identifier,
    "abc",
    vec![Token::Identifier("abc".to_string())]
);

test_lexer!(
    identifier_with_number,
    "abc123",
    vec![Token::Identifier("abc123".to_string())]
);

test_lexer!(
    identifier_with_underscore,
    "abc_123",
    vec![Token::Identifier("abc_123".to_string())]
);

test_lexer!(
    complex_expr,
    "variable_name = 123",
    vec![
        Token::Identifier("variable_name".to_string()),
        Token::Assign,
        Token::Number(123)
    ]
);

test_lexer!(
    complex_expr_with_paren,
    "variable_name = (123 + 456) * 789",
    vec![
        Token::Identifier("variable_name".to_string()),
        Token::Assign,
        Token::OpenParen,
        Token::Number(123),
        Token::Operator(Operator::Plus),
        Token::Number(456),
        Token::CloseParen,
        Token::Operator(Operator::Multiply),
        Token::Number(789)
    ]
);

test_lexer!(
    complex_expr_with_paren_and_identifier,
    "variable_name = (123 + variable_name) * 789",
    vec![
        Token::Identifier("variable_name".to_string()),
        Token::Assign,
        Token::OpenParen,
        Token::Number(123),
        Token::Operator(Operator::Plus),
        Token::Identifier("variable_name".to_string()),
        Token::CloseParen,
        Token::Operator(Operator::Multiply),
        Token::Number(789)
    ]
);
test_lexer!(
    variable_definition,
    "let x = 123;",
    vec![
        Token::Keyword(Keyword::Let),
        Token::Identifier("x".to_string()),
        Token::Assign,
        Token::Number(123),
        Token::EoL
    ]
);

test_lexer!(
    if_statement,
    "if (x == 123) { x = 456; }",
    vec![
        Token::Keyword(Keyword::If),
        Token::OpenParen,
        Token::Identifier("x".to_string()),
        Token::Operator(Operator::Equal),
        Token::Number(123),
        Token::CloseParen,
        Token::OpenBrace,
        Token::Identifier("x".to_string()),
        Token::Assign,
        Token::Number(456),
        Token::EoL,
        Token::CloseBrace,
    ]
);

test_lexer!(
    equality_operator,
    "x == y",
    vec![
        Token::Identifier("x".to_string()),
        Token::Operator(Operator::Equal),
        Token::Identifier("y".to_string()),
    ]
);

test_lexer!(
    inequality_operator,
    "x != y",
    vec![
        Token::Identifier("x".to_string()),
        Token::Operator(Operator::NotEqual),
        Token::Identifier("y".to_string()),
    ]
);

test_lexer!(
    test_while,
    "while (x == 5) { let x = x + 1; }",
    vec![
        Token::Keyword(Keyword::While),
        Token::OpenParen,
        Token::Identifier("x".to_string()),
        Token::Operator(Operator::Equal),
        Token::Number(5),
        Token::CloseParen,
        Token::OpenBrace,
        Token::Keyword(Keyword::Let),
        Token::Identifier("x".to_string()),
        Token::Assign,
        Token::Identifier("x".to_string()),
        Token::Operator(Operator::Plus),
        Token::Number(1),
        Token::EoL,
        Token::CloseBrace,
    ]
);

test_lexer!(
    test_string,
    "\"Hello, World!\"",
    vec![Token::StringLiteral("Hello, World!".to_string())]
);

test_lexer!(
    test_exec,
    "exec(\"ls\")",
    vec![
        Token::BuiltInFunction(BuiltInFunction::Exec),
        Token::OpenParen,
        Token::StringLiteral("ls".to_string()),
        Token::CloseParen
    ]
);

test_lexer!(
    test_print,
    "print(\"Hello, World!\")",
    vec![
        Token::BuiltInFunction(BuiltInFunction::Print),
        Token::OpenParen,
        Token::StringLiteral("Hello, World!".to_string()),
        Token::CloseParen
    ]
);

test_lexer!(
    test_exit,
    "exit(0)",
    vec![
        Token::BuiltInFunction(BuiltInFunction::Exit),
        Token::OpenParen,
        Token::Number(0),
        Token::CloseParen
    ]
);

test_lexer!(
    test_arg,
    "arg(0)",
    vec![
        Token::BuiltInFunction(BuiltInFunction::Arg),
        Token::OpenParen,
        Token::Number(0),
        Token::CloseParen
    ]
);

test_lexer!(
    test_for,
    "for (let i = 0; i != 10; i = i + 1) { print(i); }",
    vec![
        Token::Keyword(Keyword::For),
        Token::OpenParen,
        Token::Keyword(Keyword::Let),
        Token::Identifier("i".to_string()),
        Token::Assign,
        Token::Number(0),
        Token::EoL,
        Token::Identifier("i".to_string()),
        Token::Operator(Operator::NotEqual),
        Token::Number(10),
        Token::EoL,
        Token::Identifier("i".to_string()),
        Token::Assign,
        Token::Identifier("i".to_string()),
        Token::Operator(Operator::Plus),
        Token::Number(1),
        Token::CloseParen,
        Token::OpenBrace,
        Token::BuiltInFunction(BuiltInFunction::Print),
        Token::OpenParen,
        Token::Identifier("i".to_string()),
        Token::CloseParen,
        Token::EoL,
        Token::CloseBrace,
    ]
);

test_lexer!(
    test_else,
    "if (x == 5) { print(\"Hello\"); } else { print(\"World\"); }",
    vec![
        Token::Keyword(Keyword::If),
        Token::OpenParen,
        Token::Identifier("x".to_string()),
        Token::Operator(Operator::Equal),
        Token::Number(5),
        Token::CloseParen,
        Token::OpenBrace,
        Token::BuiltInFunction(BuiltInFunction::Print),
        Token::OpenParen,
        Token::StringLiteral("Hello".to_string()),
        Token::CloseParen,
        Token::EoL,
        Token::CloseBrace,
        Token::Keyword(Keyword::Else),
        Token::OpenBrace,
        Token::BuiltInFunction(BuiltInFunction::Print),
        Token::OpenParen,
        Token::StringLiteral("World".to_string()),
        Token::CloseParen,
        Token::EoL,
        Token::CloseBrace,
    ]
);