use super::*; macro_rules! lex { (type ($($t:tt)*), $expected:expr) => { let token = Lexer::new(stringify!($($t)*)).scan().expect(stringify!($($t:tt)* should yield a valid token)); assert_eq!(token.kind, $expected); }; (str $t:literal, $expected:expr) => { let token = Lexer::new($t).scan().expect(stringify!($t:tt should yield a valid token)); assert_eq!(token.kind, $expected); }; ({ $($t:tt)* }) => { Lexer::new(stringify!($($t)*)) }; } #[test] fn ascii_char() { lex!(type ('A'), TokenKind::Char('A')); // 'A' should be a valid char lex!(type ('\x1b'), TokenKind::Char('\x1b')); // '\\x1b' should be a valid char } #[test] fn unicode_escape_char() { lex!(type ('\u{1f988}'), TokenKind::Char('🦈')); // '\\u{1f988}' should be a valid 🦈 } #[test] fn number_with_base() { lex!(type (0), TokenKind::Number(0, 10)); // 0 should be a 16-bit base-10 number lex!(type (42069), TokenKind::Number(42069, 10)); // 42069 should be a 16-bit base-10 number lex!(type (0x420), TokenKind::Number(0x420, 16)); // 0x420 should be a 16-bit base-16 number lex!(type (0d100), TokenKind::Number(100, 10)); // 0d100 should be a 16-bit base-10 number lex!(type (0o100), TokenKind::Number(64, 8)); // 0o100 should be a 16-bit base-8 number lex!(type (0b100), TokenKind::Number(4, 2)); // 0b100 should be a 16-bit base-8 number } #[test] fn no_operand_emulated() { lex!(type (nop), TokenKind::NoEm(NoEm::Nop)); // nop should be a valid NoEm lex!(type (ret), TokenKind::NoEm(NoEm::Ret)); // ret should be a valid NoEm lex!(type (clrc), TokenKind::NoEm(NoEm::Clrc)); // clrc should be a valid NoEm lex!(type (clrz), TokenKind::NoEm(NoEm::Clrz)); // clrz should be a valid NoEm lex!(type (clrn), TokenKind::NoEm(NoEm::Clrn)); // clrn should be a valid NoEm lex!(type (setc), TokenKind::NoEm(NoEm::Setc)); // setc should be a valid NoEm lex!(type (setz), TokenKind::NoEm(NoEm::Setz)); // setz should be a valid NoEm lex!(type (setn), TokenKind::NoEm(NoEm::Setn)); // setn should be a valid NoEm lex!(type (dint), TokenKind::NoEm(NoEm::Dint)); // dint should be a valid NoEm lex!(type (eint), TokenKind::NoEm(NoEm::Eint)); // eint should be a valid NoEm } #[test] fn br() { lex!(type (br), TokenKind::Special(Special::Br)); } #[test] fn one_operand_emulated() { lex!(type (pop), TokenKind::OneEm(OneEm::Pop)); lex!(type (rla), TokenKind::OneEm(OneEm::Rla)); lex!(type (rlc), TokenKind::OneEm(OneEm::Rlc)); lex!(type (inv), TokenKind::OneEm(OneEm::Inv)); lex!(type (clr), TokenKind::OneEm(OneEm::Clr)); lex!(type (tst), TokenKind::OneEm(OneEm::Tst)); lex!(type (dec), TokenKind::OneEm(OneEm::Dec)); lex!(type (decd), TokenKind::OneEm(OneEm::Decd)); lex!(type (inc), TokenKind::OneEm(OneEm::Inc)); lex!(type (incd), TokenKind::OneEm(OneEm::Incd)); lex!(type (adc), TokenKind::OneEm(OneEm::Adc)); lex!(type (dadc), TokenKind::OneEm(OneEm::Dadc)); lex!(type (sbc), TokenKind::OneEm(OneEm::Sbc)); } #[test] fn one_operand() { lex!(type (rrc), TokenKind::OneArg(OneArg::Rrc)); lex!(type (swpb), TokenKind::OneArg(OneArg::Swpb)); lex!(type (rra), TokenKind::OneArg(OneArg::Rra)); lex!(type (sxt), TokenKind::OneArg(OneArg::Sxt)); lex!(type (push), TokenKind::OneArg(OneArg::Push)); lex!(type (call), TokenKind::OneArg(OneArg::Call)); lex!(type (reti), TokenKind::OneArg(OneArg::Reti)); } #[test] fn two_operand() { lex!(type (mov), TokenKind::TwoArg(TwoArg::Mov)); lex!(type (add), TokenKind::TwoArg(TwoArg::Add)); lex!(type (addc), TokenKind::TwoArg(TwoArg::Addc)); lex!(type (subc), TokenKind::TwoArg(TwoArg::Subc)); lex!(type (sub), TokenKind::TwoArg(TwoArg::Sub)); lex!(type (cmp), TokenKind::TwoArg(TwoArg::Cmp)); lex!(type (dadd), TokenKind::TwoArg(TwoArg::Dadd)); lex!(type (bit), TokenKind::TwoArg(TwoArg::Bit)); lex!(type (bic), TokenKind::TwoArg(TwoArg::Bic)); lex!(type (bis), TokenKind::TwoArg(TwoArg::Bis)); lex!(type (xor), TokenKind::TwoArg(TwoArg::Xor)); lex!(type (and), TokenKind::TwoArg(TwoArg::And)); } #[test] fn jump() { lex!(type (jne), TokenKind::Jump(Jump::Jne)); lex!(type (jnz), TokenKind::Jump(Jump::Jnz)); lex!(type (jeq), TokenKind::Jump(Jump::Jeq)); lex!(type (jz), TokenKind::Jump(Jump::Jz)); lex!(type (jnc), TokenKind::Jump(Jump::Jnc)); lex!(type (jlo), TokenKind::Jump(Jump::Jlo)); lex!(type (jc), TokenKind::Jump(Jump::Jc)); lex!(type (jhs), TokenKind::Jump(Jump::Jhs)); lex!(type (jn), TokenKind::Jump(Jump::Jn)); lex!(type (jge), TokenKind::Jump(Jump::Jge)); lex!(type (jl), TokenKind::Jump(Jump::Jl)); lex!(type (jmp), TokenKind::Jump(Jump::Jmp)); } #[test] fn registers() { lex!(type (pc), TokenKind::Reg(Reg::PC)); lex!(type (sp), TokenKind::Reg(Reg::SP)); lex!(type (sr), TokenKind::Reg(Reg::SR)); lex!(type (cg), TokenKind::Reg(Reg::CG)); lex!(type (r0), TokenKind::Reg(Reg::PC)); lex!(type (r1), TokenKind::Reg(Reg::SP)); lex!(type (r2), TokenKind::Reg(Reg::SR)); lex!(type (r3), TokenKind::Reg(Reg::CG)); lex!(type (r4), TokenKind::Reg(Reg::R4)); lex!(type (r5), TokenKind::Reg(Reg::R5)); lex!(type (r6), TokenKind::Reg(Reg::R6)); lex!(type (r7), TokenKind::Reg(Reg::R7)); lex!(type (r8), TokenKind::Reg(Reg::R8)); lex!(type (r9), TokenKind::Reg(Reg::R9)); lex!(type (r10), TokenKind::Reg(Reg::R10)); lex!(type (r11), TokenKind::Reg(Reg::R11)); lex!(type (r12), TokenKind::Reg(Reg::R12)); lex!(type (r13), TokenKind::Reg(Reg::R13)); lex!(type (r14), TokenKind::Reg(Reg::R14)); lex!(type (r15), TokenKind::Reg(Reg::R15)); } #[test] fn delimiters() { lex!(str "", TokenKind::Eof); lex!(str "\n", TokenKind::Newline); lex!(str "(", TokenKind::OpenParen); lex!(str ")", TokenKind::CloseParen); lex!(str "{", TokenKind::OpenCurly); lex!(str "}", TokenKind::CloseCurly); lex!(str "[", TokenKind::OpenBrace); lex!(str "]", TokenKind::CloseBrace); } #[test] fn comment() { lex!(str "; this is a comment!\n\n", TokenKind::Comment); } #[test] fn other() { // lex!(type (), TokenKind::) lex!(type (,), TokenKind::Comma); lex!(type (:), TokenKind::Colon); lex!(type (!), TokenKind::Bang); lex!(type (@), TokenKind::At); lex!(type (&), TokenKind::Amp); lex!(type (|), TokenKind::Bar); lex!(type (^), TokenKind::Caret); lex!(type (*), TokenKind::Star); lex!(type (#), TokenKind::Hash); lex!(type ($), TokenKind::Dollar); lex!(type (%), TokenKind::Percent); lex!(type (+), TokenKind::Plus); lex!(type (-), TokenKind::Minus); lex!(type (/), TokenKind::Slash); lex!(type (<<), TokenKind::Lsh); lex!(type (>>), TokenKind::Rsh); lex!(type (.directive), TokenKind::Directive); lex!(type (identifier), TokenKind::Identifier); lex!(type (.b), TokenKind::Byte); lex!(type (.w), TokenKind::Word); } #[test] fn ignores_leading_whitespace() { lex!(str " \u{a0}\t\t\t\t\t\t\t-", TokenKind::Minus); }