use core::fmt::Debug;
use core::marker::PhantomData;
use crate::ctor::Ctor;
use crate::ctor::Handler;
use crate::ctx::Match;
use crate::debug_ctor_beg;
use crate::debug_ctor_reval;
use crate::debug_ctor_stage;
use crate::debug_regex_beg;
use crate::debug_regex_reval;
use crate::debug_regex_stage;
use crate::err::Error;
use crate::regex::Regex;
use crate::regex::impl_not_for_regex;
use crate::span::Span;
pub struct LongestTokenMatch<C, L, R> {
left: L,
right: R,
marker: PhantomData<C>,
}
impl_not_for_regex!(LongestTokenMatch<C, L, R>);
impl<C, L, R> Debug for LongestTokenMatch<C, L, R>
where
L: Debug,
R: Debug,
{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("LongestTokenMatch")
.field("left", &self.left)
.field("right", &self.right)
.finish()
}
}
impl<C, L, R> Default for LongestTokenMatch<C, L, R>
where
L: Default,
R: Default,
{
fn default() -> Self {
Self {
left: Default::default(),
right: Default::default(),
marker: Default::default(),
}
}
}
impl<C, L, R> Clone for LongestTokenMatch<C, L, R>
where
L: Clone,
R: Clone,
{
fn clone(&self) -> Self {
Self {
left: self.left.clone(),
right: self.right.clone(),
marker: self.marker,
}
}
}
impl<C, L, R> Copy for LongestTokenMatch<C, L, R>
where
L: Copy,
R: Copy,
{
}
impl<C, L, R> LongestTokenMatch<C, L, R> {
pub const fn new(pat1: L, pat2: R) -> Self {
Self {
left: pat1,
right: pat2,
marker: PhantomData,
}
}
pub const fn left(&self) -> &L {
&self.left
}
pub const fn left_mut(&mut self) -> &mut L {
&mut self.left
}
pub const fn right(&self) -> &R {
&self.right
}
pub const fn right_mut(&mut self) -> &mut R {
&mut self.right
}
pub fn set_left(&mut self, left: L) -> &mut Self {
self.left = left;
self
}
pub fn set_right(&mut self, right: R) -> &mut Self {
self.right = right;
self
}
}
impl<'a, C, L, R, O, H> Ctor<C, O, H> for LongestTokenMatch<C, L, R>
where
L: Ctor<C, O, H>,
R: Ctor<C, O, H>,
C: Match<'a>,
H: Handler<C>,
{
#[inline(always)]
fn construct(&self, ctx: &mut C, func: &mut H) -> Result<O, Error> {
let offset = ctx.offset();
debug_ctor_beg!("LongestTokenMatch", offset);
let l = debug_ctor_stage!("LongestTokenMatch", "l", self.left.construct(ctx, func));
let off_l = ctx.offset();
ctx.set_offset(offset);
let r = debug_ctor_stage!("LongestTokenMatch", "r", self.right.construct(ctx, func));
let off_r = ctx.offset();
let ret = match (l, r) {
(Ok(l), Ok(r)) => Ok(if off_l >= off_r {
(off_l, l)
} else {
(off_r, r)
}),
(Ok(l), Err(_)) => Ok((off_l, l)),
(Err(_), Ok(r)) => Ok((off_r, r)),
(Err(_), Err(r)) => Err(r),
};
ctx.set_offset(ret.as_ref().map(|v| v.0).unwrap_or(offset));
let ret = ret.map(|v| v.1);
debug_ctor_reval!("LongestTokenMatch", offset, ctx.offset(), ret.is_ok());
ret
}
}
impl<'a, C, L, R> Regex<C> for LongestTokenMatch<C, L, R>
where
L: Regex<C>,
R: Regex<C>,
C: Match<'a>,
{
#[inline(always)]
fn try_parse(&self, ctx: &mut C) -> Result<Span, Error> {
let offset = ctx.offset();
debug_regex_beg!("LongestTokenMatch", offset);
let l = debug_regex_stage!("LongestTokenMatch", "l", ctx.try_mat(&self.left));
ctx.set_offset(offset);
let r = debug_regex_stage!("LongestTokenMatch", "r", ctx.try_mat(&self.right));
let ret = match (l, r) {
(Ok(l), Ok(r)) => Ok(if l.len() >= r.len() { l } else { r }),
(Ok(l), Err(_)) => Ok(l),
(Err(_), Ok(r)) => Ok(r),
(Err(_), Err(r)) => Err(r),
};
ctx.set_offset(offset + ret.map(|v| v.len()).unwrap_or_default());
debug_regex_reval!("LongestTokenMatch", ret)
}
}