blob: 27543c3ed6371bfce6dded5abc2fe48b4247703c [file] [log] [blame]
//! Combinators which take one or more parsers and applies them repeatedly.
use crate::{
error::{
Commit, ParseError,
ParseResult::{self, *},
ResultExt, StdParseResult, StreamError, Tracked,
},
lib::{borrow::BorrowMut, cmp, marker::PhantomData, mem},
parser::{
choice::{optional, Optional, Or},
combinator::{ignore, Ignore},
function::{parser, FnParser},
sequence::With,
token::{value, Value},
FirstMode, ParseMode,
},
stream::{uncons, Stream, StreamOnce},
ErrorOffset, Parser,
};
parser! {
pub struct Count;
/// Parses `parser` from zero up to `count` times.
///
/// ```
/// # extern crate combine;
/// # use combine::*;
/// # use combine::error::Info;
/// # use combine::stream::easy::Error;
/// # fn main() {
/// let mut parser = count(2, token(b'a'));
///
/// let result = parser.parse(&b"aaab"[..]);
/// assert_eq!(result, Ok((b"aa"[..].to_owned(), &b"ab"[..])));
/// # }
/// ```
pub fn count[F, Input, P](count: usize, parser: P)(Input) -> F
where [
Input: Stream,
P: Parser<Input>,
F: Extend<P::Output> + Default,
]
{
count_min_max(0, *count, parser)
}
}
parser! {
pub struct SkipCount;
type PartialState = <With<Count<Sink, Input, P>, Value<Input, ()>> as Parser<Input>>::PartialState;
/// Parses `parser` from zero up to `count` times skipping the output of `parser`.
///
/// ```
/// # extern crate combine;
/// # use combine::*;
/// # use combine::stream::easy::{Error, Info};
/// # fn main() {
/// let mut parser = skip_count(2, token(b'a'));
///
/// let result = parser.parse(&b"aaab"[..]);
/// assert_eq!(result, Ok(((), &b"ab"[..])));
/// # }
/// ```
pub fn skip_count[Input, P](count: usize, parser: P)(Input) -> ()
where [
P: Parser<Input>
]
{
self::count::<Sink, _, _>(*count, parser.map(|_| ())).with(value(()))
}
}
#[derive(Copy, Clone)]
pub struct CountMinMax<F, P> {
parser: P,
min: usize,
max: usize,
_marker: PhantomData<fn() -> F>,
}
struct SuggestSizeHint<I> {
iterator: I,
min: usize,
max: Option<usize>,
}
impl<I> Iterator for SuggestSizeHint<I>
where
I: Iterator,
{
type Item = I::Item;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.iterator.next()
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
(self.min, self.max)
}
}
fn suggest_size_hint<I>(iterator: I, (min, max): (usize, Option<usize>)) -> SuggestSizeHint<I>
where
I: Iterator,
{
SuggestSizeHint {
iterator,
// Invalid input may report an extreme size so we guard against that (while still
// optimizing by preallocating for the expected case of success)
min: cmp::min(min, 4096),
max,
}
}
impl<Input, P, F> Parser<Input> for CountMinMax<F, P>
where
Input: Stream,
P: Parser<Input>,
F: Extend<P::Output> + Default,
{
type Output = F;
type PartialState = (usize, F, P::PartialState);
parse_mode!(Input);
#[inline]
fn parse_mode_impl<M>(
&mut self,
mode: M,
input: &mut Input,
state: &mut Self::PartialState,
) -> ParseResult<Self::Output, Input::Error>
where
M: ParseMode,
{
let (count, elements, child_state) = state;
let mut iter = self.parser.by_ref().partial_iter(mode, input, child_state);
let remaining_min = self.min.saturating_sub(*count);
let remaining_max = self.max - *count;
elements.extend(suggest_size_hint(
iter.by_ref().take(remaining_max).inspect(|_| *count += 1),
(remaining_min, Some(remaining_max)),
));
if *count < self.min {
let err = StreamError::message_format(format_args!(
"expected {} more elements",
self.min - *count
));
iter.fail(err)
} else {
iter.into_result_fast(elements).map(|x| {
*count = 0;
x
})
}
}
fn add_error(&mut self, error: &mut Tracked<<Input as StreamOnce>::Error>) {
self.parser.add_error(error)
}
}
/// Parses `parser` from `min` to `max` times (including `min` and `max`).
///
/// ```
/// # extern crate combine;
/// # use combine::*;
/// # use combine::stream::easy::{Error, Info};
/// # fn main() {
/// let mut parser = count_min_max(2, 2, token(b'a'));
///
/// let result = parser.parse(&b"aaab"[..]);
/// assert_eq!(result, Ok((b"aa"[..].to_owned(), &b"ab"[..])));
/// let result = parser.parse(&b"ab"[..]);
/// assert!(result.is_err());
/// # }
/// ```
///
/// # Panics
///
/// If `min` > `max`.
pub fn count_min_max<F, Input, P>(min: usize, max: usize, parser: P) -> CountMinMax<F, P>
where
Input: Stream,
P: Parser<Input>,
F: Extend<P::Output> + Default,
{
assert!(min <= max);
CountMinMax {
parser,
min,
max,
_marker: PhantomData,
}
}
parser! {
pub struct SkipCountMinMax;
type PartialState = <With<CountMinMax<Sink, P>, Value<Input, ()>> as Parser<Input>>::PartialState;
/// Parses `parser` from `min` to `max` times (including `min` and `max`)
/// skipping the output of `parser`.
///
/// ```
/// # extern crate combine;
/// # use combine::*;
/// # fn main() {
/// let mut parser = skip_count_min_max(2, 2, token(b'a'));
///
/// let result = parser.parse(&b"aaab"[..]);
/// assert_eq!(result, Ok(((), &b"ab"[..])));
/// let result = parser.parse(&b"ab"[..]);
/// assert!(result.is_err());
/// # }
/// ```
///
/// # Panics
///
/// If `min` > `max`.
pub fn skip_count_min_max[Input, P](min: usize, max: usize, parser: P)(Input) -> ()
where [
P: Parser<Input>,
]
{
count_min_max::<Sink, _, _>(*min, *max, parser.map(|_| ())).with(value(()))
}
}
pub struct Iter<'a, Input, P, S, M>
where
Input: Stream,
P: Parser<Input>,
{
parser: P,
input: &'a mut Input,
committed: bool,
state: State<<Input as StreamOnce>::Error>,
partial_state: S,
mode: M,
}
enum State<E> {
Ok,
PeekErr(E),
CommitErr(E),
}
impl<'a, Input, P, S, M> Iter<'a, Input, P, S, M>
where
Input: Stream,
P: Parser<Input>,
S: BorrowMut<P::PartialState>,
{
pub fn new(parser: P, mode: M, input: &'a mut Input, partial_state: S) -> Self {
Iter {
parser,
input,
committed: false,
state: State::Ok,
partial_state,
mode,
}
}
/// Converts the iterator to a `ParseResult`, returning `Ok` if the parsing so far has be done
/// without any errors which committed data.
pub fn into_result<O>(self, value: O) -> StdParseResult<O, Input> {
self.into_result_(value).into()
}
fn into_result_<O>(self, value: O) -> ParseResult<O, Input::Error> {
match self.state {
State::Ok | State::PeekErr(_) => {
if self.committed {
CommitOk(value)
} else {
PeekOk(value)
}
}
State::CommitErr(e) => CommitErr(e),
}
}
fn into_result_fast<O>(self, value: &mut O) -> ParseResult<O, Input::Error>
where
O: Default,
{
match self.state {
State::Ok | State::PeekErr(_) => {
let value = mem::take(value);
if self.committed {
CommitOk(value)
} else {
PeekOk(value)
}
}
State::CommitErr(e) => CommitErr(e),
}
}
fn fail<T>(
self,
err: <<Input as StreamOnce>::Error as ParseError<
<Input as StreamOnce>::Token,
<Input as StreamOnce>::Range,
<Input as StreamOnce>::Position,
>>::StreamError,
) -> ParseResult<T, Input::Error> {
match self.state {
State::Ok => {
let err = <Input as StreamOnce>::Error::from_error(self.input.position(), err);
if self.committed {
CommitErr(err)
} else {
PeekErr(err.into())
}
}
State::PeekErr(mut e) => {
let err = <Input as StreamOnce>::Error::from_error(self.input.position(), err);
e = e.merge(err);
if self.committed {
CommitErr(e)
} else {
PeekErr(e.into())
}
}
State::CommitErr(mut e) => {
e.add(err);
CommitErr(e)
}
}
}
}
impl<'a, Input, P, S, M> Iterator for Iter<'a, Input, P, S, M>
where
Input: Stream,
P: Parser<Input>,
S: BorrowMut<P::PartialState>,
M: ParseMode,
{
type Item = P::Output;
fn next(&mut self) -> Option<P::Output> {
let before = self.input.checkpoint();
match self
.parser
.parse_mode(self.mode, self.input, self.partial_state.borrow_mut())
{
PeekOk(v) => {
self.mode.set_first();
Some(v)
}
CommitOk(v) => {
self.mode.set_first();
self.committed = true;
Some(v)
}
PeekErr(e) => {
self.state = match self.input.reset(before) {
Err(err) => State::CommitErr(err),
Ok(_) => State::PeekErr(e.error),
};
None
}
CommitErr(e) => {
self.state = State::CommitErr(e);
None
}
}
}
}
#[derive(Copy, Clone)]
pub struct Many<F, P>(P, PhantomData<F>);
impl<F, Input, P> Parser<Input> for Many<F, P>
where
Input: Stream,
P: Parser<Input>,
F: Extend<P::Output> + Default,
{
type Output = F;
type PartialState = (F, P::PartialState);
parse_mode!(Input);
#[inline]
fn parse_mode_impl<M>(
&mut self,
mode: M,
input: &mut Input,
state: &mut Self::PartialState,
) -> ParseResult<Self::Output, Input::Error>
where
M: ParseMode,
{
// TODO
let (ref mut elements, ref mut child_state) = *state;
let mut iter = (&mut self.0).partial_iter(mode, input, child_state);
elements.extend(iter.by_ref());
iter.into_result_fast(elements)
}
fn add_error(&mut self, errors: &mut Tracked<<Input as StreamOnce>::Error>) {
self.0.add_error(errors)
}
fn add_committed_expected_error(&mut self, errors: &mut Tracked<<Input as StreamOnce>::Error>) {
self.add_error(errors);
}
fn parser_count(&self) -> ErrorOffset {
self.0.parser_count()
}
}
/// Parses `p` zero or more times returning a collection with the values from `p`.
///
/// If the returned collection cannot be inferred type annotations must be supplied, either by
/// annotating the resulting type binding `let collection: Vec<_> = ...` or by specializing when
/// calling many, `many::<Vec<_>, _, _>(...)`.
///
/// NOTE: If `p` can succeed without consuming any input this may hang forever as `many` will
/// repeatedly use `p` to parse the same location in the input every time
///
/// ```
/// # extern crate combine;
/// # use combine::*;
/// # use combine::parser::char::digit;
/// # fn main() {
/// let result = many(digit())
/// .parse("123A")
/// .map(|x| x.0);
/// assert_eq!(result, Ok(vec!['1', '2', '3']));
/// # }
/// ```
pub fn many<F, Input, P>(p: P) -> Many<F, P>
where
Input: Stream,
P: Parser<Input>,
F: Extend<P::Output> + Default,
{
Many(p, PhantomData)
}
#[derive(Copy, Clone)]
pub struct Many1<F, P>(P, PhantomData<fn() -> F>);
impl<F, Input, P> Parser<Input> for Many1<F, P>
where
Input: Stream,
F: Extend<P::Output> + Default,
P: Parser<Input>,
{
type Output = F;
type PartialState = (bool, bool, F, P::PartialState);
parse_mode!(Input);
#[inline]
fn parse_mode_impl<M>(
&mut self,
mut mode: M,
input: &mut Input,
state: &mut Self::PartialState,
) -> ParseResult<F, Input::Error>
where
M: ParseMode,
{
let (ref mut parsed_one, ref mut committed_state, ref mut elements, ref mut child_state) =
*state;
if mode.is_first() || !*parsed_one {
debug_assert!(!*parsed_one);
let (first, committed) = ctry!(self.0.parse_mode(mode, input, child_state));
elements.extend(Some(first));
// TODO Should PeekOk be an error?
*committed_state = !committed.is_peek();
*parsed_one = true;
mode.set_first();
}
let mut iter = Iter {
parser: &mut self.0,
committed: *committed_state,
input,
state: State::Ok,
partial_state: child_state,
mode,
};
elements.extend(iter.by_ref());
iter.into_result_fast(elements).map(|x| {
*parsed_one = false;
x
})
}
fn add_committed_expected_error(&mut self, errors: &mut Tracked<<Input as StreamOnce>::Error>) {
self.add_error(errors);
}
forward_parser!(Input, add_error parser_count, 0);
}
/// Parses `p` one or more times returning a collection with the values from `p`.
///
/// If the returned collection cannot be inferred type annotations must be supplied, either by
/// annotating the resulting type binding `let collection: Vec<_> = ...` or by specializing when
/// calling many1 `many1::<Vec<_>, _>(...)`.
///
/// NOTE: If `p` can succeed without consuming any input this may hang forever as `many1` will
/// repeatedly use `p` to parse the same location in the input every time
///
///
/// ```
/// # extern crate combine;
/// # use combine::*;
/// # use combine::parser::char::digit;
/// # fn main() {
/// let result = many1::<Vec<_>, _, _>(digit())
/// .parse("A123");
/// assert!(result.is_err());
/// # }
/// ```
pub fn many1<F, Input, P>(p: P) -> Many1<F, P>
where
Input: Stream,
F: Extend<P::Output> + Default,
P: Parser<Input>,
{
Many1(p, PhantomData)
}
#[derive(Clone)]
#[doc(hidden)]
// FIXME Should not be public
pub struct Sink;
impl Default for Sink {
fn default() -> Self {
Sink
}
}
impl<A> Extend<A> for Sink {
fn extend<T>(&mut self, iter: T)
where
T: IntoIterator<Item = A>,
{
for _ in iter {}
}
}
parser! {
pub struct SkipMany;
type PartialState = <Ignore<Many<Sink, Ignore<P>>> as Parser<Input>>::PartialState;
/// Parses `p` zero or more times ignoring the result.
///
/// NOTE: If `p` can succeed without consuming any input this may hang forever as `skip_many` will
/// repeatedly use `p` to parse the same location in the input every time
///
/// ```
/// # extern crate combine;
/// # use combine::*;
/// # use combine::parser::char::digit;
/// # fn main() {
/// let result = skip_many(digit())
/// .parse("A");
/// assert_eq!(result, Ok(((), "A")));
/// # }
/// ```
pub fn skip_many[Input, P](p: P)(Input) -> ()
where [
P: Parser<Input>,
]
{
ignore(many::<Sink, _, _>(ignore(p)))
}
}
parser! {
pub struct SkipMany1;
type PartialState = <Ignore<Many1<Sink, Ignore<P>>> as Parser<Input>>::PartialState;
/// Parses `p` one or more times ignoring the result.
///
/// NOTE: If `p` can succeed without consuming any input this may hang forever as `skip_many1` will
/// repeatedly use `p` to parse the same location in the input every time
///
/// ```
/// # extern crate combine;
/// # use combine::*;
/// # use combine::parser::char::digit;
/// # fn main() {
/// let result = skip_many1(digit())
/// .parse("123A");
/// assert_eq!(result, Ok(((), "A")));
/// # }
/// ```
pub fn skip_many1[Input, P](p: P)(Input) -> ()
where [
P: Parser<Input>,
]
{
ignore(many1::<Sink, _, _>(ignore(p)))
}
}
#[derive(Copy, Clone)]
pub struct SepBy<F, P, S> {
parser: P,
separator: S,
_marker: PhantomData<fn() -> F>,
}
impl<F, Input, P, S> Parser<Input> for SepBy<F, P, S>
where
Input: Stream,
F: Extend<P::Output> + Default,
P: Parser<Input>,
S: Parser<Input>,
{
type Output = F;
type PartialState = <Or<
SepBy1<F, P, S>,
FnParser<Input, fn(&mut Input) -> StdParseResult<F, Input>>,
> as Parser<Input>>::PartialState;
parse_mode!(Input);
#[inline]
fn parse_mode_impl<M>(
&mut self,
mode: M,
input: &mut Input,
state: &mut Self::PartialState,
) -> ParseResult<F, Input::Error>
where
M: ParseMode,
{
sep_by1(&mut self.parser, &mut self.separator)
.or(parser(|_| Ok((F::default(), Commit::Peek(())))))
.parse_mode(mode, input, state)
}
fn add_committed_expected_error(&mut self, errors: &mut Tracked<<Input as StreamOnce>::Error>) {
self.separator.add_error(errors)
}
forward_parser!(Input, add_error parser_count, parser);
}
/// Parses `parser` zero or more time separated by `separator`, returning a collection with the
/// values from `p`.
///
/// If the returned collection cannot be inferred type annotations must be supplied, either by
/// annotating the resulting type binding `let collection: Vec<_> = ...` or by specializing when
/// calling `sep_by`, `sep_by::<Vec<_>, _, _>(...)`.
///
/// ```
/// # extern crate combine;
/// # use combine::*;
/// # use combine::parser::char::digit;
/// # fn main() {
/// let mut parser = sep_by(digit(), token(','));
/// let result_ok = parser.parse("1,2,3");
/// assert_eq!(result_ok, Ok((vec!['1', '2', '3'], "")));
/// let result_ok2 = parser.parse("");
/// assert_eq!(result_ok2, Ok((vec![], "")));
/// # }
/// ```
pub fn sep_by<F, Input, P, S>(parser: P, separator: S) -> SepBy<F, P, S>
where
Input: Stream,
F: Extend<P::Output> + Default,
P: Parser<Input>,
S: Parser<Input>,
{
SepBy {
parser,
separator,
_marker: PhantomData,
}
}
#[derive(Copy, Clone)]
pub struct SepBy1<F, P, S> {
parser: P,
separator: S,
_marker: PhantomData<fn() -> F>,
}
impl<F, Input, P, S> Parser<Input> for SepBy1<F, P, S>
where
Input: Stream,
F: Extend<P::Output> + Default,
P: Parser<Input>,
S: Parser<Input>,
{
type Output = F;
type PartialState = (
Option<Commit<()>>,
F,
<With<S, P> as Parser<Input>>::PartialState,
);
parse_mode!(Input);
#[inline]
fn parse_mode_impl<M>(
&mut self,
mode: M,
input: &mut Input,
state: &mut Self::PartialState,
) -> ParseResult<Self::Output, Input::Error>
where
M: ParseMode,
{
let (ref mut parsed_one, ref mut elements, ref mut child_state) = *state;
let rest = match *parsed_one {
Some(rest) => rest,
None => {
let (first, rest) =
ctry!(self
.parser
.parse_mode(mode, input, &mut child_state.B.state));
elements.extend(Some(first));
rest
}
};
rest.combine_commit(move |_| {
let rest = (&mut self.separator).with(&mut self.parser);
let mut iter = Iter::new(rest, mode, input, child_state);
elements.extend(iter.by_ref());
iter.into_result_fast(elements).map(|x| {
*parsed_one = None;
x
})
})
}
fn add_committed_expected_error(&mut self, errors: &mut Tracked<<Input as StreamOnce>::Error>) {
self.separator.add_error(errors)
}
forward_parser!(Input, add_error parser_count, parser);
}
/// Parses `parser` one or more time separated by `separator`, returning a collection with the
/// values from `p`.
///
/// If the returned collection cannot be inferred type annotations must be supplied, either by
/// annotating the resulting type binding `let collection: Vec<_> = ...` or by specializing when
/// calling `sep_by`, `sep_by1::<Vec<_>, _, _>(...)`.
///
/// ```
/// # extern crate combine;
/// # use combine::*;
/// # use combine::parser::char::digit;
/// # use combine::stream::easy;
/// # use combine::stream::position::{self, SourcePosition};
/// # fn main() {
/// let mut parser = sep_by1(digit(), token(','));
/// let result_ok = parser.easy_parse(position::Stream::new("1,2,3"))
/// .map(|(vec, state)| (vec, state.input));
/// assert_eq!(result_ok, Ok((vec!['1', '2', '3'], "")));
/// let result_err = parser.easy_parse(position::Stream::new(""));
/// assert_eq!(result_err, Err(easy::Errors {
/// position: SourcePosition::default(),
/// errors: vec![
/// easy::Error::end_of_input(),
/// easy::Error::Expected("digit".into())
/// ]
/// }));
/// # }
/// ```
pub fn sep_by1<F, Input, P, S>(parser: P, separator: S) -> SepBy1<F, P, S>
where
Input: Stream,
F: Extend<P::Output> + Default,
P: Parser<Input>,
S: Parser<Input>,
{
SepBy1 {
parser,
separator,
_marker: PhantomData,
}
}
#[derive(Copy, Clone)]
pub struct SepEndBy<F, P, S> {
parser: P,
separator: S,
_marker: PhantomData<fn() -> F>,
}
impl<F, Input, P, S> Parser<Input> for SepEndBy<F, P, S>
where
Input: Stream,
F: Extend<P::Output> + Default,
P: Parser<Input>,
S: Parser<Input>,
{
type Output = F;
type PartialState = <Or<
SepEndBy1<F, P, S>,
FnParser<Input, fn(&mut Input) -> StdParseResult<F, Input>>,
> as Parser<Input>>::PartialState;
parse_mode!(Input);
#[inline]
fn parse_mode_impl<M>(
&mut self,
mode: M,
input: &mut Input,
state: &mut Self::PartialState,
) -> ParseResult<Self::Output, Input::Error>
where
M: ParseMode,
{
sep_end_by1(&mut self.parser, &mut self.separator)
.or(parser(|_| Ok((F::default(), Commit::Peek(())))))
.parse_mode(mode, input, state)
}
fn add_error(&mut self, errors: &mut Tracked<<Input as StreamOnce>::Error>) {
self.parser.add_error(errors)
}
}
/// Parses `parser` zero or more times separated and ended by `separator`, returning a collection
/// with the values from `p`.
///
/// If the returned collection cannot be inferred type annotations must be supplied, either by
/// annotating the resulting type binding `let collection: Vec<_> = ...` or by specializing when
/// calling `sep_by`, `sep_by::<Vec<_>, _, _>(...)`
///
/// ```
/// # extern crate combine;
/// # use combine::*;
/// # use combine::parser::char::digit;
/// # fn main() {
/// let mut parser = sep_end_by(digit(), token(';'));
/// let result_ok = parser.parse("1;2;3;");
/// assert_eq!(result_ok, Ok((vec!['1', '2', '3'], "")));
/// let result_ok2 = parser.parse("1;2;3");
/// assert_eq!(result_ok2, Ok((vec!['1', '2', '3'], "")));
/// # }
/// ```
pub fn sep_end_by<F, Input, P, S>(parser: P, separator: S) -> SepEndBy<F, P, S>
where
Input: Stream,
F: Extend<P::Output> + Default,
P: Parser<Input>,
S: Parser<Input>,
{
SepEndBy {
parser,
separator,
_marker: PhantomData,
}
}
#[derive(Copy, Clone)]
pub struct SepEndBy1<F, P, S> {
parser: P,
separator: S,
_marker: PhantomData<fn() -> F>,
}
impl<F, Input, P, S> Parser<Input> for SepEndBy1<F, P, S>
where
Input: Stream,
F: Extend<P::Output> + Default,
P: Parser<Input>,
S: Parser<Input>,
{
type Output = F;
type PartialState = (
Option<Commit<()>>,
F,
<With<S, Optional<P>> as Parser<Input>>::PartialState,
);
parse_mode!(Input);
#[inline]
fn parse_mode_impl<M>(
&mut self,
mode: M,
input: &mut Input,
state: &mut Self::PartialState,
) -> ParseResult<Self::Output, Input::Error>
where
M: ParseMode,
{
let (ref mut parsed_one, ref mut elements, ref mut child_state) = *state;
let rest = match *parsed_one {
Some(rest) => rest,
None => {
let (first, rest) =
ctry!(self
.parser
.parse_mode(mode, input, &mut child_state.B.state));
*parsed_one = Some(rest);
elements.extend(Some(first));
rest
}
};
rest.combine_commit(|_| {
let rest = (&mut self.separator).with(optional(&mut self.parser));
let mut iter = Iter::new(rest, mode, input, child_state);
// Parse elements until `self.parser` returns `None`
elements.extend(iter.by_ref().scan((), |_, x| x));
if iter.committed {
*parsed_one = Some(Commit::Commit(()));
}
iter.into_result_fast(elements).map(|x| {
*parsed_one = None;
x
})
})
}
fn add_error(&mut self, errors: &mut Tracked<<Input as StreamOnce>::Error>) {
self.parser.add_error(errors)
}
}
/// Parses `parser` one or more times separated and ended by `separator`, returning a collection
/// with the values from `p`.
///
/// If the returned collection cannot be inferred type annotations must be
/// supplied, either by annotating the resulting type binding `let collection: Vec<_> = ...` or by
/// specializing when calling `sep_by`, `sep_by1::<Vec<_>, _, _>(...)`.
///
/// ```
/// # extern crate combine;
/// # use combine::*;
/// # use combine::parser::char::digit;
/// # use combine::stream::easy;
/// # use combine::stream::position::{self, SourcePosition};
/// # fn main() {
/// let mut parser = sep_end_by1(digit(), token(';'));
/// let result_ok = parser.easy_parse(position::Stream::new("1;2;3;"))
/// .map(|(vec, state)| (vec, state.input));
/// assert_eq!(result_ok, Ok((vec!['1', '2', '3'], "")));
/// let result_err = parser.easy_parse(position::Stream::new(""));
/// assert_eq!(result_err, Err(easy::Errors {
/// position: SourcePosition::default(),
/// errors: vec![
/// easy::Error::end_of_input(),
/// easy::Error::Expected("digit".into())
/// ]
/// }));
/// # }
/// ```
pub fn sep_end_by1<F, Input, P, S>(parser: P, separator: S) -> SepEndBy1<F, P, S>
where
Input: Stream,
F: Extend<P::Output> + Default,
P: Parser<Input>,
S: Parser<Input>,
{
SepEndBy1 {
parser,
separator,
_marker: PhantomData,
}
}
#[derive(Copy, Clone)]
pub struct Chainl1<P, Op>(P, Op);
impl<Input, P, Op> Parser<Input> for Chainl1<P, Op>
where
Input: Stream,
P: Parser<Input>,
Op: Parser<Input>,
Op::Output: FnOnce(P::Output, P::Output) -> P::Output,
{
type Output = P::Output;
type PartialState = (
Option<(P::Output, Commit<()>)>,
<(Op, P) as Parser<Input>>::PartialState,
);
parse_mode!(Input);
#[inline]
fn parse_mode_impl<M>(
&mut self,
mut mode: M,
input: &mut Input,
state: &mut Self::PartialState,
) -> ParseResult<Self::Output, Input::Error>
where
M: ParseMode,
{
let (ref mut l_state, ref mut child_state) = *state;
let (mut l, mut committed) = match l_state.take() {
Some(x) => x,
None => {
let x = ctry!(self.0.parse_partial(input, &mut child_state.B.state));
mode.set_first();
x
}
};
loop {
let before = input.checkpoint();
match (&mut self.1, &mut self.0)
.parse_mode(mode, input, child_state)
.into()
{
Ok(((op, r), rest)) => {
l = op(l, r);
committed = committed.merge(rest);
mode.set_first();
}
Err(Commit::Commit(err)) => {
*l_state = Some((l, committed));
return CommitErr(err.error);
}
Err(Commit::Peek(_)) => {
ctry!(input.reset(before).committed());
break;
}
}
}
Ok((l, committed)).into()
}
fn add_error(&mut self, errors: &mut Tracked<<Input as StreamOnce>::Error>) {
self.0.add_error(errors)
}
}
/// Parses `p` 1 or more times separated by `op`. The value returned is the one produced by the
/// left associative application of the function returned by the parser `op`.
///
/// ```
/// # extern crate combine;
/// # use combine::*;
/// # use combine::parser::char::digit;
/// # fn main() {
/// let number = digit().map(|c: char| c.to_digit(10).unwrap());
/// let sub = token('-').map(|_| |l: u32, r: u32| l - r);
/// let mut parser = chainl1(number, sub);
/// assert_eq!(parser.parse("9-3-5"), Ok((1, "")));
/// # }
/// ```
pub fn chainl1<Input, P, Op>(parser: P, op: Op) -> Chainl1<P, Op>
where
Input: Stream,
P: Parser<Input>,
Op: Parser<Input>,
Op::Output: FnOnce(P::Output, P::Output) -> P::Output,
{
Chainl1(parser, op)
}
#[derive(Copy, Clone)]
pub struct Chainr1<P, Op>(P, Op);
impl<Input, P, Op> Parser<Input> for Chainr1<P, Op>
where
Input: Stream,
P: Parser<Input>,
Op: Parser<Input>,
Op::Output: FnOnce(P::Output, P::Output) -> P::Output,
{
type Output = P::Output;
type PartialState = ();
#[inline]
fn parse_lazy(&mut self, input: &mut Input) -> ParseResult<P::Output, Input::Error> {
// FIXME FastResult
let (mut l, mut committed) = ctry!(self.0.parse_lazy(input));
loop {
let before = input.checkpoint();
let op = match self.1.parse_lazy(input).into() {
Ok((x, rest)) => {
committed = committed.merge(rest);
x
}
Err(Commit::Commit(err)) => return CommitErr(err.error),
Err(Commit::Peek(_)) => {
ctry!(input.reset(before).committed());
break;
}
};
let before = input.checkpoint();
match self.parse_lazy(input).into() {
Ok((r, rest)) => {
l = op(l, r);
committed = committed.merge(rest);
}
Err(Commit::Commit(err)) => return CommitErr(err.error),
Err(Commit::Peek(_)) => {
ctry!(input.reset(before).committed());
break;
}
}
}
Ok((l, committed)).into()
}
fn add_error(&mut self, errors: &mut Tracked<<Input as StreamOnce>::Error>) {
self.0.add_error(errors)
}
}
/// Parses `p` one or more times separated by `op`. The value returned is the one produced by the
/// right associative application of the function returned by `op`.
///
/// ```
/// # extern crate combine;
/// # use combine::*;
/// # use combine::parser::char::digit;
/// # fn main() {
/// let number = digit().map(|c: char| c.to_digit(10).unwrap());
/// let pow = token('^').map(|_| |l: u32, r: u32| l.pow(r));
/// let mut parser = chainr1(number, pow);
/// assert_eq!(parser.parse("2^3^2"), Ok((512, "")));
/// }
/// ```
pub fn chainr1<Input, P, Op>(parser: P, op: Op) -> Chainr1<P, Op>
where
Input: Stream,
P: Parser<Input>,
Op: Parser<Input>,
Op::Output: FnOnce(P::Output, P::Output) -> P::Output,
{
Chainr1(parser, op)
}
#[derive(Copy, Clone)]
pub struct TakeUntil<F, P> {
end: P,
_marker: PhantomData<fn() -> F>,
}
impl<F, Input, P> Parser<Input> for TakeUntil<F, P>
where
Input: Stream,
F: Extend<<Input as StreamOnce>::Token> + Default,
P: Parser<Input>,
{
type Output = F;
type PartialState = (F, P::PartialState);
parse_mode!(Input);
#[inline]
fn parse_mode_impl<M>(
&mut self,
mode: M,
input: &mut Input,
state: &mut Self::PartialState,
) -> ParseResult<Self::Output, Input::Error>
where
M: ParseMode,
{
let (ref mut output, ref mut end_state) = *state;
let mut committed = Commit::Peek(());
loop {
let before = input.checkpoint();
match self.end.parse_mode(mode, input, end_state).into() {
Ok((_, rest)) => {
ctry!(input.reset(before).committed());
return match committed.merge(rest) {
Commit::Commit(()) => CommitOk(mem::take(output)),
Commit::Peek(()) => PeekOk(mem::take(output)),
};
}
Err(Commit::Peek(_)) => {
ctry!(input.reset(before).committed());
output.extend(Some(ctry!(uncons(input)).0));
committed = Commit::Commit(());
}
Err(Commit::Commit(e)) => {
ctry!(input.reset(before).committed());
return CommitErr(e.error);
}
};
}
}
}
/// Takes input until `end` is encountered or `end` indicates that it has committed input before
/// failing (`attempt` can be used to make it look like it has not committed any input)
///
/// ```
/// # extern crate combine;
/// # use combine::*;
/// # use combine::parser::char;
/// # use combine::parser::byte;
/// # use combine::parser::combinator::attempt;
/// # use combine::parser::repeat::take_until;
/// # fn main() {
/// let mut char_parser = take_until(char::digit());
/// assert_eq!(char_parser.parse("abc123"), Ok(("abc".to_string(), "123")));
///
/// let mut byte_parser = take_until(byte::bytes(&b"TAG"[..]));
/// assert_eq!(byte_parser.parse(&b"123TAG"[..]), Ok((b"123".to_vec(), &b"TAG"[..])));
/// assert!(byte_parser.parse(&b"123TATAG"[..]).is_err());
///
/// // `attempt` must be used if the `end` should be consume input before failing
/// let mut byte_parser = take_until(attempt(byte::bytes(&b"TAG"[..])));
/// assert_eq!(byte_parser.parse(&b"123TATAG"[..]), Ok((b"123TA".to_vec(), &b"TAG"[..])));
/// # }
/// ```
pub fn take_until<F, Input, P>(end: P) -> TakeUntil<F, P>
where
Input: Stream,
F: Extend<<Input as StreamOnce>::Token> + Default,
P: Parser<Input>,
{
TakeUntil {
end,
_marker: PhantomData,
}
}
parser! {
pub struct SkipUntil;
type PartialState = <With<TakeUntil<Sink, P>, Value<Input, ()>> as Parser<Input>>::PartialState;
/// Skips input until `end` is encountered or `end` indicates that it has committed input before
/// failing (`attempt` can be used to make it look like it has not committed any input)
///
/// ```
/// # extern crate combine;
/// # use combine::*;
/// # use combine::parser::char;
/// # use combine::parser::byte;
/// # use combine::parser::combinator::attempt;
/// # use combine::parser::repeat::skip_until;
/// # fn main() {
/// let mut char_parser = skip_until(char::digit());
/// assert_eq!(char_parser.parse("abc123"), Ok(((), "123")));
///
/// let mut byte_parser = skip_until(byte::bytes(&b"TAG"[..]));
/// assert_eq!(byte_parser.parse(&b"123TAG"[..]), Ok(((), &b"TAG"[..])));
/// assert!(byte_parser.parse(&b"123TATAG"[..]).is_err());
///
/// // `attempt` must be used if the `end` should consume input before failing
/// let mut byte_parser = skip_until(attempt(byte::bytes(&b"TAG"[..])));
/// assert_eq!(byte_parser.parse(&b"123TATAG"[..]), Ok(((), &b"TAG"[..])));
/// # }
/// ```
pub fn skip_until[Input, P](end: P)(Input) -> ()
where [
P: Parser<Input>,
]
{
take_until::<Sink, _, _>(end).with(value(()))
}
}
#[derive(Copy, Clone)]
pub struct RepeatUntil<F, P, E> {
parser: P,
end: E,
_marker: PhantomData<fn() -> F>,
}
impl<F, Input, P, E> Parser<Input> for RepeatUntil<F, P, E>
where
Input: Stream,
F: Extend<P::Output> + Default,
P: Parser<Input>,
E: Parser<Input>,
{
type Output = F;
type PartialState = (F, bool, P::PartialState, E::PartialState);
parse_mode!(Input);
#[inline]
fn parse_mode_impl<M>(
&mut self,
mut mode: M,
input: &mut Input,
state: &mut Self::PartialState,
) -> ParseResult<Self::Output, Input::Error>
where
M: ParseMode,
{
let (output, is_parse, parse_state, end_state) = state;
let mut committed = Commit::Peek(());
loop {
if *is_parse {
let (token, c) = ctry!(self.parser.parse_mode(mode, input, parse_state));
output.extend(Some(token));
committed = committed.merge(c);
*is_parse = false;
} else {
let before = input.checkpoint();
match self.end.parse_mode(mode, input, end_state).into() {
Ok((_, rest)) => {
ctry!(input.reset(before).committed());
return match committed.merge(rest) {
Commit::Commit(()) => CommitOk(mem::take(output)),
Commit::Peek(()) => PeekOk(mem::take(output)),
};
}
Err(Commit::Peek(_)) => {
ctry!(input.reset(before).committed());
mode.set_first();
*is_parse = true;
}
Err(Commit::Commit(e)) => {
ctry!(input.reset(before).committed());
return CommitErr(e.error);
}
}
}
}
}
}
pub fn repeat_until<F, Input, P, E>(parser: P, end: E) -> RepeatUntil<F, P, E>
where
Input: Stream,
F: Extend<P::Output> + Default,
P: Parser<Input>,
E: Parser<Input>,
{
RepeatUntil {
parser,
end,
_marker: PhantomData,
}
}
parser! {
pub struct SkipRepeatUntil;
type PartialState = <With<RepeatUntil<Sink, P, E>, Value<Input, ()>> as Parser<Input>>::PartialState;
/// Skips input until `end` is encountered or `end` indicates that it has committed input before
/// failing (`attempt` can be used to continue skipping even if `end` has committed input)
///
/// ```
/// # extern crate combine;
/// # use combine::*;
/// # use combine::parser::char;
/// # use combine::parser::byte;
/// # use combine::parser::combinator::attempt;
/// # use combine::parser::repeat::skip_until;
/// # fn main() {
/// let mut char_parser = skip_until(char::digit());
/// assert_eq!(char_parser.parse("abc123"), Ok(((), "123")));
///
/// let mut byte_parser = skip_until(byte::bytes(&b"TAG"[..]));
/// assert_eq!(byte_parser.parse(&b"123TAG"[..]), Ok(((), &b"TAG"[..])));
/// assert!(byte_parser.parse(&b"123TATAG"[..]).is_err());
///
/// // `attempt` must be used because the `end` will commit to `TA` before failing,
/// // but we want to continue skipping
/// let mut byte_parser = skip_until(attempt(byte::bytes(&b"TAG"[..])));
/// assert_eq!(byte_parser.parse(&b"123TATAG"[..]), Ok(((), &b"TAG"[..])));
/// }
/// ```
pub fn repeat_skip_until[Input, P, E](parser: P, end: E)(Input) -> ()
where [
P: Parser<Input>,
E: Parser<Input>,
]
{
repeat_until::<Sink, _, _, _>(parser, end).with(value(()))
}
}
#[derive(Default)]
pub struct EscapedState<T, U>(PhantomData<(T, U)>);
pub struct Escaped<P, Q, I> {
parser: P,
escape: I,
escape_parser: Q,
}
impl<Input, P, Q> Parser<Input> for Escaped<P, Q, Input::Token>
where
Input: Stream,
P: Parser<Input>,
<Input as StreamOnce>::Token: PartialEq,
Q: Parser<Input>,
{
type Output = ();
type PartialState = EscapedState<P::PartialState, Q::PartialState>;
fn parse_lazy(&mut self, input: &mut Input) -> ParseResult<Self::Output, Input::Error> {
let mut committed = Commit::Peek(());
loop {
match self.parser.parse_lazy(input) {
PeekOk(_) => {}
CommitOk(_) => {
committed = Commit::Commit(());
}
PeekErr(_) => {
let checkpoint = input.checkpoint();
match uncons(input) {
CommitOk(ref c) | PeekOk(ref c) if *c == self.escape => {
match self.escape_parser.parse_committed_mode(
FirstMode,
input,
&mut Default::default(),
) {
PeekOk(_) => {}
CommitOk(_) => {
committed = Commit::Commit(());
}
CommitErr(err) => return CommitErr(err),
PeekErr(err) => {
return CommitErr(err.error);
}
}
}
CommitErr(err) => {
return CommitErr(err);
}
_ => {
ctry!(input.reset(checkpoint).committed());
return if committed.is_peek() {
PeekOk(())
} else {
CommitOk(())
};
}
}
}
CommitErr(err) => return CommitErr(err),
}
}
}
fn add_error(&mut self, errors: &mut Tracked<<Input as StreamOnce>::Error>) {
use crate::error;
self.parser.add_error(errors);
errors.error.add_expected(error::Token(self.escape.clone()));
}
}
/// Parses an escaped string by first applying `parser` which accept the normal characters which do
/// not need escaping. Once `parser` can not consume any more input it checks if the next token
/// is `escape`. If it is then `escape_parser` is used to parse the escaped character and then
/// resumes parsing using `parser`. If `escape` was not found then the parser finishes
/// successfully.
///
/// This returns `()` since there isn't a good way to collect the output of the parsers so it is
/// best paired with one of the `recognize` parsers.
///
/// ```
/// # extern crate combine;
/// # use combine::*;
/// # use combine::parser::repeat::escaped;
/// # use combine::parser::char;
/// # use combine::parser::range::{recognize, take_while1};
/// # fn main() {
/// let mut parser = recognize(
/// escaped(take_while1(|c| c != '"' && c != '\\'), '\\', one_of(r#"nr"\"#.chars()))
/// );
/// assert_eq!(parser.parse(r#"ab\"12\n\rc""#), Ok((r#"ab\"12\n\rc"#, r#"""#)));
/// assert!(parser.parse(r#"\"#).is_err());
/// assert!(parser.parse(r#"\a"#).is_err());
/// }
/// ```
pub fn escaped<Input, P, Q>(
parser: P,
escape: <Input as StreamOnce>::Token,
escape_parser: Q,
) -> Escaped<P, Q, Input::Token>
where
Input: Stream,
P: Parser<Input>,
<Input as StreamOnce>::Token: PartialEq,
Q: Parser<Input>,
{
Escaped {
parser,
escape,
escape_parser,
}
}
pub struct Iterate<F, I, P> {
parser: P,
iterable: I,
_marker: PhantomData<fn() -> F>,
}
impl<'s, 'a, P, Q, I, J, F> Parser<I> for Iterate<F, J, P>
where
P: FnMut(&J::Item, &mut I) -> Q,
Q: Parser<I>,
I: Stream,
J: IntoIterator + Clone,
F: Extend<Q::Output> + Default,
{
type Output = F;
type PartialState = (
Option<(J::IntoIter, Option<J::Item>)>,
bool,
F,
Q::PartialState,
);
parse_mode!(I);
fn parse_mode_impl<M>(
&mut self,
mut mode: M,
input: &mut I,
state: &mut Self::PartialState,
) -> ParseResult<Self::Output, I::Error>
where
M: ParseMode,
{
let (opt_iter, committed, buf, next) = state;
let (iter, next_item) = match opt_iter {
Some(iter) if !mode.is_first() => iter,
_ => {
*opt_iter = Some((self.iterable.clone().into_iter(), None));
opt_iter.as_mut().unwrap()
}
};
let mut consume = |item: J::Item| {
let mut parser = (self.parser)(&item, input);
let before = input.checkpoint();
match parser.parse_mode(mode, input, next) {
PeekOk(v) => {
mode.set_first();
Ok(v)
}
CommitOk(v) => {
mode.set_first();
*committed = true;
Ok(v)
}
PeekErr(err) => {
if let Err(err) = input.reset(before) {
return Err((item, CommitErr(err)));
}
Err((
item,
if *committed {
CommitErr(err.error)
} else {
PeekErr(err)
},
))
}
CommitErr(err) => Err((item, CommitErr(err))),
}
};
let result = (|| {
if let Some(item) = next_item.take() {
buf.extend(Some(consume(item)?));
}
let mut result = Ok(());
let size_hint = iter.size_hint();
buf.extend(suggest_size_hint(
iter.scan((), |_, item| match consume(item) {
Ok(item) => Some(item),
Err(err) => {
result = Err(err);
None
}
}),
size_hint,
));
result
})();
if let Err((item, err)) = result {
*next_item = Some(item);
return err;
}
opt_iter.take();
let value = mem::take(buf);
if *committed {
*committed = false;
CommitOk(value)
} else {
PeekOk(value)
}
}
}
///
/// ```
/// # use combine::parser::repeat::{count_min_max, iterate};
/// # use combine::*;
///
/// assert_eq!(
/// iterate(0..3, |&i, _| count_min_max(i, i, any())).parse("abbccc"),
/// Ok((vec!["".to_string(), "a".to_string(), "bb".to_string()], "ccc")),
/// );
/// ```
pub fn iterate<F, J, P, I, Q>(iterable: J, parser: P) -> Iterate<F, J, P>
where
P: FnMut(&J::Item, &mut I) -> Q,
Q: Parser<I>,
I: Stream,
J: IntoIterator + Clone,
F: Extend<Q::Output> + Default,
{
Iterate {
parser,
iterable,
_marker: PhantomData,
}
}