use core::marker::PhantomData;
use crate::{
error::token::{Leading, Repeated, Trailing},
utils::{Expected, SimpleSpan},
};
pub use unexpected_leading::*;
pub use unexpected_repeated::*;
pub use unexpected_trailing::*;
mod unexpected_leading;
mod unexpected_repeated;
mod unexpected_trailing;
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub struct UnexpectedToken<'a, T, Kind, S = SimpleSpan, Lang: ?Sized = ()> {
span: S,
found: Option<T>,
expected: Option<Expected<'a, Kind>>,
_lang: PhantomData<Lang>,
}
impl<'a, T, Kind, S, Lang: ?Sized> From<UnexpectedToken<'a, T, Kind, S, Lang>> for () {
#[cfg_attr(not(tarpaulin), inline(always))]
fn from(_: UnexpectedToken<'a, T, Kind, S, Lang>) -> Self {}
}
impl<T, Kind, S, Data> UnexpectedToken<'_, T, Kind, S, Trailing<Data>> {
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn trailing(span: S, found: T) -> Self {
Self::trailing_of(span, found)
}
}
impl<T, Kind, S, Data> UnexpectedToken<'_, T, Kind, S, Leading<Data>> {
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn leading(span: S, found: T) -> Self {
Self::leading_of(span, found)
}
}
impl<T, Kind, S, Data> UnexpectedToken<'_, T, Kind, S, Repeated<Data>> {
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn repeated(span: S, found: T) -> Self {
Self::repeated_of(span, found)
}
}
impl<T, Kind, S, Data, Lang: ?Sized> UnexpectedToken<'_, T, Kind, S, Trailing<Data, Lang>> {
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn trailing_of(span: S, found: T) -> Self {
Self::new_in(span, Some(found), None)
}
}
impl<T, Kind, S, Data, Lang: ?Sized> UnexpectedToken<'_, T, Kind, S, Leading<Data, Lang>> {
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn leading_of(span: S, found: T) -> Self {
Self::new_in(span, Some(found), None)
}
}
impl<T, Kind, S, Data, Lang: ?Sized> UnexpectedToken<'_, T, Kind, S, Repeated<Data, Lang>> {
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn repeated_of(span: S, found: T) -> Self {
Self::new_in(span, Some(found), None)
}
}
impl<'a, T, Kind, S> UnexpectedToken<'a, T, Kind, S> {
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn new(span: S) -> Self {
Self::of(span)
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn with_expected(span: S, expected: Expected<'a, Kind>) -> Self {
Self::with_expected_of(span, expected)
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn maybe_expected(span: S, expected: Option<Expected<'a, Kind>>) -> Self {
Self::maybe_expected_of(span, expected)
}
}
impl<'a, T, Kind, S, Lang: ?Sized> UnexpectedToken<'a, T, Kind, S, Lang> {
#[cfg_attr(not(tarpaulin), inline(always))]
pub(super) const fn new_in(
span: S,
found: Option<T>,
expected: Option<Expected<'a, Kind>>,
) -> Self {
Self {
span,
found,
expected,
_lang: PhantomData,
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn of(span: S) -> Self {
Self::new_in(span, None, None)
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn with_expected_of(span: S, expected: Expected<'a, Kind>) -> Self {
Self::new_in(span, None, Some(expected))
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn maybe_expected_of(span: S, expected: Option<Expected<'a, Kind>>) -> Self {
Self::new_in(span, None, expected)
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn expected_one(span: S, expected: Kind) -> Self {
Self::with_expected_of(span, Expected::one(expected))
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn expected_one_with_found(span: S, found: T, expected: Kind) -> Self {
Self::new_in(span, Some(found), Some(Expected::one(expected)))
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn expected_one_of(span: S, expected: &'static [Kind]) -> Self {
Self::with_expected_of(span, Expected::one_of(expected))
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn expected_one_of_with_found(span: S, found: T, expected: &'static [Kind]) -> Self {
Self::new_in(span, Some(found), Some(Expected::one_of(expected)))
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub fn maybe_found(mut self, found: Option<T>) -> Self {
self.found = found;
self
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub fn maybe_found_const(mut self, found: Option<T>) -> Self
where
T: Copy,
{
self.found = found;
self
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub fn with_found(mut self, found: T) -> Self {
self.found = Some(found);
self
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub fn with_found_const(mut self, found: T) -> Self
where
T: Copy,
{
self.found = Some(found);
self
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn span(&self) -> S
where
S: Copy,
{
self.span
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn span_ref(&self) -> &S {
&self.span
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn span_mut(&mut self) -> &mut S {
&mut self.span
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn found(&self) -> Option<&T> {
self.found.as_ref()
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn expected(&self) -> Option<&Expected<'a, Kind>> {
self.expected.as_ref()
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub fn bump(&mut self, offset: &S::Offset)
where
S: crate::lexer::Span,
{
self.span.bump(offset);
}
pub fn map_expected<F, Kind2>(self, f: F) -> UnexpectedToken<'a, T, Kind2, S>
where
F: FnOnce(Expected<'a, Kind>) -> Expected<'a, Kind2>,
{
UnexpectedToken {
span: self.span,
found: self.found,
expected: self.expected.map(f),
_lang: PhantomData,
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub fn into_components(self) -> (S, Option<T>, Option<Expected<'a, Kind>>) {
(self.span, self.found, self.expected)
}
}
impl<T, Kind, S, Lang: ?Sized> UnexpectedToken<'_, T, Kind, S, Lang>
where
S: crate::lexer::Span,
{
pub fn debug_fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result
where
T: core::fmt::Debug,
Kind: core::fmt::Debug,
S: core::fmt::Debug,
{
f.debug_struct("UnexpectedToken")
.field("span", &self.span)
.field("found", &self.found)
.field("expected", &self.expected)
.finish()
}
pub fn display_fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result
where
T: core::fmt::Display,
Kind: core::fmt::Display,
{
match &self.found {
Some(found) => match &self.expected {
Some(expected) => write!(f, "unexpected token '{}', expected {}", found, expected),
None => write!(f, "unexpected token '{}'", found),
},
None => match &self.expected {
Some(expected) => write!(f, "unexpected token, expected {}", expected),
None => write!(f, "unexpected token"),
},
}
}
}