use elmx::{Token, TokenKind::{self, *}, Lexer};
fn lex(input: &str) -> Vec<Token> {
let lexer = Lexer::new(input);
lexer.collect()
}
fn single_token(input: &str, kind: TokenKind) {
let token = Token {
literal: input,
kind,
line: 1,
column: 1,
};
assert_eq!(lex(input), vec![token]);
}
#[test]
fn tokens() {
let tests = [
("main", Ident),
("let", Let),
("in", In),
("module", Module),
("import", Import),
("exposing", Exposing),
("type", Type),
("case", Case),
("of", Of),
("=", Assign),
("->", Arrow),
(":", Colon),
("|", Pipe),
(",", Comma),
(".", Dot),
("::", DoubleColon),
("++", DoublePlus),
("-", Minus),
("%", Modulo),
("+", Plus),
("*", Multiply),
("^", Power),
("&&", And),
("not", Not),
("||", Or),
("==", Equal),
(">", Greater),
(">=", GreaterEq),
("<", Less),
("<=", LessEq),
("42", Int),
("True", True),
("False", False),
("42.0", Float),
("'#'", Char),
("\"hello\"", Str),
("(", OpenParen),
(")", CloseParen),
("[", OpenBracket),
("]", CloseBracket),
("{", OpenBrace),
("}", CloseBrace),
("\\", Backslash),
("if", If),
("then", Then),
("else", Else),
("-- this is a single line comment", SingleComment),
(r#"{- this is a multi-line comment
this is the second line
-}"#, MultiComment),
];
for (input, kind) in tests {
single_token(input, kind);
}
}
#[test]
fn dot() {
let tokens = [
Token { literal: "String", kind: Ident, line: 1, column: 1 },
Token { literal: ".", kind: Dot, line: 1, column: 7 },
Token { literal: "fromInt", kind: Ident, line: 1, column: 8 },
];
assert_eq!(lex("String.fromInt"), tokens);
}
#[test]
fn let_stmt() {
let tokens = vec![
Token { literal: "module", kind: Module, line: 1, column: 1 },
Token { literal: "Main", kind: Ident, line: 1, column: 8 },
Token { literal: "exposing", kind: Exposing, line: 1, column: 13 },
Token { literal: "(", kind: OpenParen, line: 1, column: 22 },
Token { literal: "..", kind: DoubleDot, line: 1, column: 23 },
Token { literal: ")", kind: CloseParen, line: 1, column: 25 },
Token { literal: "fizzBuzz", kind: Ident, line: 3, column: 1 },
Token { literal: ":", kind: Colon, line: 3, column: 10 },
Token { literal: "Int", kind: Ident, line: 3, column: 12 },
Token { literal: "->", kind: Arrow, line: 3, column: 16 },
Token { literal: "String", kind: Ident, line: 3, column: 19 },
Token { literal: "fizzBuzz", kind: Ident, line: 4, column: 1 },
Token { literal: "n", kind: Ident, line: 4, column: 10 },
Token { literal: "=", kind: Assign, line: 4, column: 12 },
Token { literal: "if", kind: If, line: 5, column: 5 },
Token { literal: "n", kind: Ident, line: 5, column: 8 },
Token { literal: "%", kind: Modulo, line: 5, column: 10 },
Token { literal: "3", kind: Int, line: 5, column: 12 },
Token { literal: "==", kind: Equal, line: 5, column: 14 },
Token { literal: "0", kind: Int, line: 5, column: 17 },
Token { literal: "&&", kind: And, line: 5, column: 19 },
Token { literal: "n", kind: Ident, line: 5, column: 22 },
Token { literal: "%", kind: Modulo, line: 5, column: 24 },
Token { literal: "5", kind: Int, line: 5, column: 26 },
Token { literal: "==", kind: Equal, line: 5, column: 28 },
Token { literal: "0", kind: Int, line: 5, column: 31 },
Token { literal: "then", kind: Then, line: 5, column: 33 },
Token { literal: "\"FizzBuzz\"", kind: Str, line: 6, column: 9 },
Token { literal: "else", kind: Else, line: 7, column: 5 },
Token { literal: "if", kind: If, line: 7, column: 10 },
Token { literal: "n", kind: Ident, line: 7, column: 13 },
Token { literal: "%", kind: Modulo, line: 7, column: 15 },
Token { literal: "3", kind: Int, line: 7, column: 17 },
Token { literal: "==", kind: Equal, line: 7, column: 19 },
Token { literal: "0", kind: Int, line: 7, column: 22 },
Token { literal: "then", kind: Then, line: 7, column: 24 },
Token { literal: "\"Fizz\"", kind: Str, line: 8, column: 9 },
Token { literal: "else", kind: Else, line: 9, column: 5 },
Token { literal: "if", kind: If, line: 9, column: 10 },
Token { literal: "n", kind: Ident, line: 9, column: 13 },
Token { literal: "%", kind: Modulo, line: 9, column: 15 },
Token { literal: "5", kind: Int, line: 9, column: 17 },
Token { literal: "==", kind: Equal, line: 9, column: 19 },
Token { literal: "0", kind: Int, line: 9, column: 22 },
Token { literal: "then", kind: Then, line: 9, column: 24 },
Token { literal: "\"Buzz\"", kind: Str, line: 10, column: 9 },
Token { literal: "else", kind: Else, line: 11, column: 5 },
Token { literal: "String", kind: Ident, line: 12, column: 9 },
Token { literal: ".", kind: Dot, line: 12, column: 15 },
Token { literal: "fromInt", kind: Ident, line: 12, column: 16 },
Token { literal: "n", kind: Ident, line: 12, column: 24 },
Token { literal: "main", kind: Ident, line: 14, column: 1 },
Token { literal: "=", kind: Assign, line: 14, column: 6 },
Token { literal: "let", kind: Let, line: 15, column: 5 },
Token { literal: "numbers", kind: Ident, line: 16, column: 9 },
Token { literal: "=", kind: Assign, line: 16, column: 17 },
Token { literal: "List", kind: Ident, line: 16, column: 19 },
Token { literal: ".", kind: Dot, line: 16, column: 23 },
Token { literal: "range", kind: Ident, line: 16, column: 24 },
Token { literal: "1", kind: Int, line: 16, column: 30 },
Token { literal: "100", kind: Int, line: 16, column: 32 },
Token { literal: "results", kind: Ident, line: 17, column: 9 },
Token { literal: "=", kind: Assign, line: 17, column: 17 },
Token { literal: "List", kind: Ident, line: 17, column: 19 },
Token { literal: ".", kind: Dot, line: 17, column: 23 },
Token { literal: "map", kind: Ident, line: 17, column: 24 },
Token { literal: "fizzBuzz", kind: Ident, line: 17, column: 28 },
Token { literal: "numbers", kind: Ident, line: 17, column: 37 },
Token { literal: "in", kind: In, line: 18, column: 5 },
Token { literal: "List", kind: Ident, line: 19, column: 5 },
Token { literal: ".", kind: Dot, line: 19, column: 9 },
Token { literal: "foldl", kind: Ident, line: 19, column: 10 },
Token { literal: "(", kind: OpenParen, line: 19, column: 16 },
Token { literal: "\\", kind: Backslash, line: 19, column: 17 },
Token { literal: "line", kind: Ident, line: 19, column: 18 },
Token { literal: "acc", kind: Ident, line: 19, column: 23 },
Token { literal: "->", kind: Arrow, line: 19, column: 27 },
Token { literal: "acc", kind: Ident, line: 19, column: 30 },
Token { literal: "++", kind: DoublePlus, line: 19, column: 34 },
Token { literal: "line", kind: Ident, line: 19, column: 37 },
Token { literal: "++", kind: DoublePlus, line: 19, column: 42 },
Token { literal: "\"\\n\"", kind: Str, line: 19, column: 45 },
Token { literal: ")", kind: CloseParen, line: 19, column: 49 },
Token { literal: "\"\"", kind: Str, line: 19, column: 51 },
Token { literal: "results", kind: Ident, line: 19, column: 54 },
Token { literal: "|>", kind: Pipeline, line: 19, column: 62 },
Token { literal: "Debug", kind: Ident, line: 19, column: 65 },
Token { literal: ".", kind: Dot, line: 19, column: 70 },
Token { literal: "log", kind: Ident, line: 19, column: 71 },
Token { literal: "\"FizzBuzz Output\"", kind: Str, line: 19, column: 75 },
];
let lexed_tokens = lex(include_str!("Main.elm"));
assert_eq!(tokens.len(), lexed_tokens.len());
for (token, lexed_token) in tokens.into_iter().zip(lexed_tokens) {
assert_eq!(token, lexed_token);
}
}