//! 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, } }