use derive_more::{IsVariant, TryUnwrap, Unwrap};
use crate::utils::{Spanned, cmp::Equivalent};
#[cfg(feature = "logos")]
#[cfg_attr(docsrs, doc(cfg(feature = "logos")))]
pub use logos::Logos;
#[derive(Debug, PartialEq, IsVariant, Unwrap, TryUnwrap)]
#[unwrap(ref, ref_mut)]
#[try_unwrap(ref, ref_mut)]
pub enum Lexed<'a, T: Token<'a>> {
Token(T),
Error(T::Error),
}
impl<'a, T> Clone for Lexed<'a, T>
where
T: Token<'a>,
{
#[cfg_attr(not(tarpaulin), inline(always))]
fn clone(&self) -> Self {
match self {
Self::Token(tok) => Self::Token(tok.clone()),
Self::Error(err) => Self::Error(err.clone()),
}
}
}
impl<'a, T> Copy for Lexed<'a, T>
where
T: Token<'a> + Copy,
T::Error: Copy,
{
}
impl<'a, T: Token<'a>> Lexed<'a, T> {
#[cfg_attr(not(tarpaulin), inline(always))]
pub fn lex<L>(lexer: &mut L) -> Option<Self>
where
L: super::Lexer<'a, Token = T>,
{
lexer.lex().map(|res| res.into())
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub fn lex_spanned<L>(lexer: &mut L) -> Option<Spanned<Self, L::Span>>
where
L: super::Lexer<'a, Token = T>,
{
lexer
.lex()
.map(|res| Spanned::new(lexer.span(), res.into()))
}
}
impl<'a, T: 'a> core::fmt::Display for Lexed<'a, T>
where
T: Token<'a> + core::fmt::Display,
T::Error: core::fmt::Display,
{
#[cfg_attr(not(tarpaulin), inline(always))]
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
Self::Token(tok) => ::core::fmt::Display::fmt(tok, f),
Self::Error(err) => err.fmt(f),
}
}
}
impl<'a, T: Token<'a>> From<Result<T, T::Error>> for Lexed<'a, T> {
#[cfg_attr(not(tarpaulin), inline(always))]
fn from(value: Result<T, T::Error>) -> Self {
match value {
Ok(tok) => Self::Token(tok),
Err(err) => Self::Error(err),
}
}
}
impl<'a, T: Token<'a>> From<Lexed<'a, T>> for Result<T, T::Error> {
#[cfg_attr(not(tarpaulin), inline(always))]
fn from(value: Lexed<'a, T>) -> Self {
match value {
Lexed::Token(tok) => Ok(tok),
Lexed::Error(err) => Err(err),
}
}
}
pub trait Token<'a>: Clone + core::fmt::Debug + 'a {
type Kind: Copy + core::fmt::Debug + core::fmt::Display + PartialEq + Eq + core::hash::Hash;
type Error: Clone + core::fmt::Debug;
fn kind(&self) -> Self::Kind;
fn is_trivia(&self) -> bool;
}
pub trait PunctuatorToken<'a>: Token<'a> {
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_punctuator(&self) -> bool {
self.is_dot()
|| self.is_comma()
|| self.is_colon()
|| self.is_semicolon()
|| self.is_exclamation()
|| self.is_double_quote()
|| self.is_apostrophe()
|| self.is_hash()
|| self.is_dollar()
|| self.is_percent()
|| self.is_ampersand()
|| self.is_asterisk()
|| self.is_plus()
|| self.is_minus()
|| self.is_slash()
|| self.is_backslash()
|| self.is_open_angle()
|| self.is_equal()
|| self.is_close_angle()
|| self.is_question()
|| self.is_at()
|| self.is_open_bracket()
|| self.is_close_bracket()
|| self.is_open_brace()
|| self.is_close_brace()
|| self.is_open_paren()
|| self.is_close_paren()
|| self.is_backtick()
|| self.is_pipe()
|| self.is_caret()
|| self.is_underscore()
|| self.is_tilde()
|| self.is_space()
|| self.is_tab()
|| self.is_newline()
|| self.is_carriage_return()
|| self.is_crlf()
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_dot(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_space(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_tab(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_newline(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_carriage_return(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_crlf(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_comma(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_colon(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_semicolon(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_exclamation(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_double_quote(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_apostrophe(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_hash(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_dollar(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_percent(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_ampersand(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_asterisk(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_plus(&self) -> bool {
false
}
#[doc(alias = "is_dash")]
#[doc(alias = "is_hyphen")]
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_minus(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_slash(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_backslash(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_open_angle(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_equal(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_close_angle(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_question(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_at(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_open_bracket(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_close_bracket(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_open_brace(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_close_brace(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_open_paren(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_close_paren(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_backtick(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_pipe(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_caret(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_underscore(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_tilde(&self) -> bool {
false
}
}
impl<'a, T> DelimiterToken<'a> for T
where
T: PunctuatorToken<'a>,
{
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_open_paren(&self) -> bool {
PunctuatorToken::is_open_paren(self)
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_close_paren(&self) -> bool {
PunctuatorToken::is_close_paren(self)
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_open_brace(&self) -> bool {
PunctuatorToken::is_open_brace(self)
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_close_brace(&self) -> bool {
PunctuatorToken::is_close_brace(self)
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_open_bracket(&self) -> bool {
PunctuatorToken::is_open_bracket(self)
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_close_bracket(&self) -> bool {
PunctuatorToken::is_close_bracket(self)
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_open_angle(&self) -> bool {
PunctuatorToken::is_open_angle(self)
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_close_angle(&self) -> bool {
PunctuatorToken::is_close_angle(self)
}
}
pub trait LitToken<'a>: Token<'a> {
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_literal(&self) -> bool {
self.is_numeric_literal()
|| self.is_string_literal()
|| self.is_raw_string_literal()
|| self.is_char_literal()
|| self.is_byte_literal()
|| self.is_byte_string_literal()
|| self.is_boolean_literal()
|| self.is_null_literal()
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_numeric_literal(&self) -> bool {
self.is_integer_literal() || self.is_float_literal() || self.is_hex_float_literal()
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_integer_literal(&self) -> bool {
self.is_binary_literal()
|| self.is_decimal_literal()
|| self.is_hexadecimal_literal()
|| self.is_octal_literal()
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_float_literal(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_decimal_literal(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_hexadecimal_literal(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_octal_literal(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_binary_literal(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_hex_float_literal(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_string_literal(&self) -> bool {
self.is_inline_string_literal() || self.is_multiline_string_literal()
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_inline_string_literal(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_multiline_string_literal(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_raw_string_literal(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_char_literal(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_byte_literal(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_byte_string_literal(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_boolean_literal(&self) -> bool {
self.is_true_literal() || self.is_false_literal()
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_true_literal(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_false_literal(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_null_literal(&self) -> bool {
false
}
}
pub trait IdentifierToken<'a, S>: Token<'a> {
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_identifier(&self) -> bool {
self.identifier().is_some()
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn matches_identifier<O>(&self, name: &O) -> bool
where
O: Equivalent<S>,
{
self.identifier().is_some_and(|id| name.equivalent(id))
}
fn identifier(&self) -> Option<&S> {
None
}
fn try_into_identifier(self) -> Result<S, Self>
where
Self: Sized;
}
pub trait KeywordToken<'a>: Token<'a> {
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_keyword(&self) -> bool {
self.keyword().is_some()
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn keyword(&self) -> Option<&'static str> {
None
}
}
pub trait OperatorToken<'a>: Token<'a> {
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_eq_assign(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_colon_eq_assign(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_add(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_sub(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_mul(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_div(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_mod(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_pow(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_pow_assign(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_increment(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_decrement(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_add_assign(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_sub_assign(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_mul_assign(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_div_assign(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_mod_assign(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_bitand(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_bitor(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_bitxor(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_bitand_assign(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_bitor_assign(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_bitxor_assign(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_logical_xor(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_logical_and(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_logical_or(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_logical_not(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_eq(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_strict_eq(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_ne(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_strict_ne(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_lt(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_strict_lt(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_le(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_strict_le(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_gt(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_strict_gt(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_ge(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_strict_ge(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_shl(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_shr(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_sar(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_shl_assign(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_shr_assign(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_arrow(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_fat_arrow(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_pipe_forward(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_double_colon(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_backslash_assign(&self) -> bool {
false
}
}
pub trait DelimiterToken<'a>: Token<'a> {
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_delimiter(&self) -> bool {
self.is_opening_delimiter() || self.is_closing_delimiter()
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_opening_delimiter(&self) -> bool {
self.is_open_paren() || self.is_open_brace() || self.is_open_bracket() || self.is_open_angle()
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_closing_delimiter(&self) -> bool {
self.is_close_paren()
|| self.is_close_brace()
|| self.is_close_bracket()
|| self.is_close_angle()
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_open_paren(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_close_paren(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_open_brace(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_close_brace(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_open_bracket(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_close_bracket(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_open_angle(&self) -> bool {
false
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_close_angle(&self) -> bool {
false
}
}