use crate::combinator::trace;
use crate::error::ErrMode;
use crate::error::ErrorKind;
use crate::error::ParserError;
use crate::stream::Accumulate;
use crate::stream::Range;
use crate::stream::Stream;
use crate::PResult;
use crate::Parser;
#[doc(alias = "many0")]
#[doc(alias = "count")]
#[doc(alias = "many0_count")]
#[doc(alias = "many1")]
#[doc(alias = "many1_count")]
#[doc(alias = "many_m_n")]
#[doc(alias = "repeated")]
#[doc(alias = "skip_many")]
#[doc(alias = "skip_many1")]
#[inline(always)]
pub fn repeat<I, O, C, E, P>(range: impl Into<Range>, parser: P) -> Repeat<P, I, O, C, E>
where
I: Stream,
C: Accumulate<O>,
P: Parser<I, O, E>,
E: ParserError<I>,
{
Repeat {
range: range.into(),
parser,
i: Default::default(),
o: Default::default(),
c: Default::default(),
e: Default::default(),
}
}
#[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))]
pub struct Repeat<P, I, O, C, E>
where
P: Parser<I, O, E>,
I: Stream,
C: Accumulate<O>,
E: ParserError<I>,
{
range: Range,
parser: P,
i: core::marker::PhantomData<I>,
o: core::marker::PhantomData<O>,
c: core::marker::PhantomData<C>,
e: core::marker::PhantomData<E>,
}
impl<P, I, O, E> Repeat<P, I, O, (), E>
where
P: Parser<I, O, E>,
I: Stream,
E: ParserError<I>,
{
#[doc(alias = "fold_many0")]
#[doc(alias = "fold_many1")]
#[doc(alias = "fold_many_m_n")]
#[doc(alias = "fold_repeat")]
#[inline(always)]
pub fn fold<H, G, R>(mut self, mut init: H, mut g: G) -> impl Parser<I, R, E>
where
G: FnMut(R, O) -> R,
H: FnMut() -> R,
{
let Range {
start_inclusive,
end_inclusive,
} = self.range;
trace("repeat_fold", move |i: &mut I| {
match (start_inclusive, end_inclusive) {
(0, None) => fold_repeat0_(&mut self.parser, &mut init, &mut g, i),
(1, None) => fold_repeat1_(&mut self.parser, &mut init, &mut g, i),
(start, end) => fold_repeat_m_n_(
start,
end.unwrap_or(usize::MAX),
&mut self.parser,
&mut init,
&mut g,
i,
),
}
})
}
}
impl<P, I, O, C, E> Parser<I, C, E> for Repeat<P, I, O, C, E>
where
P: Parser<I, O, E>,
I: Stream,
C: Accumulate<O>,
E: ParserError<I>,
{
#[inline(always)]
fn parse_next(&mut self, i: &mut I) -> PResult<C, E> {
let Range {
start_inclusive,
end_inclusive,
} = self.range;
trace("repeat", move |i: &mut I| {
match (start_inclusive, end_inclusive) {
(0, None) => repeat0_(&mut self.parser, i),
(1, None) => repeat1_(&mut self.parser, i),
(start, end) if Some(start) == end => repeat_n_(start, &mut self.parser, i),
(start, end) => repeat_m_n_(start, end.unwrap_or(usize::MAX), &mut self.parser, i),
}
})
.parse_next(i)
}
}
fn repeat0_<I, O, C, E, F>(f: &mut F, i: &mut I) -> PResult<C, E>
where
I: Stream,
C: Accumulate<O>,
F: Parser<I, O, E>,
E: ParserError<I>,
{
let mut acc = C::initial(None);
loop {
let start = i.checkpoint();
let len = i.eof_offset();
match f.parse_next(i) {
Err(ErrMode::Backtrack(_)) => {
i.reset(start);
return Ok(acc);
}
Err(e) => return Err(e),
Ok(o) => {
if i.eof_offset() == len {
return Err(ErrMode::assert(i, "`repeat` parsers must always consume"));
}
acc.accumulate(o);
}
}
}
}
fn repeat1_<I, O, C, E, F>(f: &mut F, i: &mut I) -> PResult<C, E>
where
I: Stream,
C: Accumulate<O>,
F: Parser<I, O, E>,
E: ParserError<I>,
{
match f.parse_next(i) {
Err(e) => Err(e.append(i, ErrorKind::Many)),
Ok(o) => {
let mut acc = C::initial(None);
acc.accumulate(o);
loop {
let start = i.checkpoint();
let len = i.eof_offset();
match f.parse_next(i) {
Err(ErrMode::Backtrack(_)) => {
i.reset(start);
return Ok(acc);
}
Err(e) => return Err(e),
Ok(o) => {
if i.eof_offset() == len {
return Err(ErrMode::assert(i, "`repeat` parsers must always consume"));
}
acc.accumulate(o);
}
}
}
}
}
}
fn repeat_n_<I, O, C, E, F>(count: usize, f: &mut F, i: &mut I) -> PResult<C, E>
where
I: Stream,
C: Accumulate<O>,
F: Parser<I, O, E>,
E: ParserError<I>,
{
let mut res = C::initial(Some(count));
for _ in 0..count {
match f.parse_next(i) {
Ok(o) => {
res.accumulate(o);
}
Err(e) => {
return Err(e.append(i, ErrorKind::Many));
}
}
}
Ok(res)
}
fn repeat_m_n_<I, O, C, E, F>(min: usize, max: usize, parse: &mut F, input: &mut I) -> PResult<C, E>
where
I: Stream,
C: Accumulate<O>,
F: Parser<I, O, E>,
E: ParserError<I>,
{
if min > max {
return Err(ErrMode::Cut(E::from_error_kind(input, ErrorKind::Many)));
}
let mut res = C::initial(Some(min));
for count in 0..max {
let start = input.checkpoint();
let len = input.eof_offset();
match parse.parse_next(input) {
Ok(value) => {
if input.eof_offset() == len {
return Err(ErrMode::assert(
input,
"`repeat` parsers must always consume",
));
}
res.accumulate(value);
}
Err(ErrMode::Backtrack(e)) => {
if count < min {
return Err(ErrMode::Backtrack(e.append(input, ErrorKind::Many)));
} else {
input.reset(start);
return Ok(res);
}
}
Err(e) => {
return Err(e);
}
}
}
Ok(res)
}
#[doc(alias = "many_till0")]
pub fn repeat_till<I, O, C, P, E, F, G>(
range: impl Into<Range>,
mut f: F,
mut g: G,
) -> impl Parser<I, (C, P), E>
where
I: Stream,
C: Accumulate<O>,
F: Parser<I, O, E>,
G: Parser<I, P, E>,
E: ParserError<I>,
{
let Range {
start_inclusive,
end_inclusive,
} = range.into();
trace("repeat_till", move |i: &mut I| {
match (start_inclusive, end_inclusive) {
(0, None) => repeat_till0_(&mut f, &mut g, i),
(start, end) => repeat_till_m_n_(start, end.unwrap_or(usize::MAX), &mut f, &mut g, i),
}
})
}
#[deprecated(since = "0.5.35", note = "Replaced with `repeat_till`")]
#[inline(always)]
pub fn repeat_till0<I, O, C, P, E, F, G>(f: F, g: G) -> impl Parser<I, (C, P), E>
where
I: Stream,
C: Accumulate<O>,
F: Parser<I, O, E>,
G: Parser<I, P, E>,
E: ParserError<I>,
{
repeat_till(0.., f, g)
}
fn repeat_till0_<I, O, C, P, E, F, G>(f: &mut F, g: &mut G, i: &mut I) -> PResult<(C, P), E>
where
I: Stream,
C: Accumulate<O>,
F: Parser<I, O, E>,
G: Parser<I, P, E>,
E: ParserError<I>,
{
let mut res = C::initial(None);
loop {
let start = i.checkpoint();
let len = i.eof_offset();
match g.parse_next(i) {
Ok(o) => return Ok((res, o)),
Err(ErrMode::Backtrack(_)) => {
i.reset(start);
match f.parse_next(i) {
Err(e) => return Err(e.append(i, ErrorKind::Many)),
Ok(o) => {
if i.eof_offset() == len {
return Err(ErrMode::assert(i, "`repeat` parsers must always consume"));
}
res.accumulate(o);
}
}
}
Err(e) => return Err(e),
}
}
}
fn repeat_till_m_n_<I, O, C, P, E, F, G>(
min: usize,
max: usize,
f: &mut F,
g: &mut G,
i: &mut I,
) -> PResult<(C, P), E>
where
I: Stream,
C: Accumulate<O>,
F: Parser<I, O, E>,
G: Parser<I, P, E>,
E: ParserError<I>,
{
if min > max {
return Err(ErrMode::Cut(E::from_error_kind(i, ErrorKind::Many)));
}
let mut res = C::initial(Some(min));
for _ in 0..min {
match f.parse_next(i) {
Ok(o) => {
res.accumulate(o);
}
Err(e) => {
return Err(e.append(i, ErrorKind::Many));
}
}
}
for count in min..=max {
let start = i.checkpoint();
let len = i.eof_offset();
match g.parse_next(i) {
Ok(o) => return Ok((res, o)),
Err(ErrMode::Backtrack(err)) => {
if count == max {
return Err(ErrMode::Backtrack(err));
}
i.reset(start);
match f.parse_next(i) {
Err(e) => {
return Err(e.append(i, ErrorKind::Many));
}
Ok(o) => {
if i.eof_offset() == len {
return Err(ErrMode::assert(i, "`repeat` parsers must always consume"));
}
res.accumulate(o);
}
}
}
Err(e) => return Err(e),
}
}
unreachable!()
}
#[doc(alias = "sep_by")]
#[doc(alias = "sep_by1")]
#[doc(alias = "separated_list0")]
#[doc(alias = "separated_list1")]
#[doc(alias = "separated_m_n")]
#[inline(always)]
pub fn separated<I, O, C, O2, E, P, S>(
range: impl Into<Range>,
mut parser: P,
mut separator: S,
) -> impl Parser<I, C, E>
where
I: Stream,
C: Accumulate<O>,
P: Parser<I, O, E>,
S: Parser<I, O2, E>,
E: ParserError<I>,
{
let Range {
start_inclusive,
end_inclusive,
} = range.into();
trace("separated", move |input: &mut I| {
match (start_inclusive, end_inclusive) {
(0, None) => separated0_(&mut parser, &mut separator, input),
(1, None) => separated1_(&mut parser, &mut separator, input),
(start, end) if Some(start) == end => {
separated_n_(start, &mut parser, &mut separator, input)
}
(start, end) => separated_m_n_(
start,
end.unwrap_or(usize::MAX),
&mut parser,
&mut separator,
input,
),
}
})
}
#[doc(alias = "sep_by")]
#[doc(alias = "separated_list0")]
#[deprecated(since = "0.5.19", note = "Replaced with `combinator::separated`")]
pub fn separated0<I, O, C, O2, E, P, S>(mut parser: P, mut sep: S) -> impl Parser<I, C, E>
where
I: Stream,
C: Accumulate<O>,
P: Parser<I, O, E>,
S: Parser<I, O2, E>,
E: ParserError<I>,
{
trace("separated0", move |i: &mut I| {
separated0_(&mut parser, &mut sep, i)
})
}
fn separated0_<I, O, C, O2, E, P, S>(
parser: &mut P,
separator: &mut S,
input: &mut I,
) -> PResult<C, E>
where
I: Stream,
C: Accumulate<O>,
P: Parser<I, O, E>,
S: Parser<I, O2, E>,
E: ParserError<I>,
{
let mut acc = C::initial(None);
let start = input.checkpoint();
match parser.parse_next(input) {
Err(ErrMode::Backtrack(_)) => {
input.reset(start);
return Ok(acc);
}
Err(e) => return Err(e),
Ok(o) => {
acc.accumulate(o);
}
}
loop {
let start = input.checkpoint();
let len = input.eof_offset();
match separator.parse_next(input) {
Err(ErrMode::Backtrack(_)) => {
input.reset(start);
return Ok(acc);
}
Err(e) => return Err(e),
Ok(_) => {
if input.eof_offset() == len {
return Err(ErrMode::assert(
input,
"`separated` separator parser must always consume",
));
}
match parser.parse_next(input) {
Err(ErrMode::Backtrack(_)) => {
input.reset(start);
return Ok(acc);
}
Err(e) => return Err(e),
Ok(o) => {
acc.accumulate(o);
}
}
}
}
}
}
#[doc(alias = "sep_by1")]
#[doc(alias = "separated_list1")]
#[deprecated(since = "0.5.19", note = "Replaced with `combinator::separated`")]
pub fn separated1<I, O, C, O2, E, P, S>(mut parser: P, mut sep: S) -> impl Parser<I, C, E>
where
I: Stream,
C: Accumulate<O>,
P: Parser<I, O, E>,
S: Parser<I, O2, E>,
E: ParserError<I>,
{
trace("separated1", move |i: &mut I| {
separated1_(&mut parser, &mut sep, i)
})
}
fn separated1_<I, O, C, O2, E, P, S>(
parser: &mut P,
separator: &mut S,
input: &mut I,
) -> PResult<C, E>
where
I: Stream,
C: Accumulate<O>,
P: Parser<I, O, E>,
S: Parser<I, O2, E>,
E: ParserError<I>,
{
let mut acc = C::initial(None);
match parser.parse_next(input) {
Err(e) => return Err(e),
Ok(o) => {
acc.accumulate(o);
}
}
loop {
let start = input.checkpoint();
let len = input.eof_offset();
match separator.parse_next(input) {
Err(ErrMode::Backtrack(_)) => {
input.reset(start);
return Ok(acc);
}
Err(e) => return Err(e),
Ok(_) => {
if input.eof_offset() == len {
return Err(ErrMode::assert(
input,
"`separated` separator parser must always consume",
));
}
match parser.parse_next(input) {
Err(ErrMode::Backtrack(_)) => {
input.reset(start);
return Ok(acc);
}
Err(e) => return Err(e),
Ok(o) => {
acc.accumulate(o);
}
}
}
}
}
}
fn separated_n_<I, O, C, O2, E, P, S>(
count: usize,
parser: &mut P,
separator: &mut S,
input: &mut I,
) -> PResult<C, E>
where
I: Stream,
C: Accumulate<O>,
P: Parser<I, O, E>,
S: Parser<I, O2, E>,
E: ParserError<I>,
{
let mut acc = C::initial(Some(count));
if count == 0 {
return Ok(acc);
}
match parser.parse_next(input) {
Err(e) => {
return Err(e.append(input, ErrorKind::Many));
}
Ok(o) => {
acc.accumulate(o);
}
}
for _ in 1..count {
let len = input.eof_offset();
match separator.parse_next(input) {
Err(e) => {
return Err(e.append(input, ErrorKind::Many));
}
Ok(_) => {
if input.eof_offset() == len {
return Err(ErrMode::assert(
input,
"`separated` separator parser must always consume",
));
}
match parser.parse_next(input) {
Err(e) => {
return Err(e.append(input, ErrorKind::Many));
}
Ok(o) => {
acc.accumulate(o);
}
}
}
}
}
Ok(acc)
}
fn separated_m_n_<I, O, C, O2, E, P, S>(
min: usize,
max: usize,
parser: &mut P,
separator: &mut S,
input: &mut I,
) -> PResult<C, E>
where
I: Stream,
C: Accumulate<O>,
P: Parser<I, O, E>,
S: Parser<I, O2, E>,
E: ParserError<I>,
{
if min > max {
return Err(ErrMode::Cut(E::from_error_kind(input, ErrorKind::Many)));
}
let mut acc = C::initial(Some(min));
let start = input.checkpoint();
match parser.parse_next(input) {
Err(ErrMode::Backtrack(e)) => {
if min == 0 {
input.reset(start);
return Ok(acc);
} else {
return Err(ErrMode::Backtrack(e.append(input, ErrorKind::Many)));
}
}
Err(e) => return Err(e),
Ok(o) => {
acc.accumulate(o);
}
}
for index in 1..max {
let start = input.checkpoint();
let len = input.eof_offset();
match separator.parse_next(input) {
Err(ErrMode::Backtrack(e)) => {
if index < min {
return Err(ErrMode::Backtrack(e.append(input, ErrorKind::Many)));
} else {
input.reset(start);
return Ok(acc);
}
}
Err(e) => {
return Err(e);
}
Ok(_) => {
if input.eof_offset() == len {
return Err(ErrMode::assert(
input,
"`separated` separator parser must always consume",
));
}
match parser.parse_next(input) {
Err(ErrMode::Backtrack(e)) => {
if index < min {
return Err(ErrMode::Backtrack(e.append(input, ErrorKind::Many)));
} else {
input.reset(start);
return Ok(acc);
}
}
Err(e) => {
return Err(e);
}
Ok(o) => {
acc.accumulate(o);
}
}
}
}
}
Ok(acc)
}
pub fn separated_foldl1<I, O, O2, E, P, S, Op>(
mut parser: P,
mut sep: S,
mut op: Op,
) -> impl Parser<I, O, E>
where
I: Stream,
P: Parser<I, O, E>,
S: Parser<I, O2, E>,
E: ParserError<I>,
Op: FnMut(O, O2, O) -> O,
{
trace("separated_foldl1", move |i: &mut I| {
let mut ol = parser.parse_next(i)?;
loop {
let start = i.checkpoint();
let len = i.eof_offset();
match sep.parse_next(i) {
Err(ErrMode::Backtrack(_)) => {
i.reset(start);
return Ok(ol);
}
Err(e) => return Err(e),
Ok(s) => {
if i.eof_offset() == len {
return Err(ErrMode::assert(i, "`repeat` parsers must always consume"));
}
match parser.parse_next(i) {
Err(ErrMode::Backtrack(_)) => {
i.reset(start);
return Ok(ol);
}
Err(e) => return Err(e),
Ok(or) => {
ol = op(ol, s, or);
}
}
}
}
}
})
}
#[cfg(feature = "alloc")]
pub fn separated_foldr1<I, O, O2, E, P, S, Op>(
mut parser: P,
mut sep: S,
mut op: Op,
) -> impl Parser<I, O, E>
where
I: Stream,
P: Parser<I, O, E>,
S: Parser<I, O2, E>,
E: ParserError<I>,
Op: FnMut(O, O2, O) -> O,
{
trace("separated_foldr1", move |i: &mut I| {
let ol = parser.parse_next(i)?;
let all: crate::lib::std::vec::Vec<(O2, O)> =
repeat(0.., (sep.by_ref(), parser.by_ref())).parse_next(i)?;
if let Some((s, or)) = all
.into_iter()
.rev()
.reduce(|(sr, or), (sl, ol)| (sl, op(ol, sr, or)))
{
let merged = op(ol, s, or);
Ok(merged)
} else {
Ok(ol)
}
})
}
pub fn fill<'a, I, O, E, F>(mut f: F, buf: &'a mut [O]) -> impl Parser<I, (), E> + 'a
where
I: Stream + 'a,
F: Parser<I, O, E> + 'a,
E: ParserError<I> + 'a,
{
trace("fill", move |i: &mut I| {
for elem in buf.iter_mut() {
match f.parse_next(i) {
Ok(o) => {
*elem = o;
}
Err(e) => {
return Err(e.append(i, ErrorKind::Many));
}
}
}
Ok(())
})
}
#[deprecated(since = "0.5.36", note = "Replaced with `repeat(...).fold(...)`")]
#[inline(always)]
pub fn fold_repeat<I, O, E, F, G, H, R>(
range: impl Into<Range>,
f: F,
init: H,
g: G,
) -> impl Parser<I, R, E>
where
I: Stream,
F: Parser<I, O, E>,
G: FnMut(R, O) -> R,
H: FnMut() -> R,
E: ParserError<I>,
{
repeat(range, f).fold(init, g)
}
fn fold_repeat0_<I, O, E, F, G, H, R>(
f: &mut F,
init: &mut H,
g: &mut G,
input: &mut I,
) -> PResult<R, E>
where
I: Stream,
F: Parser<I, O, E>,
G: FnMut(R, O) -> R,
H: FnMut() -> R,
E: ParserError<I>,
{
let mut res = init();
loop {
let start = input.checkpoint();
let len = input.eof_offset();
match f.parse_next(input) {
Ok(o) => {
if input.eof_offset() == len {
return Err(ErrMode::assert(
input,
"`repeat` parsers must always consume",
));
}
res = g(res, o);
}
Err(ErrMode::Backtrack(_)) => {
input.reset(start);
return Ok(res);
}
Err(e) => {
return Err(e);
}
}
}
}
fn fold_repeat1_<I, O, E, F, G, H, R>(
f: &mut F,
init: &mut H,
g: &mut G,
input: &mut I,
) -> PResult<R, E>
where
I: Stream,
F: Parser<I, O, E>,
G: FnMut(R, O) -> R,
H: FnMut() -> R,
E: ParserError<I>,
{
let init = init();
match f.parse_next(input) {
Err(ErrMode::Backtrack(_)) => Err(ErrMode::from_error_kind(input, ErrorKind::Many)),
Err(e) => Err(e),
Ok(o1) => {
let mut acc = g(init, o1);
loop {
let start = input.checkpoint();
let len = input.eof_offset();
match f.parse_next(input) {
Err(ErrMode::Backtrack(_)) => {
input.reset(start);
break;
}
Err(e) => return Err(e),
Ok(o) => {
if input.eof_offset() == len {
return Err(ErrMode::assert(
input,
"`repeat` parsers must always consume",
));
}
acc = g(acc, o);
}
}
}
Ok(acc)
}
}
}
fn fold_repeat_m_n_<I, O, E, F, G, H, R>(
min: usize,
max: usize,
parse: &mut F,
init: &mut H,
fold: &mut G,
input: &mut I,
) -> PResult<R, E>
where
I: Stream,
F: Parser<I, O, E>,
G: FnMut(R, O) -> R,
H: FnMut() -> R,
E: ParserError<I>,
{
if min > max {
return Err(ErrMode::Cut(E::from_error_kind(input, ErrorKind::Many)));
}
let mut acc = init();
for count in 0..max {
let start = input.checkpoint();
let len = input.eof_offset();
match parse.parse_next(input) {
Ok(value) => {
if input.eof_offset() == len {
return Err(ErrMode::assert(
input,
"`repeat` parsers must always consume",
));
}
acc = fold(acc, value);
}
Err(ErrMode::Backtrack(err)) => {
if count < min {
return Err(ErrMode::Backtrack(err.append(input, ErrorKind::Many)));
} else {
input.reset(start);
break;
}
}
Err(e) => return Err(e),
}
}
Ok(acc)
}