use core::fmt::Debug;
use core::marker::PhantomData;
use crate::ctor::Ctor;
use crate::ctor::Handler;
use crate::ctor::Map;
use crate::ctx::CtxGuard;
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::map::Select0;
use crate::map::Select1;
use crate::map::SelectEq;
use crate::regex::Regex;
use crate::regex::impl_not_for_regex;
use crate::span::Span;
pub struct Then<C, L, R> {
left: L,
right: R,
marker: PhantomData<C>,
}
impl_not_for_regex!(Then<C, L, R>);
impl<C, L, R> Debug for Then<C, L, R>
where
L: Debug,
R: Debug,
{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("Then")
.field("left", &self.left)
.field("right", &self.right)
.finish()
}
}
impl<C, L, R> Default for Then<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 Then<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 Then<C, L, R>
where
L: Copy,
R: Copy,
{
}
impl<C, L, R> Then<C, L, R> {
pub const fn new(pat: L, then: R) -> Self {
Self {
left: pat,
right: then,
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, pat: L) -> &mut Self {
self.left = pat;
self
}
pub fn set_right(&mut self, then: R) -> &mut Self {
self.right = then;
self
}
pub fn _0<O>(self) -> Map<C, Self, Select0, O> {
Map::new(self, Select0)
}
pub fn _1<O>(self) -> Map<C, Self, Select1, O> {
Map::new(self, Select1)
}
pub fn _eq<I1, I2>(self) -> Map<C, Self, SelectEq, (I1, I2)> {
Map::new(self, SelectEq)
}
}
impl<'a, C, L, R, O1, O2, H> Ctor<C, (O1, O2), H> for Then<C, L, R>
where
L: Ctor<C, O1, H>,
R: Ctor<C, O2, H>,
C: Match<'a>,
H: Handler<C>,
{
#[inline(always)]
fn construct(&self, ctx: &mut C, func: &mut H) -> Result<(O1, O2), Error> {
let mut ctx = CtxGuard::new(ctx);
debug_ctor_beg!("Then", ctx.beg());
let ret =
debug_ctor_stage!("Then", "l", self.left.construct(ctx.ctx(), func)).and_then(|ret1| {
debug_ctor_stage!("Then", "r", self.right.construct(ctx.ctx(), func))
.map(|ret2| (ret1, ret2))
});
let ret = ctx.process_ret(ret);
debug_ctor_reval!("Then", ctx.beg(), ctx.end(), ret.is_ok());
ret
}
}
impl<'a, C, L, R> Regex<C> for Then<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 mut ctx = CtxGuard::new(ctx);
debug_regex_beg!("Then", ctx.beg());
let mut ret = debug_regex_stage!("Then", "l", ctx.try_mat(&self.left)?);
ret.add_assign(debug_regex_stage!("Then", "r", ctx.try_mat(&self.right)?));
debug_regex_reval!("Then", Ok(ret))
}
}
pub struct IfThen<C, L, I, R> {
left: L,
test: I,
right: R,
marker: PhantomData<C>,
}
impl_not_for_regex!(IfThen<C, L, I, R>);
impl<C, L, I, R> Debug for IfThen<C, L, I, R>
where
L: Debug,
R: Debug,
I: Debug,
{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("IfThen")
.field("left", &self.left)
.field("test", &self.test)
.field("right", &self.right)
.finish()
}
}
impl<C, L, I, R> Default for IfThen<C, L, I, R>
where
L: Default,
R: Default,
I: Default,
{
fn default() -> Self {
Self {
left: Default::default(),
test: Default::default(),
right: Default::default(),
marker: Default::default(),
}
}
}
impl<C, L, I, R> Clone for IfThen<C, L, I, R>
where
L: Clone,
R: Clone,
I: Clone,
{
fn clone(&self) -> Self {
Self {
test: self.test.clone(),
left: self.left.clone(),
right: self.right.clone(),
marker: self.marker,
}
}
}
impl<C, L, I, R> Copy for IfThen<C, L, I, R>
where
L: Copy,
R: Copy,
I: Copy,
{
}
impl<C, L, I, R> IfThen<C, L, I, R> {
pub const fn new(left: L, test: I, right: R) -> Self {
Self {
test,
left,
right,
marker: PhantomData,
}
}
pub const fn test(&self) -> &I {
&self.test
}
pub const fn test_mut(&mut self) -> &mut I {
&mut self.test
}
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_test(&mut self, test: I) -> &mut Self {
self.test = test;
self
}
pub fn set_left(&mut self, pat: L) -> &mut Self {
self.left = pat;
self
}
pub fn set_right(&mut self, then: R) -> &mut Self {
self.right = then;
self
}
pub fn _0<O>(self) -> Map<C, Self, Select0, O> {
Map::new(self, Select0)
}
pub fn _1<O>(self) -> Map<C, Self, Select1, O> {
Map::new(self, Select1)
}
pub fn _eq<I1, I2>(self) -> Map<C, Self, SelectEq, (I1, I2)> {
Map::new(self, SelectEq)
}
}
impl<'a, C, L, I, R, O1, O2, H> Ctor<C, (O1, Option<O2>), H> for IfThen<C, L, I, R>
where
L: Ctor<C, O1, H>,
R: Ctor<C, O2, H>,
I: Regex<C>,
C: Match<'a>,
H: Handler<C>,
{
#[inline(always)]
fn construct(&self, ctx: &mut C, func: &mut H) -> Result<(O1, Option<O2>), Error> {
let mut ctx = CtxGuard::new(ctx);
debug_ctor_beg!("IfThen", ctx.beg());
let l = debug_ctor_stage!("IfThen", "l", self.left.construct(ctx.ctx(), func));
let l = ctx.process_ret(l)?;
let test = {
let mut if_ctx = CtxGuard::new(ctx.ctx());
debug_ctor_stage!("IfThen", "test", if_ctx.try_mat(&self.test)).is_ok()
};
let pair = if test {
let r = debug_ctor_stage!("IfThen", "r", self.right.construct(ctx.ctx(), func));
let r = ctx.process_ret(r)?;
(l, Some(r))
} else {
(l, None)
};
debug_ctor_reval!("IfThen", ctx.beg(), ctx.end(), true);
Ok(pair)
}
}
impl<'a, C, L, I, R> Regex<C> for IfThen<C, L, I, R>
where
I: Regex<C>,
L: Regex<C>,
R: Regex<C>,
C: Match<'a>,
{
#[inline(always)]
fn try_parse(&self, ctx: &mut C) -> Result<Span, Error> {
let mut ctx = CtxGuard::new(ctx);
debug_regex_beg!("IfThen", ctx.beg());
let mut ret = debug_regex_stage!("IfThen", "l", ctx.try_mat(&self.left)?);
let span = {
let mut if_ctx = CtxGuard::new(ctx.ctx());
debug_regex_stage!("IfThen", "test", if_ctx.try_mat(&self.test))
};
if let Ok(span) = span {
ret.add_assign(span);
ret.add_assign(debug_regex_stage!("IfThen", "r", ctx.try_mat(&self.right)?));
}
debug_regex_reval!("IfThen", Ok(ret))
}
}