use core::ops::{Add, AddAssign};
use crate::utils::{CharLen, Lexeme, PositionedChar, SimpleSpan, human_display::DisplayHuman};
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct UnknownLexeme<Char, Knowledge, O = usize> {
lexeme: Lexeme<Char, O>,
knowledge: Knowledge,
}
impl<Char, Knowledge, O> core::fmt::Display for UnknownLexeme<Char, Knowledge, 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,
"unknown character '{}' encountered at {}",
pc.char_ref().display(),
pc.position_ref(),
),
Lexeme::Range(span) => write!(f, "unknown lexeme encountered at {}", span),
}
}
}
impl<Char, Knowledge, O> core::error::Error for UnknownLexeme<Char, Knowledge, O>
where
Char: DisplayHuman + core::fmt::Debug,
Knowledge: core::fmt::Debug,
O: core::fmt::Debug + core::fmt::Display,
{
}
impl<Char, Knowledge, O> core::ops::Deref for UnknownLexeme<Char, Knowledge, O> {
type Target = Lexeme<Char, O>;
#[cfg_attr(not(tarpaulin), inline(always))]
fn deref(&self) -> &Self::Target {
&self.lexeme
}
}
impl<Char, Knowledge, O> core::ops::DerefMut for UnknownLexeme<Char, Knowledge, O> {
#[cfg_attr(not(tarpaulin), inline(always))]
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.lexeme
}
}
impl<Char, O> UnknownLexeme<Char, crate::utils::knowledge::Characters, O> {
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn unknown_characters(span: SimpleSpan<O>) -> Self {
Self::new(Lexeme::Range(span), sealed::Sealed::INIT)
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn unknown_character(pos: O, ch: Char) -> Self {
Self::from_char(pos, ch, sealed::Sealed::INIT)
}
}
impl<Char, Knowledge, O> UnknownLexeme<Char, Knowledge, O> {
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn new(lexeme: Lexeme<Char, O>, knowledge: Knowledge) -> Self {
Self { lexeme, knowledge }
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn from_char(pos: O, ch: Char, knowledge: Knowledge) -> Self {
Self::from_positioned_char(PositionedChar::with_position(ch, pos), knowledge)
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn from_positioned_char(pc: PositionedChar<Char, O>, knowledge: Knowledge) -> Self {
Self::new(Lexeme::Char(pc), knowledge)
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn from_range_const(span: SimpleSpan<O>, knowledge: Knowledge) -> Self {
Self::new(Lexeme::Range(span), knowledge)
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub fn from_range(span: impl Into<SimpleSpan<O>>, knowledge: Knowledge) -> Self {
Self::new(Lexeme::Range(span.into()), knowledge)
}
#[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 knowledge(&self) -> &Knowledge {
&self.knowledge
}
#[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 knowledge_mut(&mut self) -> &mut Knowledge {
&mut self.knowledge
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub fn into_components(self) -> (Lexeme<Char, O>, Knowledge) {
(self.lexeme, self.knowledge)
}
#[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_knowledge(self) -> Knowledge {
self.knowledge
}
#[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) -> UnknownLexeme<NewChar, Knowledge, O>
where
F: FnMut(Char) -> NewChar,
{
UnknownLexeme {
lexeme: self.lexeme.map(f),
knowledge: self.knowledge,
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub fn map_knowledge<F, NewKnowledge>(self, f: F) -> UnknownLexeme<Char, NewKnowledge, O>
where
F: FnOnce(Knowledge) -> NewKnowledge,
{
UnknownLexeme {
lexeme: self.lexeme,
knowledge: f(self.knowledge),
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub fn map<F, NewChar, G, NewKnowledge>(
self,
f: F,
g: G,
) -> UnknownLexeme<NewChar, NewKnowledge, O>
where
F: FnMut(Char) -> NewChar,
G: FnOnce(Knowledge) -> NewKnowledge,
{
UnknownLexeme {
lexeme: self.lexeme.map(f),
knowledge: g(self.knowledge),
}
}
#[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
}
}
pub trait MaybeUnknown: sealed::Sealed {}
impl<T> MaybeUnknown for T where T: sealed::Sealed {}
mod sealed {
use crate::utils::knowledge::Characters;
pub trait Sealed {
const INIT: Self;
}
impl Sealed for Characters {
const INIT: Self = Self(());
}
}