use crate::combinator::trace;
use crate::error::ParserError;
use crate::stream::Stream;
use crate::*;
#[doc(inline)]
pub use crate::seq;
/// Sequence two parsers, only returning the output from the second.
///
/// See also [`seq`] to generalize this across any number of fields.
///
/// # Example
///
/// ```rust
/// # use winnow::{error::ErrMode, error::ErrorKind, error::InputError, error::Needed};
/// # use winnow::prelude::*;
/// # use winnow::error::Needed::Size;
/// use winnow::combinator::preceded;
///
/// let mut parser = preceded("abc", "efg");
///
/// assert_eq!(parser.parse_peek("abcefg"), Ok(("", "efg")));
/// assert_eq!(parser.parse_peek("abcefghij"), Ok(("hij", "efg")));
/// assert_eq!(parser.parse_peek(""), Err(ErrMode::Backtrack(InputError::new("", ErrorKind::Tag))));
/// assert_eq!(parser.parse_peek("123"), Err(ErrMode::Backtrack(InputError::new("123", ErrorKind::Tag))));
/// ```
#[doc(alias = "ignore_then")]
pub fn preceded(
mut ignored: IgnoredParser,
mut parser: ParseNext,
) -> impl Parser
where
Input: Stream,
Error: ParserError,
IgnoredParser: Parser,
ParseNext: Parser,
{
trace("preceded", move |input: &mut Input| {
let _ = ignored.parse_next(input)?;
parser.parse_next(input)
})
}
/// Sequence two parsers, only returning the output of the first.
///
/// See also [`seq`] to generalize this across any number of fields.
///
/// # Example
///
/// ```rust
/// # use winnow::{error::ErrMode, error::ErrorKind, error::InputError, error::Needed};
/// # use winnow::prelude::*;
/// # use winnow::error::Needed::Size;
/// use winnow::combinator::terminated;
///
/// let mut parser = terminated("abc", "efg");
///
/// assert_eq!(parser.parse_peek("abcefg"), Ok(("", "abc")));
/// assert_eq!(parser.parse_peek("abcefghij"), Ok(("hij", "abc")));
/// assert_eq!(parser.parse_peek(""), Err(ErrMode::Backtrack(InputError::new("", ErrorKind::Tag))));
/// assert_eq!(parser.parse_peek("123"), Err(ErrMode::Backtrack(InputError::new("123", ErrorKind::Tag))));
/// ```
#[doc(alias = "then_ignore")]
pub fn terminated(
mut parser: ParseNext,
mut ignored: IgnoredParser,
) -> impl Parser
where
Input: Stream,
Error: ParserError,
ParseNext: Parser,
IgnoredParser: Parser,
{
trace("terminated", move |input: &mut Input| {
let o = parser.parse_next(input)?;
ignored.parse_next(input).map(|_| o)
})
}
/// Sequence three parsers, only returning the values of the first and third.
///
/// See also [`seq`] to generalize this across any number of fields.
///
/// # Example
///
/// ```rust
/// # use winnow::{error::ErrMode, error::ErrorKind, error::InputError, error::Needed};
/// # use winnow::error::Needed::Size;
/// # use winnow::prelude::*;
/// use winnow::combinator::separated_pair;
///
/// let mut parser = separated_pair("abc", "|", "efg");
///
/// assert_eq!(parser.parse_peek("abc|efg"), Ok(("", ("abc", "efg"))));
/// assert_eq!(parser.parse_peek("abc|efghij"), Ok(("hij", ("abc", "efg"))));
/// assert_eq!(parser.parse_peek(""), Err(ErrMode::Backtrack(InputError::new("", ErrorKind::Tag))));
/// assert_eq!(parser.parse_peek("123"), Err(ErrMode::Backtrack(InputError::new("123", ErrorKind::Tag))));
/// ```
pub fn separated_pair(
mut first: P1,
mut sep: SepParser,
mut second: P2,
) -> impl Parser
where
Input: Stream,
Error: ParserError,
P1: Parser,
SepParser: Parser,
P2: Parser,
{
trace("separated_pair", move |input: &mut Input| {
let o1 = first.parse_next(input)?;
let _ = sep.parse_next(input)?;
second.parse_next(input).map(|o2| (o1, o2))
})
}
/// Sequence three parsers, only returning the output of the second.
///
/// See also [`seq`] to generalize this across any number of fields.
///
/// # Example
///
/// ```rust
/// # use winnow::{error::ErrMode, error::ErrorKind, error::InputError, error::Needed};
/// # use winnow::error::Needed::Size;
/// # use winnow::prelude::*;
/// use winnow::combinator::delimited;
///
/// let mut parser = delimited("(", "abc", ")");
///
/// assert_eq!(parser.parse_peek("(abc)"), Ok(("", "abc")));
/// assert_eq!(parser.parse_peek("(abc)def"), Ok(("def", "abc")));
/// assert_eq!(parser.parse_peek(""), Err(ErrMode::Backtrack(InputError::new("", ErrorKind::Tag))));
/// assert_eq!(parser.parse_peek("123"), Err(ErrMode::Backtrack(InputError::new("123", ErrorKind::Tag))));
/// ```
#[doc(alias = "between")]
#[doc(alias = "padded")]
pub fn delimited<
Input,
Ignored1,
Output,
Ignored2,
Error,
IgnoredParser1,
ParseNext,
IgnoredParser2,
>(
mut ignored1: IgnoredParser1,
mut parser: ParseNext,
mut ignored2: IgnoredParser2,
) -> impl Parser
where
Input: Stream,
Error: ParserError,
IgnoredParser1: Parser,
ParseNext: Parser,
IgnoredParser2: Parser,
{
trace("delimited", move |input: &mut Input| {
let _ = ignored1.parse_next(input)?;
let o2 = parser.parse_next(input)?;
ignored2.parse_next(input).map(|_| o2)
})
}