use std::marker::PhantomData;
use crate::ctx::Context;
use crate::ctx::CtxGuard;
use crate::ctx::Match;
use crate::err::Error;
use crate::neu::CRange;
use crate::re::trace;
use crate::re::trace_v;
use crate::re::Regex;
#[derive(Debug, Default, Copy)]
pub struct RegexSepOnce<C, L, S, R> {
left: L,
sep: S,
right: R,
marker: PhantomData<C>,
}
impl<C, L, S, R> Clone for RegexSepOnce<C, L, S, R>
where
L: Clone,
S: Clone,
R: Clone,
{
fn clone(&self) -> Self {
Self {
left: self.left.clone(),
sep: self.sep.clone(),
right: self.right.clone(),
marker: self.marker,
}
}
}
impl<C, L, S, R> RegexSepOnce<C, L, S, R> {
pub fn new(left: L, sep: S, right: R) -> Self {
Self {
left,
sep,
right,
marker: PhantomData,
}
}
pub fn left(&self) -> &L {
&self.left
}
pub fn left_mut(&mut self) -> &mut L {
&mut self.left
}
pub fn sep(&self) -> &S {
&self.sep
}
pub fn sep_mut(&mut self) -> &mut S {
&mut self.sep
}
pub fn right(&self) -> &R {
&self.right
}
pub 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
}
pub fn set_sep(&mut self, sep: S) -> &mut Self {
self.sep = sep;
self
}
}
impl<'a, C, L, S, R> Regex<C> for RegexSepOnce<C, L, S, R>
where
S: Regex<C>,
L: Regex<C>,
R: Regex<C>,
C: Context<'a> + Match<C>,
{
type Ret = (L::Ret, R::Ret);
#[inline(always)]
fn try_parse(&self, ctx: &mut C) -> Result<Self::Ret, Error> {
let mut g = CtxGuard::new(ctx);
let beg = g.beg();
let l = trace!("sep_once", beg @ "left", g.try_mat(&self.left)?);
let _ = trace!("sep_once", beg @ "sep", g.try_mat(&self.sep)?);
let r = trace!("sep_once", beg @ "right", g.try_mat(&self.right)?);
trace!("sep_once", beg => g.end(), true);
Ok((l, r))
}
}
#[derive(Debug, Default, Copy)]
pub struct RegexSeparate<C, P, S> {
pat: P,
sep: S,
skip: bool,
capacity: usize,
min: usize,
marker: PhantomData<C>,
}
impl<C, P, S> Clone for RegexSeparate<C, P, S>
where
P: Clone,
S: Clone,
{
fn clone(&self) -> Self {
Self {
pat: self.pat.clone(),
sep: self.sep.clone(),
skip: self.skip,
capacity: self.capacity,
min: self.min,
marker: self.marker,
}
}
}
impl<C, P, S> RegexSeparate<C, P, S> {
pub fn new(pat: P, sep: S) -> Self {
Self {
pat,
sep,
skip: true,
capacity: 0,
min: 1,
marker: PhantomData,
}
}
pub fn pat(&self) -> &P {
&self.pat
}
pub fn pat_mut(&mut self) -> &mut P {
&mut self.pat
}
pub fn sep(&self) -> &S {
&self.sep
}
pub fn sep_mut(&mut self) -> &mut S {
&mut self.sep
}
pub fn skip(&self) -> bool {
self.skip
}
pub fn min(&self) -> usize {
self.min
}
pub fn capacity(&self) -> usize {
self.capacity
}
pub fn set_pat(&mut self, pat: P) -> &mut Self {
self.pat = pat;
self
}
pub fn set_sep(&mut self, sep: S) -> &mut Self {
self.sep = sep;
self
}
pub fn set_skip(&mut self, skip: bool) -> &mut Self {
self.skip = skip;
self
}
pub fn set_capacity(&mut self, capacity: usize) -> &mut Self {
self.capacity = capacity;
self
}
pub fn set_min(&mut self, min: usize) -> &mut Self {
self.min = min;
self
}
pub fn with_skip(mut self, skip: bool) -> Self {
self.skip = skip;
self
}
pub fn with_capacity(mut self, capacity: usize) -> Self {
self.capacity = capacity;
self
}
pub fn at_least(mut self, min: usize) -> Self {
self.min = min;
self
}
}
impl<'a, C, S, P> Regex<C> for RegexSeparate<C, P, S>
where
S: Regex<C>,
P: Regex<C>,
C: Context<'a> + Match<C>,
{
type Ret = Vec<P::Ret>;
#[inline(always)]
fn try_parse(&self, ctx: &mut C) -> Result<Self::Ret, Error> {
let mut g = CtxGuard::new(ctx);
let mut res = Vec::with_capacity(self.capacity.max(self.min));
let mut ret = Err(Error::Separate);
let beg = g.beg();
let range: CRange<usize> = (self.min..).into();
trace_v!("separate", range, beg, ());
while let Ok(ret) = g.try_mat(&self.pat) {
let sep_ret = g.try_mat(&self.sep);
if sep_ret.is_ok() || self.skip {
res.push(ret);
}
if sep_ret.is_err() {
break;
}
}
let len = res.len();
if len >= self.min {
ret = Ok(res);
}
trace_v!("separate", range, beg => g.end(), ret.is_ok(), len);
g.process_ret(ret)
}
}
#[derive(Debug, Default, Copy)]
pub struct RegexSepCollect<C, P, S, T> {
pat: P,
sep: S,
skip: bool,
min: usize,
marker: PhantomData<(C, T)>,
}
impl<C, P, S, T> Clone for RegexSepCollect<C, P, S, T>
where
P: Clone,
S: Clone,
{
fn clone(&self) -> Self {
Self {
pat: self.pat.clone(),
sep: self.sep.clone(),
skip: self.skip,
min: self.min,
marker: self.marker,
}
}
}
impl<C, P, S, T> RegexSepCollect<C, P, S, T> {
pub fn new(pat: P, sep: S) -> Self {
Self {
pat,
sep,
skip: true,
min: 1,
marker: PhantomData,
}
}
pub fn pat(&self) -> &P {
&self.pat
}
pub fn pat_mut(&mut self) -> &mut P {
&mut self.pat
}
pub fn sep(&self) -> &S {
&self.sep
}
pub fn sep_mut(&mut self) -> &mut S {
&mut self.sep
}
pub fn skip(&self) -> bool {
self.skip
}
pub fn min(&self) -> usize {
self.min
}
pub fn set_pat(&mut self, pat: P) -> &mut Self {
self.pat = pat;
self
}
pub fn set_sep(&mut self, sep: S) -> &mut Self {
self.sep = sep;
self
}
pub fn set_skip(&mut self, skip: bool) -> &mut Self {
self.skip = skip;
self
}
pub fn set_min(&mut self, min: usize) -> &mut Self {
self.min = min;
self
}
pub fn with_skip(mut self, skip: bool) -> Self {
self.skip = skip;
self
}
pub fn at_least(mut self, min: usize) -> Self {
self.min = min;
self
}
}
impl<'a, C, S, P, T> Regex<C> for RegexSepCollect<C, P, S, T>
where
S: Regex<C>,
P: Regex<C>,
T: FromIterator<P::Ret>,
C: Context<'a> + Match<C>,
{
type Ret = T;
#[inline(always)]
fn try_parse(&self, ctx: &mut C) -> Result<Self::Ret, Error> {
let mut g = CtxGuard::new(ctx);
let mut ret = Err(Error::SepCollect);
let mut cnt = 0;
let mut end = false;
let beg = g.beg();
let range: CRange<usize> = (self.min..).into();
let val = trace_v!(
"sep_collect",
range,
beg,
T::from_iter(std::iter::from_fn(|| {
g.try_mat(&self.pat).ok().and_then(|ret| {
let sep_ret = g.try_mat(&self.sep);
if !end {
if sep_ret.is_err() {
end = true;
}
if sep_ret.is_ok() || self.skip {
cnt += 1;
return Some(ret);
}
}
None
})
}))
);
if cnt >= self.min {
ret = Ok(val);
}
trace_v!("sep_collect", range, beg => g.end(), ret.is_ok(), cnt);
g.process_ret(ret)
}
}