use core::ops::{Add, AddAssign};
use crate::utils::{
CharLen, Lexeme, PositionedChar, SimpleSpan, human_display::DisplayHuman,
knowledge::LineTerminator,
};
pub type UnexpectedLineTerminator<Char, O = usize> = UnexpectedLexeme<Char, LineTerminator, O>;
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct UnexpectedLexeme<Char, Hint, O = usize> {
lexeme: Lexeme<Char, O>,
hint: Hint,
}
impl<Char, Hint, O> core::fmt::Display for UnexpectedLexeme<Char, Hint, O>
where
Char: DisplayHuman,
O: core::fmt::Display,
{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match &self.lexeme {
Lexeme::Char(pc) => write!(
f,
"unexpected character '{}' at position {}",
pc.char_ref().display(),
pc.position_ref(),
),
Lexeme::Range(span) => write!(f, "unexpected characters at {}", span,),
}
}
}
impl<Char, Hint, O> core::error::Error for UnexpectedLexeme<Char, Hint, O>
where
Char: DisplayHuman + core::fmt::Debug,
Hint: core::fmt::Debug,
O: core::fmt::Debug + core::fmt::Display,
{
}
impl<Char, Hint, O> core::ops::Deref for UnexpectedLexeme<Char, Hint, O> {
type Target = Lexeme<Char, O>;
#[cfg_attr(not(tarpaulin), inline(always))]
fn deref(&self) -> &Self::Target {
&self.lexeme
}
}
impl<Char, Hint, O> core::ops::DerefMut for UnexpectedLexeme<Char, Hint, O> {
#[cfg_attr(not(tarpaulin), inline(always))]
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.lexeme
}
}
impl<Char, O> UnexpectedLexeme<Char, LineTerminator, O> {
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn new_line(pos: O, ch: Char) -> Self {
Self::from_char(pos, ch, LineTerminator::NewLine)
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn carriage_return(pos: O, ch: Char) -> Self {
Self::from_char(pos, ch, LineTerminator::CarriageReturn)
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn carriage_return_new_line(span: SimpleSpan<O>) -> Self {
Self::from_range_const(span, LineTerminator::CarriageReturnNewLine)
}
}
impl<Char, Hint, O> UnexpectedLexeme<Char, Hint, O> {
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn new(lexeme: Lexeme<Char, O>, hint: Hint) -> Self {
Self { lexeme, hint }
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn from_char(pos: O, ch: Char, hint: Hint) -> Self {
Self::from_positioned_char(PositionedChar::with_position(ch, pos), hint)
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn from_positioned_char(pc: PositionedChar<Char, O>, hint: Hint) -> Self {
Self::new(Lexeme::Char(pc), hint)
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn from_range_const(span: SimpleSpan<O>, hint: Hint) -> Self {
Self::new(Lexeme::Range(span), hint)
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub fn from_range(span: impl Into<SimpleSpan<O>>, hint: Hint) -> Self {
Self::new(Lexeme::Range(span.into()), hint)
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn lexeme(&self) -> &Lexeme<Char, O> {
&self.lexeme
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn hint(&self) -> &Hint {
&self.hint
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn lexeme_mut(&mut self) -> &mut Lexeme<Char, O> {
&mut self.lexeme
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn hint_mut(&mut self) -> &mut Hint {
&mut self.hint
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub fn into_components(self) -> (Lexeme<Char, O>, Hint) {
(self.lexeme, self.hint)
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub fn into_lexeme(self) -> Lexeme<Char, O> {
self.lexeme
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub fn into_hint(self) -> Hint {
self.hint
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub fn span_with(&self, len_of: impl FnOnce(&Char) -> usize) -> SimpleSpan<O>
where
O: Clone + Ord,
for<'a> &'a O: Add<usize, Output = O>,
{
self.lexeme.span_with(len_of)
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub fn span(&self) -> SimpleSpan<O>
where
Char: CharLen,
O: Clone + Ord,
for<'a> &'a O: Add<usize, Output = O>,
{
self.lexeme.span()
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub fn map_char<F, NewChar>(self, f: F) -> UnexpectedLexeme<NewChar, Hint, O>
where
F: FnMut(Char) -> NewChar,
{
UnexpectedLexeme {
lexeme: self.lexeme.map(f),
hint: self.hint,
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub fn map_hint<F, NewHint>(self, f: F) -> UnexpectedLexeme<Char, NewHint, O>
where
F: FnOnce(Hint) -> NewHint,
{
UnexpectedLexeme {
lexeme: self.lexeme,
hint: f(self.hint),
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub fn map<F, NewChar, G, NewHint>(self, f: F, g: G) -> UnexpectedLexeme<NewChar, NewHint, O>
where
F: FnMut(Char) -> NewChar,
G: FnOnce(Hint) -> NewHint,
{
UnexpectedLexeme {
lexeme: self.lexeme.map(f),
hint: g(self.hint),
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub fn bump(&mut self, n: &O) -> &mut Self
where
O: for<'a> AddAssign<&'a O> + Clone,
{
self.lexeme.bump(n);
self
}
}