diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
commit | 36d22d82aa202bb199967e9512281e9a53db42c9 (patch) | |
tree | 105e8c98ddea1c1e4784a60a5a6410fa416be2de /third_party/rust/nom/src/sequence/mod.rs | |
parent | Initial commit. (diff) | |
download | firefox-esr-upstream.tar.xz firefox-esr-upstream.zip |
Adding upstream version 115.7.0esr.upstream/115.7.0esrupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/nom/src/sequence/mod.rs')
-rw-r--r-- | third_party/rust/nom/src/sequence/mod.rs | 279 |
1 files changed, 279 insertions, 0 deletions
diff --git a/third_party/rust/nom/src/sequence/mod.rs b/third_party/rust/nom/src/sequence/mod.rs new file mode 100644 index 0000000000..735ab45cc7 --- /dev/null +++ b/third_party/rust/nom/src/sequence/mod.rs @@ -0,0 +1,279 @@ +//! Combinators applying parsers in sequence + +#[cfg(test)] +mod tests; + +use crate::error::ParseError; +use crate::internal::{IResult, Parser}; + +/// Gets an object from the first parser, +/// then gets another object from the second parser. +/// +/// # Arguments +/// * `first` The first parser to apply. +/// * `second` The second parser to apply. +/// +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::Needed::Size; +/// use nom::sequence::pair; +/// use nom::bytes::complete::tag; +/// +/// let mut parser = pair(tag("abc"), tag("efg")); +/// +/// assert_eq!(parser("abcefg"), Ok(("", ("abc", "efg")))); +/// assert_eq!(parser("abcefghij"), Ok(("hij", ("abc", "efg")))); +/// assert_eq!(parser(""), Err(Err::Error(("", ErrorKind::Tag)))); +/// assert_eq!(parser("123"), Err(Err::Error(("123", ErrorKind::Tag)))); +/// ``` +pub fn pair<I, O1, O2, E: ParseError<I>, F, G>( + mut first: F, + mut second: G, +) -> impl FnMut(I) -> IResult<I, (O1, O2), E> +where + F: Parser<I, O1, E>, + G: Parser<I, O2, E>, +{ + move |input: I| { + let (input, o1) = first.parse(input)?; + second.parse(input).map(|(i, o2)| (i, (o1, o2))) + } +} + +/// Matches an object from the first parser and discards it, +/// then gets an object from the second parser. +/// +/// # Arguments +/// * `first` The opening parser. +/// * `second` The second parser to get object. +/// +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::Needed::Size; +/// use nom::sequence::preceded; +/// use nom::bytes::complete::tag; +/// +/// let mut parser = preceded(tag("abc"), tag("efg")); +/// +/// assert_eq!(parser("abcefg"), Ok(("", "efg"))); +/// assert_eq!(parser("abcefghij"), Ok(("hij", "efg"))); +/// assert_eq!(parser(""), Err(Err::Error(("", ErrorKind::Tag)))); +/// assert_eq!(parser("123"), Err(Err::Error(("123", ErrorKind::Tag)))); +/// ``` +pub fn preceded<I, O1, O2, E: ParseError<I>, F, G>( + mut first: F, + mut second: G, +) -> impl FnMut(I) -> IResult<I, O2, E> +where + F: Parser<I, O1, E>, + G: Parser<I, O2, E>, +{ + move |input: I| { + let (input, _) = first.parse(input)?; + second.parse(input) + } +} + +/// Gets an object from the first parser, +/// then matches an object from the second parser and discards it. +/// +/// # Arguments +/// * `first` The first parser to apply. +/// * `second` The second parser to match an object. +/// +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::Needed::Size; +/// use nom::sequence::terminated; +/// use nom::bytes::complete::tag; +/// +/// let mut parser = terminated(tag("abc"), tag("efg")); +/// +/// assert_eq!(parser("abcefg"), Ok(("", "abc"))); +/// assert_eq!(parser("abcefghij"), Ok(("hij", "abc"))); +/// assert_eq!(parser(""), Err(Err::Error(("", ErrorKind::Tag)))); +/// assert_eq!(parser("123"), Err(Err::Error(("123", ErrorKind::Tag)))); +/// ``` +pub fn terminated<I, O1, O2, E: ParseError<I>, F, G>( + mut first: F, + mut second: G, +) -> impl FnMut(I) -> IResult<I, O1, E> +where + F: Parser<I, O1, E>, + G: Parser<I, O2, E>, +{ + move |input: I| { + let (input, o1) = first.parse(input)?; + second.parse(input).map(|(i, _)| (i, o1)) + } +} + +/// Gets an object from the first parser, +/// then matches an object from the sep_parser and discards it, +/// then gets another object from the second parser. +/// +/// # Arguments +/// * `first` The first parser to apply. +/// * `sep` The separator parser to apply. +/// * `second` The second parser to apply. +/// +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::Needed::Size; +/// use nom::sequence::separated_pair; +/// use nom::bytes::complete::tag; +/// +/// let mut parser = separated_pair(tag("abc"), tag("|"), tag("efg")); +/// +/// assert_eq!(parser("abc|efg"), Ok(("", ("abc", "efg")))); +/// assert_eq!(parser("abc|efghij"), Ok(("hij", ("abc", "efg")))); +/// assert_eq!(parser(""), Err(Err::Error(("", ErrorKind::Tag)))); +/// assert_eq!(parser("123"), Err(Err::Error(("123", ErrorKind::Tag)))); +/// ``` +pub fn separated_pair<I, O1, O2, O3, E: ParseError<I>, F, G, H>( + mut first: F, + mut sep: G, + mut second: H, +) -> impl FnMut(I) -> IResult<I, (O1, O3), E> +where + F: Parser<I, O1, E>, + G: Parser<I, O2, E>, + H: Parser<I, O3, E>, +{ + move |input: I| { + let (input, o1) = first.parse(input)?; + let (input, _) = sep.parse(input)?; + second.parse(input).map(|(i, o2)| (i, (o1, o2))) + } +} + +/// Matches an object from the first parser and discards it, +/// then gets an object from the second parser, +/// and finally matches an object from the third parser and discards it. +/// +/// # Arguments +/// * `first` The first parser to apply and discard. +/// * `second` The second parser to apply. +/// * `third` The third parser to apply and discard. +/// +/// ```rust +/// # use nom::{Err, error::ErrorKind, Needed}; +/// # use nom::Needed::Size; +/// use nom::sequence::delimited; +/// use nom::bytes::complete::tag; +/// +/// let mut parser = delimited(tag("("), tag("abc"), tag(")")); +/// +/// assert_eq!(parser("(abc)"), Ok(("", "abc"))); +/// assert_eq!(parser("(abc)def"), Ok(("def", "abc"))); +/// assert_eq!(parser(""), Err(Err::Error(("", ErrorKind::Tag)))); +/// assert_eq!(parser("123"), Err(Err::Error(("123", ErrorKind::Tag)))); +/// ``` +pub fn delimited<I, O1, O2, O3, E: ParseError<I>, F, G, H>( + mut first: F, + mut second: G, + mut third: H, +) -> impl FnMut(I) -> IResult<I, O2, E> +where + F: Parser<I, O1, E>, + G: Parser<I, O2, E>, + H: Parser<I, O3, E>, +{ + move |input: I| { + let (input, _) = first.parse(input)?; + let (input, o2) = second.parse(input)?; + third.parse(input).map(|(i, _)| (i, o2)) + } +} + +/// Helper trait for the tuple combinator. +/// +/// This trait is implemented for tuples of parsers of up to 21 elements. +pub trait Tuple<I, O, E> { + /// Parses the input and returns a tuple of results of each parser. + fn parse(&mut self, input: I) -> IResult<I, O, E>; +} + +impl<Input, Output, Error: ParseError<Input>, F: Parser<Input, Output, Error>> + Tuple<Input, (Output,), Error> for (F,) +{ + fn parse(&mut self, input: Input) -> IResult<Input, (Output,), Error> { + self.0.parse(input).map(|(i, o)| (i, (o,))) + } +} + +macro_rules! tuple_trait( + ($name1:ident $ty1:ident, $name2: ident $ty2:ident, $($name:ident $ty:ident),*) => ( + tuple_trait!(__impl $name1 $ty1, $name2 $ty2; $($name $ty),*); + ); + (__impl $($name:ident $ty: ident),+; $name1:ident $ty1:ident, $($name2:ident $ty2:ident),*) => ( + tuple_trait_impl!($($name $ty),+); + tuple_trait!(__impl $($name $ty),+ , $name1 $ty1; $($name2 $ty2),*); + ); + (__impl $($name:ident $ty: ident),+; $name1:ident $ty1:ident) => ( + tuple_trait_impl!($($name $ty),+); + tuple_trait_impl!($($name $ty),+, $name1 $ty1); + ); +); + +macro_rules! tuple_trait_impl( + ($($name:ident $ty: ident),+) => ( + impl< + Input: Clone, $($ty),+ , Error: ParseError<Input>, + $($name: Parser<Input, $ty, Error>),+ + > Tuple<Input, ( $($ty),+ ), Error> for ( $($name),+ ) { + + fn parse(&mut self, input: Input) -> IResult<Input, ( $($ty),+ ), Error> { + tuple_trait_inner!(0, self, input, (), $($name)+) + + } + } + ); +); + +macro_rules! tuple_trait_inner( + ($it:tt, $self:expr, $input:expr, (), $head:ident $($id:ident)+) => ({ + let (i, o) = $self.$it.parse($input.clone())?; + + succ!($it, tuple_trait_inner!($self, i, ( o ), $($id)+)) + }); + ($it:tt, $self:expr, $input:expr, ($($parsed:tt)*), $head:ident $($id:ident)+) => ({ + let (i, o) = $self.$it.parse($input.clone())?; + + succ!($it, tuple_trait_inner!($self, i, ($($parsed)* , o), $($id)+)) + }); + ($it:tt, $self:expr, $input:expr, ($($parsed:tt)*), $head:ident) => ({ + let (i, o) = $self.$it.parse($input.clone())?; + + Ok((i, ($($parsed)* , o))) + }); +); + +tuple_trait!(FnA A, FnB B, FnC C, FnD D, FnE E, FnF F, FnG G, FnH H, FnI I, FnJ J, FnK K, FnL L, + FnM M, FnN N, FnO O, FnP P, FnQ Q, FnR R, FnS S, FnT T, FnU U); + +// Special case: implement `Tuple` for `()`, the unit type. +// This can come up in macros which accept a variable number of arguments. +// Literally, `()` is an empty tuple, so it should simply parse nothing. +impl<I, E: ParseError<I>> Tuple<I, (), E> for () { + fn parse(&mut self, input: I) -> IResult<I, (), E> { + Ok((input, ())) + } +} + +///Applies a tuple of parsers one by one and returns their results as a tuple. +///There is a maximum of 21 parsers +/// ```rust +/// # use nom::{Err, error::ErrorKind}; +/// use nom::sequence::tuple; +/// use nom::character::complete::{alpha1, digit1}; +/// let mut parser = tuple((alpha1, digit1, alpha1)); +/// +/// assert_eq!(parser("abc123def"), Ok(("", ("abc", "123", "def")))); +/// assert_eq!(parser("123def"), Err(Err::Error(("123def", ErrorKind::Alpha)))); +/// ``` +pub fn tuple<I, O, E: ParseError<I>, List: Tuple<I, O, E>>( + mut l: List, +) -> impl FnMut(I) -> IResult<I, O, E> { + move |i: I| l.parse(i) +} |