use super::{
token::{Token, TokenTy},
Lexer,
};
pub const TWO_ASCII_TRIVIAL_TOKENS: &[(&[u8; 2], TokenTy)] = &[
(b"->", TokenTy::SingleArrow),
(b"-=", TokenTy::MinusEq),
(b"=>", TokenTy::DoubleArrow),
(b"==", TokenTy::EqEq),
(b"&&", TokenTy::AndAnd),
(b"||", TokenTy::OrOr),
(b"<<", TokenTy::LtLt),
(b">>", TokenTy::GtGt),
(b"::", TokenTy::ColonColon),
(b"|=", TokenTy::OrEq),
(b"&=", TokenTy::AndEq),
(b":=", TokenTy::ColonEq),
(b">=", TokenTy::GtEq),
(b"<=", TokenTy::LtEq),
(b"!=", TokenTy::BangEq),
(b"%=", TokenTy::ModEq),
(b"^=", TokenTy::XorEq),
(b"*=", TokenTy::StarEq),
(b"+=", TokenTy::PlusEq),
(b"/=", TokenTy::DivEq),
];
pub const SINGLE_ASCII_CHAR_TRIVIAL_TOKENS: &[(u8, TokenTy)] = &[
(b'(', TokenTy::LeftParen),
(b')', TokenTy::RightParen),
(b'[', TokenTy::LeftBracket),
(b']', TokenTy::RightBracket),
(b'{', TokenTy::LeftCurly),
(b'}', TokenTy::RightCurly),
(b'@', TokenTy::At),
(b';', TokenTy::Semi),
(b'?', TokenTy::Question),
(b',', TokenTy::Comma),
(b'#', TokenTy::Hash),
(b'$', TokenTy::Dollar),
(b'>', TokenTy::Gt),
(b'<', TokenTy::Lt),
(b'-', TokenTy::Minus),
(b':', TokenTy::Colon),
(b'!', TokenTy::Bang),
(b'=', TokenTy::Eq),
(b'&', TokenTy::And),
(b'|', TokenTy::Or),
(b'/', TokenTy::Div),
(b'+', TokenTy::Plus),
(b'^', TokenTy::Xor),
(b'*', TokenTy::Star),
(b'%', TokenTy::Mod),
];
pub fn try_consume_trivial_token(lexer: &mut Lexer) -> Option<Token> {
let bytes_remaining: usize = lexer.bytes_remaining();
if bytes_remaining == 0 {
return None;
}
if bytes_remaining >= 2 {
let bytes: &[u8] = unsafe { lexer.remaining.as_str().as_bytes().get_unchecked(0..2) };
for (pattern, kind) in TWO_ASCII_TRIVIAL_TOKENS {
if bytes == *pattern {
return Some(unsafe { lexer.split_token_unchecked(2, *kind) });
}
}
}
let byte: &u8 = unsafe { lexer.remaining.as_str().as_bytes().get_unchecked(0) };
for (pattern, kind) in SINGLE_ASCII_CHAR_TRIVIAL_TOKENS {
if byte == pattern {
return Some(unsafe { lexer.split_token_unchecked(1, *kind) });
}
}
None
}
#[cfg(test)]
mod tests {
use super::{Lexer, TokenTy};
#[test]
fn plus_and_plus_eq_tokens() {
let mut plus = Lexer::new_test("+");
let mut plus_eq = Lexer::new_test("+=");
let plus_token = plus.next_token().unwrap();
let plus_eq_token = plus_eq.next_token().unwrap();
assert_eq!(plus.bytes_remaining(), 0);
assert_eq!(plus_eq.bytes_remaining(), 0);
assert_eq!(plus_token.variant, TokenTy::Plus);
assert_eq!(plus_eq_token.variant, TokenTy::PlusEq);
}
#[test]
fn plus_one_token() {
let mut plus_one = Lexer::new_test("+1");
let plus_token = plus_one.next_token().unwrap();
assert_eq!(plus_one.bytes_remaining(), 1);
assert_eq!(plus_token.variant, TokenTy::Plus);
assert_eq!(plus_token.fragment.len(), 1);
}
}