perl-token 0.13.2

Token definitions for Perl parser
Documentation
use perl_token::TokenKind;

#[test]
fn keyword_mapping_covers_canonical_spellings() {
    let cases = [
        ("my", TokenKind::My),
        ("our", TokenKind::Our),
        ("local", TokenKind::Local),
        ("state", TokenKind::State),
        ("sub", TokenKind::Sub),
        ("if", TokenKind::If),
        ("elsif", TokenKind::Elsif),
        ("else", TokenKind::Else),
        ("unless", TokenKind::Unless),
        ("while", TokenKind::While),
        ("until", TokenKind::Until),
        ("for", TokenKind::For),
        ("foreach", TokenKind::Foreach),
        ("return", TokenKind::Return),
        ("package", TokenKind::Package),
        ("use", TokenKind::Use),
        ("no", TokenKind::No),
        ("BEGIN", TokenKind::Begin),
        ("END", TokenKind::End),
        ("CHECK", TokenKind::Check),
        ("INIT", TokenKind::Init),
        ("UNITCHECK", TokenKind::Unitcheck),
        ("eval", TokenKind::Eval),
        ("do", TokenKind::Do),
        ("given", TokenKind::Given),
        ("when", TokenKind::When),
        ("default", TokenKind::Default),
        ("try", TokenKind::Try),
        ("catch", TokenKind::Catch),
        ("finally", TokenKind::Finally),
        ("continue", TokenKind::Continue),
        ("next", TokenKind::Next),
        ("last", TokenKind::Last),
        ("redo", TokenKind::Redo),
        ("goto", TokenKind::Goto),
        ("class", TokenKind::Class),
        ("method", TokenKind::Method),
        ("field", TokenKind::Field),
        ("format", TokenKind::Format),
        ("undef", TokenKind::Undef),
        ("defer", TokenKind::Defer),
        ("and", TokenKind::WordAnd),
        ("or", TokenKind::WordOr),
        ("not", TokenKind::WordNot),
        ("xor", TokenKind::WordXor),
        ("cmp", TokenKind::StringCompare),
    ];

    for (spelling, expected) in cases {
        assert_eq!(TokenKind::from_keyword(spelling), Some(expected), "keyword: {spelling}");
    }
}

#[test]
fn operator_mapping_covers_canonical_spellings() {
    let cases = [
        ("=", TokenKind::Assign),
        ("+", TokenKind::Plus),
        ("-", TokenKind::Minus),
        ("*", TokenKind::Star),
        ("/", TokenKind::Slash),
        ("%", TokenKind::Percent),
        ("**", TokenKind::Power),
        ("<<", TokenKind::LeftShift),
        (">>", TokenKind::RightShift),
        ("&", TokenKind::BitwiseAnd),
        ("|", TokenKind::BitwiseOr),
        ("^", TokenKind::BitwiseXor),
        ("~", TokenKind::BitwiseNot),
        ("+=", TokenKind::PlusAssign),
        ("-=", TokenKind::MinusAssign),
        ("*=", TokenKind::StarAssign),
        ("/=", TokenKind::SlashAssign),
        ("%=", TokenKind::PercentAssign),
        (".=", TokenKind::DotAssign),
        ("&=", TokenKind::AndAssign),
        ("|=", TokenKind::OrAssign),
        ("^=", TokenKind::XorAssign),
        ("**=", TokenKind::PowerAssign),
        ("<<=", TokenKind::LeftShiftAssign),
        (">>=", TokenKind::RightShiftAssign),
        ("&&=", TokenKind::LogicalAndAssign),
        ("||=", TokenKind::LogicalOrAssign),
        ("//=", TokenKind::DefinedOrAssign),
        ("==", TokenKind::Equal),
        ("!=", TokenKind::NotEqual),
        ("=~", TokenKind::Match),
        ("!~", TokenKind::NotMatch),
        ("~~", TokenKind::SmartMatch),
        ("<", TokenKind::Less),
        (">", TokenKind::Greater),
        ("<=", TokenKind::LessEqual),
        (">=", TokenKind::GreaterEqual),
        ("<=>", TokenKind::Spaceship),
        ("&&", TokenKind::And),
        ("||", TokenKind::Or),
        ("!", TokenKind::Not),
        ("//", TokenKind::DefinedOr),
        ("->", TokenKind::Arrow),
        ("=>", TokenKind::FatArrow),
        (".", TokenKind::Dot),
        ("..", TokenKind::Range),
        ("...", TokenKind::Ellipsis),
        ("++", TokenKind::Increment),
        ("--", TokenKind::Decrement),
        ("::", TokenKind::DoubleColon),
        ("?", TokenKind::Question),
        (":", TokenKind::Colon),
        ("\\", TokenKind::Backslash),
    ];

    for (spelling, expected) in cases {
        assert_eq!(TokenKind::from_operator(spelling), Some(expected), "operator: {spelling}");
    }
}

#[test]
fn delimiter_mapping_covers_canonical_spellings() {
    let cases = [
        ("(", TokenKind::LeftParen),
        (")", TokenKind::RightParen),
        ("{", TokenKind::LeftBrace),
        ("}", TokenKind::RightBrace),
        ("[", TokenKind::LeftBracket),
        ("]", TokenKind::RightBracket),
        (";", TokenKind::Semicolon),
        (",", TokenKind::Comma),
    ];

    for (spelling, expected) in cases {
        assert_eq!(TokenKind::from_delimiter(spelling), Some(expected), "delimiter: {spelling}");
    }
}

#[test]
fn sigil_mapping_covers_canonical_spellings() {
    let cases = [
        ("$", TokenKind::ScalarSigil),
        ("@", TokenKind::ArraySigil),
        ("%", TokenKind::HashSigil),
        ("&", TokenKind::SubSigil),
        ("*", TokenKind::GlobSigil),
    ];

    for (spelling, expected) in cases {
        assert_eq!(TokenKind::from_sigil(spelling), Some(expected), "sigil: {spelling}");
    }
}

#[test]
fn mappings_are_case_sensitive_and_contextual() {
    assert_eq!(TokenKind::from_keyword("My"), None);
    assert_eq!(TokenKind::from_keyword("begin"), None);
    assert_eq!(TokenKind::from_keyword("qw"), None);

    assert_eq!(TokenKind::from_operator("AND"), None);
    assert_eq!(TokenKind::from_delimiter("<"), None);
    assert_eq!(TokenKind::from_sigil("+"), None);
}

#[test]
fn category_helpers_align_with_category_method() {
    for kind in TokenKind::all() {
        assert_eq!(kind.is_keyword(), kind.category() == perl_token::TokenCategory::Keyword);
        assert_eq!(kind.is_operator(), kind.category() == perl_token::TokenCategory::Operator);
        assert_eq!(kind.is_literal(), kind.category() == perl_token::TokenCategory::Literal);
        assert_eq!(kind.is_delimiter(), kind.category() == perl_token::TokenCategory::Delimiter);
        assert_eq!(kind.is_identifier(), kind.category() == perl_token::TokenCategory::Identifier);
        assert_eq!(kind.is_special(), kind.category() == perl_token::TokenCategory::Special);
    }
}