//! Various combinators which do not fit anywhere else. use crate::{ error::{ Info, ParseError, ParseResult::{self, *}, ResultExt, StreamError, Tracked, }, lib::{fmt, marker::PhantomData, mem, str}, parser::ParseMode, stream::{input_at_eof, span::Span, ResetStream, Stream, StreamErrorFor, StreamOnce}, Parser, }; #[cfg(feature = "alloc")] use alloc::{boxed::Box, string::String, vec::Vec}; #[cfg(feature = "alloc")] use crate::lib::any::Any; #[derive(Copy, Clone)] pub struct NotFollowedBy

(P); impl Parser for NotFollowedBy

where Input: Stream, P: Parser, { type Output = (); type PartialState = P::PartialState; parse_mode!(Input); #[inline] fn parse_mode_impl( &mut self, mode: M, input: &mut Input, state: &mut Self::PartialState, ) -> ParseResult::Error> where M: ParseMode, { let checkpoint = input.checkpoint(); let result = self.0.parse_mode(mode, input, state); ctry!(input.reset(checkpoint).committed()); match result { CommitOk(_) | PeekOk(_) => PeekErr(Input::Error::empty(input.position()).into()), CommitErr(_) | PeekErr(_) => PeekOk(()), } } #[inline] fn add_error(&mut self, _errors: &mut Tracked<::Error>) {} fn add_committed_expected_error(&mut self, _error: &mut Tracked<::Error>) { } forward_parser!(Input, parser_count, 0); } /// Succeeds only if `parser` fails. /// Never consumes any input. /// /// ``` /// # extern crate combine; /// # use combine::*; /// # use combine::parser::char::{alpha_num, string}; /// # fn main() { /// let result = string("let") /// .skip(not_followed_by(alpha_num())) /// .parse("letx") /// .map(|x| x.0); /// assert!(result.is_err()); /// /// # } /// ``` pub fn not_followed_by(parser: P) -> NotFollowedBy

where Input: Stream, P: Parser, P::Output: Into::Token, ::Range, &'static str>>, { NotFollowedBy(parser) } /* * TODO :: Rename `Try` to `Attempt` * Because this is public, it's name cannot be changed without also making a breaking change. */ #[derive(Copy, Clone)] pub struct Try

(P); impl Parser for Try

where Input: Stream, P: Parser, { type Output = O; type PartialState = P::PartialState; #[inline] fn parse_stream(&mut self, input: &mut Input) -> ParseResult::Error> { self.parse_lazy(input) } parse_mode!(Input); #[inline] fn parse_committed_mode( &mut self, mode: M, input: &mut Input, state: &mut Self::PartialState, ) -> ParseResult::Error> where M: ParseMode, { self.parse_mode(mode, input, state) } #[inline] fn parse_mode_impl( &mut self, mode: M, input: &mut Input, state: &mut Self::PartialState, ) -> ParseResult::Error> where M: ParseMode, { match self.0.parse_committed_mode(mode, input, state) { v @ CommitOk(_) | v @ PeekOk(_) | v @ PeekErr(_) => v, CommitErr(err) => { if input.is_partial() && err.is_unexpected_end_of_input() { CommitErr(err) } else { PeekErr(err.into()) } } } } forward_parser!(Input, add_error add_committed_expected_error parser_count, 0); } /// `attempt(p)` behaves as `p` except it always acts as `p` peeked instead of committed on its /// parse. /// /// ``` /// # extern crate combine; /// # use combine::*; /// # use combine::parser::char::string; /// # fn main() { /// let mut p = attempt(string("let")) /// .or(string("lex")); /// let result = p.parse("lex").map(|x| x.0); /// assert_eq!(result, Ok("lex")); /// let result = p.parse("aet").map(|x| x.0); /// assert!(result.is_err()); /// # } /// ``` pub fn attempt(p: P) -> Try

where Input: Stream, P: Parser, { Try(p) } #[derive(Copy, Clone)] pub struct LookAhead

(P); impl Parser for LookAhead

where Input: Stream, P: Parser, { type Output = O; type PartialState = (); #[inline] fn parse_lazy(&mut self, input: &mut Input) -> ParseResult::Error> { let before = input.checkpoint(); let result = self.0.parse_lazy(input); ctry!(input.reset(before).committed()); let (o, _input) = ctry!(result); PeekOk(o) } forward_parser!(Input, add_error add_committed_expected_error parser_count, 0); } /// `look_ahead(p)` acts as `p` but doesn't consume input on success. /// /// ``` /// # extern crate combine; /// # use combine::*; /// # use combine::parser::char::string; /// # fn main() { /// let mut p = look_ahead(string("test")); /// /// let result = p.parse("test str"); /// assert_eq!(result, Ok(("test", "test str"))); /// /// let result = p.parse("aet"); /// assert!(result.is_err()); /// # } /// ``` pub fn look_ahead(p: P) -> LookAhead

where Input: Stream, P: Parser, { LookAhead(p) } #[derive(Copy, Clone)] pub struct Map(P, F); impl Parser for Map where Input: Stream, P: Parser, F: FnMut(A) -> B, { type Output = B; type PartialState = P::PartialState; parse_mode!(Input); #[inline] fn parse_mode_impl( &mut self, mode: M, input: &mut Input, state: &mut Self::PartialState, ) -> ParseResult::Error> where M: ParseMode, { match self.0.parse_mode(mode, input, state) { CommitOk(x) => CommitOk((self.1)(x)), PeekOk(x) => PeekOk((self.1)(x)), CommitErr(err) => CommitErr(err), PeekErr(err) => PeekErr(err), } } forward_parser!(Input, add_error add_committed_expected_error parser_count, 0); } /// Equivalent to [`p.map(f)`]. /// /// [`p.map(f)`]: ../trait.Parser.html#method.map pub fn map(p: P, f: F) -> Map where Input: Stream, P: Parser, F: FnMut(P::Output) -> B, { Map(p, f) } #[derive(Copy, Clone)] pub struct MapInput(P, F); impl Parser for MapInput where Input: Stream, P: Parser, F: FnMut(A, &mut Input) -> B, { type Output = B; type PartialState = P::PartialState; parse_mode!(Input); #[inline] fn parse_mode_impl( &mut self, mode: M, input: &mut Input, state: &mut Self::PartialState, ) -> ParseResult::Error> where M: ParseMode, { match self.0.parse_mode(mode, input, state) { CommitOk(x) => CommitOk((self.1)(x, input)), PeekOk(x) => PeekOk((self.1)(x, input)), CommitErr(err) => CommitErr(err), PeekErr(err) => PeekErr(err), } } forward_parser!(Input, add_error add_committed_expected_error parser_count, 0); } /// Equivalent to [`p.map_input(f)`]. /// /// [`p.map_input(f)`]: ../trait.Parser.html#method.map_input pub fn map_input(p: P, f: F) -> MapInput where Input: Stream, P: Parser, F: FnMut(P::Output, &mut Input) -> B, { MapInput(p, f) } #[derive(Copy, Clone)] pub struct FlatMap(P, F); impl Parser for FlatMap where Input: Stream, P: Parser, F: FnMut(A) -> Result, { type Output = B; type PartialState = P::PartialState; parse_mode!(Input); #[inline] fn parse_mode_impl( &mut self, mode: M, input: &mut Input, state: &mut Self::PartialState, ) -> ParseResult::Error> where M: ParseMode, { match self.0.parse_mode(mode, input, state) { PeekOk(o) => match (self.1)(o) { Ok(x) => PeekOk(x), Err(err) => PeekErr(err.into()), }, CommitOk(o) => match (self.1)(o) { Ok(x) => CommitOk(x), Err(err) => CommitErr(err), }, PeekErr(err) => PeekErr(err), CommitErr(err) => CommitErr(err), } } forward_parser!(Input, add_error add_committed_expected_error parser_count, 0); } /// Equivalent to [`p.flat_map(f)`]. /// /// [`p.flat_map(f)`]: ../trait.Parser.html#method.flat_map pub fn flat_map(p: P, f: F) -> FlatMap where Input: Stream, P: Parser, F: FnMut(P::Output) -> Result::Error>, { FlatMap(p, f) } #[derive(Copy, Clone)] pub struct AndThen(P, F); impl Parser for AndThen where Input: Stream, P: Parser, F: FnMut(P::Output) -> Result, E: Into<>::StreamError>, Input::Error: ParseError, { type Output = O; type PartialState = P::PartialState; parse_mode!(Input); fn parse_mode_impl( &mut self, mode: M, input: &mut Input, state: &mut Self::PartialState, ) -> ParseResult::Error> where M: ParseMode, { let position = input.position(); let checkpoint = input.checkpoint(); match self.0.parse_mode(mode, input, state) { PeekOk(o) => match (self.1)(o) { Ok(o) => PeekOk(o), Err(err) => { let err = ::Error::from_error(position, err.into()); if input.is_partial() && input_at_eof(input) { ctry!(input.reset(checkpoint).committed()); CommitErr(err) } else { PeekErr(err.into()) } } }, CommitOk(o) => match (self.1)(o) { Ok(o) => CommitOk(o), Err(err) => { if input.is_partial() && input_at_eof(input) { ctry!(input.reset(checkpoint).committed()); } CommitErr(::Error::from_error( position, err.into(), )) } }, PeekErr(err) => PeekErr(err), CommitErr(err) => CommitErr(err), } } forward_parser!(Input, add_error add_committed_expected_error parser_count, 0); } /// Equivalent to [`p.and_then(f)`]. /// /// [`p.and_then(f)`]: ../trait.Parser.html#method.and_then pub fn and_then(p: P, f: F) -> AndThen where P: Parser, F: FnMut(P::Output) -> Result, Input: Stream, E: Into<>::StreamError>, { AndThen(p, f) } #[derive(Copy, Clone)] pub struct Recognize(P, PhantomData F>); impl Recognize { #[inline] fn recognize_result( elements: &mut F, before: ::Checkpoint, input: &mut Input, result: ParseResult::Error>, ) -> ParseResult::Error> where P: Parser, Input: Stream, F: Default + Extend, { match result { PeekOk(_) => { let last_position = input.position(); ctry!(input.reset(before).committed()); while input.position() != last_position { match input.uncons() { Ok(elem) => elements.extend(Some(elem)), Err(err) => { return PeekErr( ::Error::from_error(input.position(), err) .into(), ); } } } PeekOk(mem::take(elements)) } CommitOk(_) => { let last_position = input.position(); ctry!(input.reset(before).committed()); while input.position() != last_position { match input.uncons() { Ok(elem) => elements.extend(Some(elem)), Err(err) => { return CommitErr(::Error::from_error( input.position(), err, )); } } } CommitOk(mem::take(elements)) } CommitErr(err) => { let last_position = input.position(); ctry!(input.reset(before).committed()); while input.position() != last_position { match input.uncons() { Ok(elem) => elements.extend(Some(elem)), Err(err) => { return CommitErr(::Error::from_error( input.position(), err, )); } } } CommitErr(err) } PeekErr(err) => PeekErr(err), } } } impl Parser for Recognize where Input: Stream, P: Parser, F: Default + Extend<::Token>, { type Output = F; type PartialState = (F, P::PartialState); parse_mode!(Input); fn parse_mode_impl( &mut self, mode: M, input: &mut Input, state: &mut Self::PartialState, ) -> ParseResult::Error> where M: ParseMode, { let (ref mut elements, ref mut child_state) = *state; let before = input.checkpoint(); let result = self.0.parse_mode(mode, input, child_state); Self::recognize_result(elements, before, input, result) } #[inline] fn add_error(&mut self, errors: &mut Tracked<::Error>) { self.0.add_error(errors) } } /// Constructs a parser which returns the tokens parsed by `parser` accumulated in /// `F: Extend` instead of `P::Output`. /// /// ``` /// use combine::Parser; /// use combine::parser::{repeat::skip_many1, token::token, combinator::recognize, char::digit}; /// /// let mut parser = recognize((skip_many1(digit()), token('.'), skip_many1(digit()))); /// assert_eq!(parser.parse("123.45"), Ok(("123.45".to_string(), ""))); /// assert_eq!(parser.parse("123.45"), Ok(("123.45".to_string(), ""))); /// ``` pub fn recognize(parser: P) -> Recognize where Input: Stream, P: Parser, F: Default + Extend<::Token>, { Recognize(parser, PhantomData) } pub enum Either { Left(L), Right(R), } impl Parser for Either where Input: Stream, L: Parser, R: Parser, { type Output = L::Output; type PartialState = Option>; #[inline] fn parse_lazy( &mut self, input: &mut Input, ) -> ParseResult::Error> { match *self { Either::Left(ref mut x) => x.parse_lazy(input), Either::Right(ref mut x) => x.parse_lazy(input), } } parse_mode!(Input); #[inline] fn parse_mode_impl( &mut self, mode: M, input: &mut Input, state: &mut Self::PartialState, ) -> ParseResult::Error> where M: ParseMode, { match *self { Either::Left(ref mut x) => { match *state { None | Some(Either::Right(_)) => { *state = Some(Either::Left(L::PartialState::default())) } Some(Either::Left(_)) => (), } x.parse_mode( mode, input, match state { Some(Either::Left(state)) => state, _ => unreachable!(), }, ) } Either::Right(ref mut x) => { match *state { None | Some(Either::Left(_)) => { *state = Some(Either::Right(R::PartialState::default())) } Some(Either::Right(_)) => (), } x.parse_mode( mode, input, match state { Some(Either::Right(state)) => state, _ => unreachable!(), }, ) } } } #[inline] fn add_error(&mut self, error: &mut Tracked<::Error>) { match *self { Either::Left(ref mut x) => x.add_error(error), Either::Right(ref mut x) => x.add_error(error), } } } pub struct NoPartial

(P); impl Parser for NoPartial

where Input: Stream, P: Parser, { type Output =

>::Output; type PartialState = (); #[inline] fn parse_lazy( &mut self, input: &mut Input, ) -> ParseResult::Error> { self.0.parse_lazy(input) } parse_mode!(Input); #[inline] fn parse_mode_impl( &mut self, _mode: M, input: &mut Input, _state: &mut Self::PartialState, ) -> ParseResult::Error> where M: ParseMode, { self.0.parse_lazy(input) } forward_parser!(Input, add_error add_committed_expected_error parser_count, 0); } pub fn no_partial(p: P) -> NoPartial

where Input: Stream, P: Parser, { NoPartial(p) } #[derive(Copy, Clone)] pub struct Ignore

(P); impl Parser for Ignore

where Input: Stream, P: Parser, { type Output = (); type PartialState = P::PartialState; #[inline] fn parse_lazy( &mut self, input: &mut Input, ) -> ParseResult::Error> { self.0.parse_lazy(input).map(|_| ()) } parse_mode!(Input); #[inline] fn parse_mode_impl( &mut self, mode: M, input: &mut Input, state: &mut Self::PartialState, ) -> ParseResult::Error> where M: ParseMode, { self.0.parse_mode(mode, input, state).map(|_| ()) } forward_parser!(Input, add_error add_committed_expected_error parser_count, 0); } #[doc(hidden)] pub fn ignore(p: P) -> Ignore

where Input: Stream, P: Parser, { Ignore(p) } #[cfg(feature = "alloc")] #[cfg_attr(docsrs, doc(cfg(feature = "std")))] #[derive(Default)] pub struct AnyPartialState(Option>); #[cfg(feature = "alloc")] #[cfg_attr(docsrs, doc(cfg(feature = "std")))] pub struct AnyPartialStateParser

(P); #[cfg(feature = "alloc")] impl Parser for AnyPartialStateParser

where Input: Stream, P: Parser, P::PartialState: 'static, { type Output = P::Output; type PartialState = AnyPartialState; #[inline] fn parse_lazy( &mut self, input: &mut Input, ) -> ParseResult::Error> { self.0.parse_lazy(input) } parse_mode!(Input); #[inline] fn parse_mode( &mut self, mode: M, input: &mut Input, state: &mut Self::PartialState, ) -> ParseResult::Error> where M: ParseMode, { let mut new_child_state; let result = { let child_state = if state.0.is_none() { new_child_state = Some(Default::default()); new_child_state.as_mut().unwrap() } else { new_child_state = None; state.0.as_mut().unwrap().downcast_mut().unwrap() }; self.0.parse_mode(mode, input, child_state) }; if let CommitErr(_) = result { if state.0.is_none() { // FIXME Make None unreachable for LLVM state.0 = Some(Box::new(new_child_state.unwrap())); } } result } forward_parser!(Input, add_error add_committed_expected_error parser_count, 0); } /// Returns a parser where `P::PartialState` is boxed. Useful as a way to avoid writing the type /// since it can get very large after combining a few parsers. /// /// ``` /// # #[macro_use] /// # extern crate combine; /// # use combine::parser::combinator::{AnyPartialState, any_partial_state}; /// # use combine::parser::char::letter; /// # use combine::*; /// /// # fn main() { /// /// parser! { /// type PartialState = AnyPartialState; /// fn example[Input]()(Input) -> (char, char) /// where [ Input: Stream ] /// { /// any_partial_state((letter(), letter())) /// } /// } /// /// assert_eq!( /// example().easy_parse("ab"), /// Ok((('a', 'b'), "")) /// ); /// /// # } /// ``` #[cfg(feature = "alloc")] #[cfg_attr(docsrs, doc(cfg(feature = "std")))] pub fn any_partial_state(p: P) -> AnyPartialStateParser

where Input: Stream, P: Parser, P::PartialState: 'static, { AnyPartialStateParser(p) } #[cfg(feature = "alloc")] #[cfg_attr(docsrs, doc(cfg(feature = "std")))] #[derive(Default)] pub struct AnySendPartialState(Option>); #[cfg(feature = "alloc")] #[cfg_attr(docsrs, doc(cfg(feature = "std")))] pub struct AnySendPartialStateParser

(P); #[cfg(feature = "alloc")] impl Parser for AnySendPartialStateParser

where Input: Stream, P: Parser, P::PartialState: Send + 'static, { type Output = P::Output; type PartialState = AnySendPartialState; #[inline] fn parse_lazy( &mut self, input: &mut Input, ) -> ParseResult::Error> { self.0.parse_lazy(input) } parse_mode!(Input); #[inline] fn parse_mode( &mut self, mode: M, input: &mut Input, state: &mut Self::PartialState, ) -> ParseResult::Error> where M: ParseMode, { let mut new_child_state; let result = { let child_state = if state.0.is_none() { new_child_state = Some(Default::default()); new_child_state.as_mut().unwrap() } else { new_child_state = None; state.0.as_mut().unwrap().downcast_mut().unwrap() }; self.0.parse_mode(mode, input, child_state) }; if let CommitErr(_) = result { if state.0.is_none() { // FIXME Make None unreachable for LLVM state.0 = Some(Box::new(new_child_state.unwrap())); } } result } forward_parser!(Input, add_error add_committed_expected_error parser_count, 0); } /// Returns a parser where `P::PartialState` is boxed. Useful as a way to avoid writing the type /// since it can get very large after combining a few parsers. /// /// ``` /// # #[macro_use] /// # extern crate combine; /// # use combine::parser::combinator::{AnySendPartialState, any_send_partial_state}; /// # use combine::parser::char::letter; /// # use combine::*; /// /// # fn main() { /// /// parser! { /// type PartialState = AnySendPartialState; /// fn example[Input]()(Input) -> (char, char) /// where [ Input: Stream ] /// { /// any_send_partial_state((letter(), letter())) /// } /// } /// /// assert_eq!( /// example().easy_parse("ab"), /// Ok((('a', 'b'), "")) /// ); /// /// # } /// ``` #[cfg(feature = "alloc")] #[cfg_attr(docsrs, doc(cfg(feature = "std")))] pub fn any_send_partial_state(p: P) -> AnySendPartialStateParser

where Input: Stream, P: Parser, P::PartialState: Send + 'static, { AnySendPartialStateParser(p) } #[cfg(feature = "alloc")] #[cfg_attr(docsrs, doc(cfg(feature = "std")))] #[derive(Default)] pub struct AnySendSyncPartialState(Option>); #[cfg(feature = "alloc")] #[cfg_attr(docsrs, doc(cfg(feature = "std")))] pub struct AnySendSyncPartialStateParser

(P); #[cfg(feature = "alloc")] impl Parser for AnySendSyncPartialStateParser

where Input: Stream, P: Parser, P::PartialState: Send + Sync + 'static, { type Output = P::Output; type PartialState = AnySendSyncPartialState; #[inline] fn parse_lazy( &mut self, input: &mut Input, ) -> ParseResult::Error> { self.0.parse_lazy(input) } parse_mode!(Input); #[inline] fn parse_mode( &mut self, mode: M, input: &mut Input, state: &mut Self::PartialState, ) -> ParseResult::Error> where M: ParseMode, { let mut new_child_state; let result = { let child_state = if state.0.is_none() { new_child_state = Some(Default::default()); new_child_state.as_mut().unwrap() } else { new_child_state = None; state.0.as_mut().unwrap().downcast_mut().unwrap() }; self.0.parse_mode(mode, input, child_state) }; if let CommitErr(_) = result { if state.0.is_none() { // FIXME Make None unreachable for LLVM state.0 = Some(Box::new(new_child_state.unwrap())); } } result } forward_parser!(Input, add_error add_committed_expected_error parser_count, 0); } /// Returns a parser where `P::PartialState` is boxed. Useful as a way to avoid writing the type /// since it can get very large after combining a few parsers. /// /// ``` /// # #[macro_use] /// # extern crate combine; /// # use combine::parser::combinator::{AnySendSyncPartialState, any_send_sync_partial_state}; /// # use combine::parser::char::letter; /// # use combine::*; /// /// # fn main() { /// /// fn example() -> impl Parser /// where /// Input: Stream, /// Input::Error: ParseError, /// { /// any_send_sync_partial_state((letter(), letter())) /// } /// /// assert_eq!( /// example().easy_parse("ab"), /// Ok((('a', 'b'), "")) /// ); /// /// # } /// ``` #[cfg(feature = "alloc")] #[cfg_attr(docsrs, doc(cfg(feature = "std")))] pub fn any_send_sync_partial_state(p: P) -> AnySendSyncPartialStateParser

where Input: Stream, P: Parser, P::PartialState: Send + Sync + 'static, { AnySendSyncPartialStateParser(p) } #[derive(Copy, Clone)] pub struct Lazy

(P); impl Parser for Lazy

where Input: Stream, P: FnMut() -> R, R: Parser, { type Output = O; type PartialState = R::PartialState; fn parse_stream(&mut self, input: &mut Input) -> ParseResult::Error> { (self.0)().parse_stream(input) } fn parse_lazy(&mut self, input: &mut Input) -> ParseResult::Error> { (self.0)().parse_lazy(input) } parse_mode!(Input); fn parse_committed_mode( &mut self, mode: M, input: &mut Input, state: &mut Self::PartialState, ) -> ParseResult::Error> where M: ParseMode, { (self.0)().parse_mode(mode, input, state) } fn parse_mode_impl( &mut self, mode: M, input: &mut Input, state: &mut Self::PartialState, ) -> ParseResult::Error> where M: ParseMode, { (self.0)().parse_mode_impl(mode, input, state) } 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.0)().add_committed_expected_error(errors); } } /// Constructs the parser lazily on each `parse_*` call. Can be used to effectively reduce the /// size of deeply nested parsers as only the function producing the parser is stored. /// /// NOTE: Expects that the parser returned is always the same one, if that is not the case the /// reported error may be wrong. If different parsers may be returned, use the [`factory`][] parser /// instead. /// /// [`factory`]: fn.factory.html pub fn lazy(p: P) -> Lazy

where Input: Stream, P: FnMut() -> R, R: Parser, { Lazy(p) } #[derive(Copy, Clone)] pub struct Factory(P, Option); impl Factory { fn parser(&mut self, input: &mut Input) -> &mut R where P: FnMut(&mut Input) -> R, { if let Some(ref mut r) = self.1 { return r; } self.1 = Some((self.0)(input)); self.1.as_mut().unwrap() } } impl Parser for Factory where Input: Stream, P: FnMut(&mut Input) -> R, R: Parser, { type Output = O; type PartialState = R::PartialState; parse_mode!(Input); fn parse_mode_impl( &mut self, mode: M, input: &mut Input, state: &mut Self::PartialState, ) -> ParseResult::Error> where M: ParseMode, { // Always ask for a new parser except if we are in a partial call being resumed as we want // to resume the same parser then if mode.is_first() { self.1 = None; } self.parser(input).parse_mode_impl(mode, input, state) } fn add_error(&mut self, errors: &mut Tracked<::Error>) { if let Some(parser) = &mut self.1 { parser.add_error(errors); } } fn add_committed_expected_error(&mut self, errors: &mut Tracked<::Error>) { if let Some(parser) = &mut self.1 { parser.add_committed_expected_error(errors); } } } /// Constructs the parser lazily on each `parse_*` call. This is similar to [`lazy`][] but it /// takes `Input` as an argument and allows different parsers to be returned on each call to /// `p` while still reporting the correct errors. /// /// [`lazy`]: fn.lazy.html /// /// ``` /// # use combine::*; /// # use combine::parser::char::{digit, letter}; /// # use combine::parser::combinator::{FnOpaque, opaque, factory}; /// /// let mut parsers: Vec> = vec![opaque(|f| f(&mut digit())), opaque(|f| f(&mut letter()))]; /// let mut iter = parsers.into_iter().cycle(); /// let mut parser = many(factory(move |_| iter.next().unwrap())); /// assert_eq!(parser.parse("1a2b3cd"), Ok(("1a2b3c".to_string(), "d"))); /// ``` pub fn factory(p: P) -> Factory where Input: Stream, P: FnMut(&mut Input) -> R, R: Parser, { Factory(p, None) } mod internal { pub trait Sealed {} } use self::internal::Sealed; pub trait StrLike: Sealed { fn from_utf8(&self) -> Option<&str>; } #[cfg(feature = "alloc")] impl Sealed for String {} #[cfg(feature = "alloc")] impl StrLike for String { fn from_utf8(&self) -> Option<&str> { Some(self) } } impl<'a> Sealed for &'a str {} impl<'a> StrLike for &'a str { fn from_utf8(&self) -> Option<&str> { Some(*self) } } impl Sealed for str {} impl StrLike for str { fn from_utf8(&self) -> Option<&str> { Some(self) } } #[cfg(feature = "alloc")] impl Sealed for Vec {} #[cfg(feature = "alloc")] impl StrLike for Vec { fn from_utf8(&self) -> Option<&str> { (**self).from_utf8() } } impl<'a> Sealed for &'a [u8] {} impl<'a> StrLike for &'a [u8] { fn from_utf8(&self) -> Option<&str> { (**self).from_utf8() } } impl Sealed for [u8] {} impl StrLike for [u8] { fn from_utf8(&self) -> Option<&str> { str::from_utf8(self).ok() } } parser! { pub struct FromStr; type PartialState = P::PartialState; /// Takes a parser that outputs a string like value (`&str`, `String`, `&[u8]` or `Vec`) and parses it /// using `std::str::FromStr`. Errors if the output of `parser` is not UTF-8 or if /// `FromStr::from_str` returns an error. /// /// ``` /// # extern crate combine; /// # use combine::parser::range; /// # use combine::parser::repeat::many1; /// # use combine::parser::combinator::from_str; /// # use combine::parser::char; /// # use combine::parser::byte; /// # use combine::*; /// # fn main() { /// let mut parser = from_str(many1::(char::digit())); /// let result = parser.parse("12345\r\n"); /// assert_eq!(result, Ok((12345i32, "\r\n"))); /// /// // Range parsers work as well /// let mut parser = from_str(range::take_while1(|c: char| c.is_digit(10))); /// let result = parser.parse("12345\r\n"); /// assert_eq!(result, Ok((12345i32, "\r\n"))); /// /// // As do parsers that work with bytes /// let digits = || range::take_while1(|b: u8| b >= b'0' && b <= b'9'); /// let mut parser = from_str(range::recognize(( /// digits(), /// byte::byte(b'.'), /// digits(), /// ))); /// let result = parser.parse(&b"123.45\r\n"[..]); /// assert_eq!(result, Ok((123.45f64, &b"\r\n"[..]))); /// # } /// ``` pub fn from_str[Input, O, P](parser: P)(Input) -> O where [ P: Parser, P::Output: StrLike, O: str::FromStr, O::Err: fmt::Display, ] { parser.and_then(|r| { r.from_utf8() .ok_or_else(|| StreamErrorFor::::expected_static_message("UTF-8")) .and_then(|s| s.parse().map_err(StreamErrorFor::::message_format)) }) } } #[derive(Copy, Clone)] pub struct Opaque(F, PhantomData O>); impl Parser for Opaque where Input: Stream, S: Default, F: FnMut(&mut dyn FnMut(&mut dyn Parser)), { type Output = O; type PartialState = S; fn parse_stream(&mut self, input: &mut Input) -> ParseResult::Error> { let mut x = None; (self.0)(&mut |parser| x = Some(parser.parse_stream(input))); x.expect("Parser") } fn parse_lazy(&mut self, input: &mut Input) -> ParseResult::Error> { let mut x = None; (self.0)(&mut |parser| x = Some(parser.parse_lazy(input))); x.expect("Parser") } parse_mode!(Input); fn parse_mode_impl( &mut self, mode: M, input: &mut Input, state: &mut Self::PartialState, ) -> ParseResult::Error> where M: ParseMode, { let mut x = None; (self.0)(&mut |parser| { x = Some(if mode.is_first() { parser.parse_first(input, state) } else { parser.parse_partial(input, state) }) }); x.expect("Parser") } fn add_error(&mut self, errors: &mut Tracked<::Error>) { (self.0)(&mut |parser| parser.add_error(errors)); } fn add_committed_expected_error(&mut self, errors: &mut Tracked<::Error>) { (self.0)(&mut |parser| parser.add_committed_expected_error(errors)); } } /// Alias over `Opaque` where the function can be a plain function pointer (does not need to /// capture any values) pub type FnOpaque = Opaque)), Input, O, S>; /// Creates a parser from a function which takes a function that are given the actual parser. /// Though convoluted this makes it possible to hide the concrete parser type without `Box` or /// losing the full information about the parser as is the case of [`parser`][]. /// /// Since this hides the type this can also be useful for writing mutually recursive `impl Parser` /// parsers to break the otherwise arbitrarily large type that rustc creates internally. /// /// If you need a more general version (that does not need trait objects) try the [`parser!`][] /// macro. /// /// ``` /// # #[macro_use] /// # extern crate combine; /// # use combine::parser::combinator::{FnOpaque, no_partial}; /// # use combine::parser::char::{char, digit}; /// # use combine::*; /// /// # fn main() { /// /// #[derive(PartialEq, Debug)] /// enum Expr { /// Number(i64), /// Pair(Box, Box), /// } /// /// fn expr() -> FnOpaque /// where /// Input: Stream, /// Input::Error: ParseError, /// { /// opaque!( /// // `no_partial` disables partial parsing and replaces the partial state with `()`, /// // letting us avoid naming that type /// no_partial(choice(( /// from_str(many1::(digit())) /// .map(Expr::Number), /// (char('('), expr(), char(','), expr(), char(')')) /// .map(|(_, l, _, r, _)| Expr::Pair(Box::new(l), Box::new(r))) /// ))), /// ) /// } /// /// assert_eq!( /// expr().easy_parse("123"), /// Ok((Expr::Number(123), "")) /// ); /// /// # } /// ``` /// /// [`parser`]: ../function/fn.parser.html /// [`parser!`]: ../../macro.parser.html pub fn opaque(f: F) -> Opaque where Input: Stream, S: Default, F: FnMut(&mut dyn FnMut(&mut dyn Parser)), { Opaque(f, PhantomData) } /// Convenience macro over [`opaque`][]. /// /// [`opaque`]: parser/combinator/fn.opaque.html #[macro_export] macro_rules! opaque { ($e: expr) => { $crate::opaque!($e,); }; ($e: expr,) => { $crate::parser::combinator::opaque( move |f: &mut dyn FnMut(&mut $crate::Parser<_, Output = _, PartialState = _>)| { f(&mut $e) }, ) }; } pub struct InputConverter where InputInner: Stream, { pub parser: P, pub converter: C, pub _marker: PhantomData, } impl Parser for InputConverter where Input: Stream, InputInner: Stream, P: Parser, for<'c> C: Converter<'c, Input, InputInner = InputInner>, { type Output = P::Output; type PartialState = P::PartialState; parse_mode!(Input); fn parse_mode_impl( &mut self, mode: M, input: &mut Input, state: &mut Self::PartialState, ) -> ParseResult where M: ParseMode, { let mut input_inner = match self.converter.convert(input) { Ok(x) => x, Err(err) => return PeekErr(err.into()), }; self.parser .parse_mode(mode, &mut input_inner, state) .map_err(|err| self.converter.convert_error(input, err)) } } pub trait Converter<'a, Input> where Input: Stream, { type InputInner: Stream + 'a; fn convert(&mut self, input: &'a mut Input) -> Result; fn convert_error( &mut self, input: &'a mut Input, error: ::Error, ) -> Input::Error; } impl<'a, Input, InputInner> Converter<'a, Input> for ( fn(&'a mut Input) -> Result, fn(&'a mut Input, InputInner::Error) -> Input::Error, ) where Input: Stream, InputInner: Stream + 'a, { type InputInner = InputInner; fn convert(&mut self, input: &'a mut Input) -> Result { (self.0)(input) } fn convert_error(&mut self, input: &'a mut Input, error: InputInner::Error) -> Input::Error { (self.1)(input, error) } } pub fn input_converter( parser: P, converter: C, ) -> InputConverter where Input: Stream, InputInner: Stream, P: Parser, for<'c> C: Converter<'c, Input, InputInner = InputInner>, { InputConverter { parser, converter, _marker: PhantomData, } } #[derive(Clone)] pub struct Spanned

(P); impl Parser for Spanned

where P: Parser, Input: Stream>, Input::Error: ParseError>, Q: Ord + Clone, { type Output = P::Output; type PartialState = P::PartialState; parse_mode!(Input); #[inline] fn parse_mode_impl( &mut self, mode: M, input: &mut Input, state: &mut Self::PartialState, ) -> ParseResult::Error> where M: ParseMode, { let start = input.position().start; self.0.parse_mode(mode, input, state).map_err(|mut err| { let error_span = err.position(); // If an inner `spanned` combinator has already attached its span that will be more // specific so only set a span if the current error has a position, not a span if error_span.start == error_span.end { let end = input.position().end; err.set_position(Span { start, end }); } err }) } forward_parser!(Input, add_error, add_committed_expected_error, 0); } /// Equivalent to [`p.spanned()`]. /// /// [`p.spanned()`]: ../trait.Parser.html#method.spanned pub fn spanned(p: P) -> Spanned

where P: Parser, Input: Stream, { Spanned(p) }