use crate::*;
use ::std::marker::PhantomData;
#[derive(Clone)]
pub struct Group<'code, Capture, const NUM: usize> {
pub buffer: Option<Buffer<'code>>,
_captured: PhantomData<Capture>,
}
impl<'code, Capture, const NUM: usize> std::fmt::Debug
for Group<'code, Capture, NUM>
{
fn fmt(
&self,
f: &mut std::fmt::Formatter<'_>,
) -> std::fmt::Result {
f.debug_tuple("Group").field(&self.buffer).finish()
}
}
impl<'code, Capture, const NUM: usize> Token<'code>
for Group<'code, Capture, NUM>
where
Capture: Token<'code>,
{
const NAME: &'static str = <Capture as Token>::NAME;
fn buffer(&self) -> Option<Buffer<'code>> {
self.buffer.clone()
}
}
impl<'code, Capture, const NUM: usize> Lexer<'code>
for Group<'code, Capture, NUM>
where
Capture: Lexer<'code>,
{
fn lex(
buffer: &mut Buffer<'code>,
) -> Result<Self, Error<'code>> {
let mut local_buffer = buffer.clone();
let mut return_buffer = None::<Buffer<'code>>;
let mut matched = 0usize;
loop {
match <Capture as Lexer>::lex(&mut local_buffer)
{
Ok(captured) => {
return_buffer = match return_buffer {
Some(return_buffer) => Some(
match <Capture as Token>::buffer(
&captured,
) {
Some(captured_buffer) => {
return_buffer
+ captured_buffer
}
None => return_buffer,
},
),
None => <Capture as Token>::buffer(
&captured,
)
.clone(),
};
matched += 1;
}
Err(mut err) => {
if NUM > 0 && matched < NUM {
err.matched = matched;
Err(err)?
}
break;
}
}
}
*buffer = local_buffer;
Ok(Self {
buffer: return_buffer,
_captured: PhantomData,
})
}
}
#[derive(Clone)]
pub struct GroupUntil<'code, Capture, End, const NUM: usize>
{
pub buffer: Option<Buffer<'code>>,
_captured: PhantomData<Capture>,
_end: PhantomData<End>,
}
impl<'code, Capture, End, const NUM: usize> std::fmt::Debug
for GroupUntil<'code, Capture, End, NUM>
{
fn fmt(
&self,
f: &mut std::fmt::Formatter<'_>,
) -> std::fmt::Result {
f.debug_tuple("Group").field(&self.buffer).finish()
}
}
impl<'code, Capture, End, const NUM: usize> Token<'code>
for GroupUntil<'code, Capture, End, NUM>
where
Capture: Token<'code>,
End: Token<'code>,
{
const NAME: &'static str = <Capture as Token>::NAME;
fn buffer(&self) -> Option<Buffer<'code>> {
self.buffer.clone()
}
}
impl<'code, Capture, End, const NUM: usize> Lexer<'code>
for GroupUntil<'code, Capture, End, NUM>
where
Capture: Lexer<'code>,
End: Lexer<'code>,
{
fn lex(
buffer: &mut Buffer<'code>,
) -> Result<Self, Error<'code>> {
let mut local_buffer = buffer.clone();
let mut return_buffer = None::<Buffer<'code>>;
let mut matched = 0usize;
while <End as Lexer>::lex(&mut local_buffer.clone())
.is_err()
{
let captured =
<Capture as Lexer>::lex(&mut local_buffer)
.map_err(|mut err| {
err.matched = matched;
if let Kind::NotFound(syntax) =
&mut err.kind
{
*syntax = <End as Token>::NAME
}
err
})?;
return_buffer = match return_buffer {
Some(return_buffer) => Some(
match <Capture as Token>::buffer(
&captured,
) {
Some(captured_buffer) => {
return_buffer + captured_buffer
}
None => return_buffer,
},
),
None => {
<Capture as Token>::buffer(&captured)
.clone()
}
};
matched += 1;
}
if NUM > 0 && matched < NUM {
Err(Error {
buffer: local_buffer.clone(),
matched,
kind: Kind::NotFound(<Self as Token>::NAME),
})?
}
*buffer = local_buffer;
Ok(Self {
buffer: return_buffer,
_captured: PhantomData,
_end: PhantomData,
})
}
}
#[derive(Debug, Clone)]
pub struct GroupBookEnd<
'code,
Start,
Capture,
End,
const NUM: usize,
> {
start: Start,
group: GroupUntil<'code, Capture, End, NUM>,
end: End,
}
impl<'code, Start, Capture, End, const NUM: usize>
Token<'code>
for GroupBookEnd<'code, Start, Capture, End, NUM>
where
Start: Token<'code>,
Capture: Token<'code>,
End: Token<'code>,
{
const NAME: &'static str = <Capture as Token>::NAME;
fn buffer(&self) -> Option<Buffer<'code>> {
let buffers = [
<Start as Token>::buffer(&self.start),
<GroupUntil<'code, Capture, End, NUM> as Token>::buffer(&self.group),
<End as Token>::buffer(&self.end),
]
.into_iter();
buffers
.flatten()
.reduce(|acc, current| acc + current)
}
}
impl<'code, Start, Capture, End, const NUM: usize>
Lexer<'code>
for GroupBookEnd<'code, Start, Capture, End, NUM>
where
Start: Lexer<'code>,
Capture: Lexer<'code>,
End: Lexer<'code>,
{
fn lex(
buffer: &mut Buffer<'code>,
) -> Result<Self, Error<'code>> {
let mut local_buffer = buffer.clone();
let mut matched = 0usize;
let start =
<Start as Lexer>::lex(&mut local_buffer)?;
matched += 1;
let group =
<GroupUntil<Capture, End, NUM> as Lexer>::lex(
&mut local_buffer,
)
.map_err(|mut err| {
matched += err.matched;
err.matched = matched;
err
})?;
let end = <End as Lexer>::lex(&mut local_buffer)
.map_err(|mut err| {
matched += err.matched;
err.matched = matched;
err
})?;
*buffer = local_buffer;
Ok(Self { start, group, end })
}
}