//! 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, F: Extend + Default, ] { count_min_max(0, *count, parser) } } parser! { pub struct SkipCount; type PartialState = , Value> as Parser>::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 ] { self::count::(*count, parser.map(|_| ())).with(value(())) } } #[derive(Copy, Clone)] pub struct CountMinMax { parser: P, min: usize, max: usize, _marker: PhantomData F>, } struct SuggestSizeHint { iterator: I, min: usize, max: Option, } impl Iterator for SuggestSizeHint where I: Iterator, { type Item = I::Item; #[inline] fn next(&mut self) -> Option { self.iterator.next() } #[inline] fn size_hint(&self) -> (usize, Option) { (self.min, self.max) } } fn suggest_size_hint(iterator: I, (min, max): (usize, Option)) -> SuggestSizeHint 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 Parser for CountMinMax where Input: Stream, P: Parser, F: Extend + Default, { type Output = F; type PartialState = (usize, F, P::PartialState); parse_mode!(Input); #[inline] fn parse_mode_impl( &mut self, mode: M, input: &mut Input, state: &mut Self::PartialState, ) -> ParseResult 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<::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(min: usize, max: usize, parser: P) -> CountMinMax where Input: Stream, P: Parser, F: Extend + Default, { assert!(min <= max); CountMinMax { parser, min, max, _marker: PhantomData, } } parser! { pub struct SkipCountMinMax; type PartialState = , Value> as Parser>::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, ] { count_min_max::(*min, *max, parser.map(|_| ())).with(value(())) } } pub struct Iter<'a, Input, P, S, M> where Input: Stream, P: Parser, { parser: P, input: &'a mut Input, committed: bool, state: State<::Error>, partial_state: S, mode: M, } enum State { Ok, PeekErr(E), CommitErr(E), } impl<'a, Input, P, S, M> Iter<'a, Input, P, S, M> where Input: Stream, P: Parser, S: BorrowMut, { 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(self, value: O) -> StdParseResult { self.into_result_(value).into() } fn into_result_(self, value: O) -> ParseResult { match self.state { State::Ok | State::PeekErr(_) => { if self.committed { CommitOk(value) } else { PeekOk(value) } } State::CommitErr(e) => CommitErr(e), } } fn into_result_fast(self, value: &mut O) -> ParseResult 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( self, err: <::Error as ParseError< ::Token, ::Range, ::Position, >>::StreamError, ) -> ParseResult { match self.state { State::Ok => { let err = ::Error::from_error(self.input.position(), err); if self.committed { CommitErr(err) } else { PeekErr(err.into()) } } State::PeekErr(mut e) => { let err = ::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, S: BorrowMut, M: ParseMode, { type Item = P::Output; fn next(&mut self) -> Option { 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(P, PhantomData); impl Parser for Many where Input: Stream, P: Parser, F: Extend + Default, { type Output = F; type PartialState = (F, P::PartialState); parse_mode!(Input); #[inline] fn parse_mode_impl( &mut self, mode: M, input: &mut Input, state: &mut Self::PartialState, ) -> ParseResult 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<::Error>) { self.0.add_error(errors) } fn add_committed_expected_error(&mut self, errors: &mut Tracked<::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::, _, _>(...)`. /// /// 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(p: P) -> Many where Input: Stream, P: Parser, F: Extend + Default, { Many(p, PhantomData) } #[derive(Copy, Clone)] pub struct Many1(P, PhantomData F>); impl Parser for Many1 where Input: Stream, F: Extend + Default, P: Parser, { type Output = F; type PartialState = (bool, bool, F, P::PartialState); parse_mode!(Input); #[inline] fn parse_mode_impl( &mut self, mut mode: M, input: &mut Input, state: &mut Self::PartialState, ) -> ParseResult 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<::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::, _>(...)`. /// /// 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::, _, _>(digit()) /// .parse("A123"); /// assert!(result.is_err()); /// # } /// ``` pub fn many1(p: P) -> Many1 where Input: Stream, F: Extend + Default, P: Parser, { Many1(p, PhantomData) } #[derive(Clone)] #[doc(hidden)] // FIXME Should not be public pub struct Sink; impl Default for Sink { fn default() -> Self { Sink } } impl Extend for Sink { fn extend(&mut self, iter: T) where T: IntoIterator, { for _ in iter {} } } parser! { pub struct SkipMany; type PartialState = >> as Parser>::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, ] { ignore(many::(ignore(p))) } } parser! { pub struct SkipMany1; type PartialState = >> as Parser>::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, ] { ignore(many1::(ignore(p))) } } #[derive(Copy, Clone)] pub struct SepBy { parser: P, separator: S, _marker: PhantomData F>, } impl Parser for SepBy where Input: Stream, F: Extend + Default, P: Parser, S: Parser, { type Output = F; type PartialState = , FnParser StdParseResult>, > as Parser>::PartialState; parse_mode!(Input); #[inline] fn parse_mode_impl( &mut self, mode: M, input: &mut Input, state: &mut Self::PartialState, ) -> ParseResult 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<::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::, _, _>(...)`. /// /// ``` /// # 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(parser: P, separator: S) -> SepBy where Input: Stream, F: Extend + Default, P: Parser, S: Parser, { SepBy { parser, separator, _marker: PhantomData, } } #[derive(Copy, Clone)] pub struct SepBy1 { parser: P, separator: S, _marker: PhantomData F>, } impl Parser for SepBy1 where Input: Stream, F: Extend + Default, P: Parser, S: Parser, { type Output = F; type PartialState = ( Option>, F, as Parser>::PartialState, ); parse_mode!(Input); #[inline] fn parse_mode_impl( &mut self, mode: M, input: &mut Input, state: &mut Self::PartialState, ) -> ParseResult 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<::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::, _, _>(...)`. /// /// ``` /// # 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(parser: P, separator: S) -> SepBy1 where Input: Stream, F: Extend + Default, P: Parser, S: Parser, { SepBy1 { parser, separator, _marker: PhantomData, } } #[derive(Copy, Clone)] pub struct SepEndBy { parser: P, separator: S, _marker: PhantomData F>, } impl Parser for SepEndBy where Input: Stream, F: Extend + Default, P: Parser, S: Parser, { type Output = F; type PartialState = , FnParser StdParseResult>, > as Parser>::PartialState; parse_mode!(Input); #[inline] fn parse_mode_impl( &mut self, mode: M, input: &mut Input, state: &mut Self::PartialState, ) -> ParseResult 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<::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::, _, _>(...)` /// /// ``` /// # 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(parser: P, separator: S) -> SepEndBy where Input: Stream, F: Extend + Default, P: Parser, S: Parser, { SepEndBy { parser, separator, _marker: PhantomData, } } #[derive(Copy, Clone)] pub struct SepEndBy1 { parser: P, separator: S, _marker: PhantomData F>, } impl Parser for SepEndBy1 where Input: Stream, F: Extend + Default, P: Parser, S: Parser, { type Output = F; type PartialState = ( Option>, F, > as Parser>::PartialState, ); parse_mode!(Input); #[inline] fn parse_mode_impl( &mut self, mode: M, input: &mut Input, state: &mut Self::PartialState, ) -> ParseResult 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<::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::, _, _>(...)`. /// /// ``` /// # 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(parser: P, separator: S) -> SepEndBy1 where Input: Stream, F: Extend + Default, P: Parser, S: Parser, { SepEndBy1 { parser, separator, _marker: PhantomData, } } #[derive(Copy, Clone)] pub struct Chainl1(P, Op); impl Parser for Chainl1 where Input: Stream, P: Parser, Op: Parser, Op::Output: FnOnce(P::Output, P::Output) -> P::Output, { type Output = P::Output; type PartialState = ( Option<(P::Output, Commit<()>)>, <(Op, P) as Parser>::PartialState, ); parse_mode!(Input); #[inline] fn parse_mode_impl( &mut self, mut mode: M, input: &mut Input, state: &mut Self::PartialState, ) -> ParseResult 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<::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(parser: P, op: Op) -> Chainl1 where Input: Stream, P: Parser, Op: Parser, Op::Output: FnOnce(P::Output, P::Output) -> P::Output, { Chainl1(parser, op) } #[derive(Copy, Clone)] pub struct Chainr1(P, Op); impl Parser for Chainr1 where Input: Stream, P: Parser, Op: Parser, 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 { // 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<::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(parser: P, op: Op) -> Chainr1 where Input: Stream, P: Parser, Op: Parser, Op::Output: FnOnce(P::Output, P::Output) -> P::Output, { Chainr1(parser, op) } #[derive(Copy, Clone)] pub struct TakeUntil { end: P, _marker: PhantomData F>, } impl Parser for TakeUntil where Input: Stream, F: Extend<::Token> + Default, P: Parser, { type Output = F; type PartialState = (F, P::PartialState); parse_mode!(Input); #[inline] fn parse_mode_impl( &mut self, mode: M, input: &mut Input, state: &mut Self::PartialState, ) -> ParseResult 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(end: P) -> TakeUntil where Input: Stream, F: Extend<::Token> + Default, P: Parser, { TakeUntil { end, _marker: PhantomData, } } parser! { pub struct SkipUntil; type PartialState = , Value> as Parser>::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, ] { take_until::(end).with(value(())) } } #[derive(Copy, Clone)] pub struct RepeatUntil { parser: P, end: E, _marker: PhantomData F>, } impl Parser for RepeatUntil where Input: Stream, F: Extend + Default, P: Parser, E: Parser, { type Output = F; type PartialState = (F, bool, P::PartialState, E::PartialState); parse_mode!(Input); #[inline] fn parse_mode_impl( &mut self, mut mode: M, input: &mut Input, state: &mut Self::PartialState, ) -> ParseResult 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(parser: P, end: E) -> RepeatUntil where Input: Stream, F: Extend + Default, P: Parser, E: Parser, { RepeatUntil { parser, end, _marker: PhantomData, } } parser! { pub struct SkipRepeatUntil; type PartialState = , Value> as Parser>::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, E: Parser, ] { repeat_until::(parser, end).with(value(())) } } #[derive(Default)] pub struct EscapedState(PhantomData<(T, U)>); pub struct Escaped { parser: P, escape: I, escape_parser: Q, } impl Parser for Escaped where Input: Stream, P: Parser, ::Token: PartialEq, Q: Parser, { type Output = (); type PartialState = EscapedState; fn parse_lazy(&mut self, input: &mut Input) -> ParseResult { 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<::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( parser: P, escape: ::Token, escape_parser: Q, ) -> Escaped where Input: Stream, P: Parser, ::Token: PartialEq, Q: Parser, { Escaped { parser, escape, escape_parser, } } pub struct Iterate { parser: P, iterable: I, _marker: PhantomData F>, } impl<'s, 'a, P, Q, I, J, F> Parser for Iterate where P: FnMut(&J::Item, &mut I) -> Q, Q: Parser, I: Stream, J: IntoIterator + Clone, F: Extend + Default, { type Output = F; type PartialState = ( Option<(J::IntoIter, Option)>, bool, F, Q::PartialState, ); parse_mode!(I); fn parse_mode_impl( &mut self, mut mode: M, input: &mut I, state: &mut Self::PartialState, ) -> ParseResult 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(iterable: J, parser: P) -> Iterate where P: FnMut(&J::Item, &mut I) -> Q, Q: Parser, I: Stream, J: IntoIterator + Clone, F: Extend + Default, { Iterate { parser, iterable, _marker: PhantomData, } }