summaryrefslogtreecommitdiffstats
path: root/third_party/rust/nom/src/sequence
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/nom/src/sequence')
-rw-r--r--third_party/rust/nom/src/sequence/mod.rs279
-rw-r--r--third_party/rust/nom/src/sequence/tests.rs290
2 files changed, 569 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)
+}
diff --git a/third_party/rust/nom/src/sequence/tests.rs b/third_party/rust/nom/src/sequence/tests.rs
new file mode 100644
index 0000000000..30ad0d6783
--- /dev/null
+++ b/third_party/rust/nom/src/sequence/tests.rs
@@ -0,0 +1,290 @@
+use super::*;
+use crate::bytes::streaming::{tag, take};
+use crate::error::{Error, ErrorKind};
+use crate::internal::{Err, IResult, Needed};
+use crate::number::streaming::be_u16;
+
+#[test]
+fn single_element_tuples() {
+ use crate::character::complete::alpha1;
+ use crate::{error::ErrorKind, Err};
+
+ let mut parser = tuple((alpha1,));
+ assert_eq!(parser("abc123def"), Ok(("123def", ("abc",))));
+ assert_eq!(
+ parser("123def"),
+ Err(Err::Error(("123def", ErrorKind::Alpha)))
+ );
+}
+
+#[derive(PartialEq, Eq, Debug)]
+struct B {
+ a: u8,
+ b: u8,
+}
+
+#[derive(PartialEq, Eq, Debug)]
+struct C {
+ a: u8,
+ b: Option<u8>,
+}
+
+/*FIXME: convert code examples to new error management
+use util::{add_error_pattern, error_to_list, print_error};
+
+#[cfg(feature = "std")]
+#[rustfmt::skip]
+fn error_to_string<P: Clone + PartialEq>(e: &Context<P, u32>) -> &'static str {
+ let v: Vec<(P, ErrorKind<u32>)> = error_to_list(e);
+ // do it this way if you can use slice patterns
+ //match &v[..] {
+ // [ErrorKind::Custom(42), ErrorKind::Tag] => "missing `ijkl` tag",
+ // [ErrorKind::Custom(42), ErrorKind::Custom(128), ErrorKind::Tag] => "missing `mnop` tag after `ijkl`",
+ // _ => "unrecognized error"
+ //}
+
+ let collected: Vec<ErrorKind<u32>> = v.iter().map(|&(_, ref e)| e.clone()).collect();
+ if &collected[..] == [ErrorKind::Custom(42), ErrorKind::Tag] {
+ "missing `ijkl` tag"
+ } else if &collected[..] == [ErrorKind::Custom(42), ErrorKind::Custom(128), ErrorKind::Tag] {
+ "missing `mnop` tag after `ijkl`"
+ } else {
+ "unrecognized error"
+ }
+}
+
+// do it this way if you can use box patterns
+//use $crate::lib::std::str;
+//fn error_to_string(e:Err) -> String
+// match e {
+// NodePosition(ErrorKind::Custom(42), i1, box Position(ErrorKind::Tag, i2)) => {
+// format!("missing `ijkl` tag, found '{}' instead", str::from_utf8(i2).unwrap())
+// },
+// NodePosition(ErrorKind::Custom(42), i1, box NodePosition(ErrorKind::Custom(128), i2, box Position(ErrorKind::Tag, i3))) => {
+// format!("missing `mnop` tag after `ijkl`, found '{}' instead", str::from_utf8(i3).unwrap())
+// },
+// _ => "unrecognized error".to_string()
+// }
+//}
+*/
+
+#[test]
+fn complete() {
+ use crate::bytes::complete::tag;
+ fn err_test(i: &[u8]) -> IResult<&[u8], &[u8]> {
+ let (i, _) = tag("ijkl")(i)?;
+ tag("mnop")(i)
+ }
+ let a = &b"ijklmn"[..];
+
+ let res_a = err_test(a);
+ assert_eq!(
+ res_a,
+ Err(Err::Error(error_position!(&b"mn"[..], ErrorKind::Tag)))
+ );
+}
+
+#[test]
+fn pair_test() {
+ fn pair_abc_def(i: &[u8]) -> IResult<&[u8], (&[u8], &[u8])> {
+ pair(tag("abc"), tag("def"))(i)
+ }
+
+ assert_eq!(
+ pair_abc_def(&b"abcdefghijkl"[..]),
+ Ok((&b"ghijkl"[..], (&b"abc"[..], &b"def"[..])))
+ );
+ assert_eq!(
+ pair_abc_def(&b"ab"[..]),
+ Err(Err::Incomplete(Needed::new(1)))
+ );
+ assert_eq!(
+ pair_abc_def(&b"abcd"[..]),
+ Err(Err::Incomplete(Needed::new(2)))
+ );
+ assert_eq!(
+ pair_abc_def(&b"xxx"[..]),
+ Err(Err::Error(error_position!(&b"xxx"[..], ErrorKind::Tag)))
+ );
+ assert_eq!(
+ pair_abc_def(&b"xxxdef"[..]),
+ Err(Err::Error(error_position!(&b"xxxdef"[..], ErrorKind::Tag)))
+ );
+ assert_eq!(
+ pair_abc_def(&b"abcxxx"[..]),
+ Err(Err::Error(error_position!(&b"xxx"[..], ErrorKind::Tag)))
+ );
+}
+
+#[test]
+fn separated_pair_test() {
+ fn sep_pair_abc_def(i: &[u8]) -> IResult<&[u8], (&[u8], &[u8])> {
+ separated_pair(tag("abc"), tag(","), tag("def"))(i)
+ }
+
+ assert_eq!(
+ sep_pair_abc_def(&b"abc,defghijkl"[..]),
+ Ok((&b"ghijkl"[..], (&b"abc"[..], &b"def"[..])))
+ );
+ assert_eq!(
+ sep_pair_abc_def(&b"ab"[..]),
+ Err(Err::Incomplete(Needed::new(1)))
+ );
+ assert_eq!(
+ sep_pair_abc_def(&b"abc,d"[..]),
+ Err(Err::Incomplete(Needed::new(2)))
+ );
+ assert_eq!(
+ sep_pair_abc_def(&b"xxx"[..]),
+ Err(Err::Error(error_position!(&b"xxx"[..], ErrorKind::Tag)))
+ );
+ assert_eq!(
+ sep_pair_abc_def(&b"xxx,def"[..]),
+ Err(Err::Error(error_position!(&b"xxx,def"[..], ErrorKind::Tag)))
+ );
+ assert_eq!(
+ sep_pair_abc_def(&b"abc,xxx"[..]),
+ Err(Err::Error(error_position!(&b"xxx"[..], ErrorKind::Tag)))
+ );
+}
+
+#[test]
+fn preceded_test() {
+ fn preceded_abcd_efgh(i: &[u8]) -> IResult<&[u8], &[u8]> {
+ preceded(tag("abcd"), tag("efgh"))(i)
+ }
+
+ assert_eq!(
+ preceded_abcd_efgh(&b"abcdefghijkl"[..]),
+ Ok((&b"ijkl"[..], &b"efgh"[..]))
+ );
+ assert_eq!(
+ preceded_abcd_efgh(&b"ab"[..]),
+ Err(Err::Incomplete(Needed::new(2)))
+ );
+ assert_eq!(
+ preceded_abcd_efgh(&b"abcde"[..]),
+ Err(Err::Incomplete(Needed::new(3)))
+ );
+ assert_eq!(
+ preceded_abcd_efgh(&b"xxx"[..]),
+ Err(Err::Error(error_position!(&b"xxx"[..], ErrorKind::Tag)))
+ );
+ assert_eq!(
+ preceded_abcd_efgh(&b"xxxxdef"[..]),
+ Err(Err::Error(error_position!(&b"xxxxdef"[..], ErrorKind::Tag)))
+ );
+ assert_eq!(
+ preceded_abcd_efgh(&b"abcdxxx"[..]),
+ Err(Err::Error(error_position!(&b"xxx"[..], ErrorKind::Tag)))
+ );
+}
+
+#[test]
+fn terminated_test() {
+ fn terminated_abcd_efgh(i: &[u8]) -> IResult<&[u8], &[u8]> {
+ terminated(tag("abcd"), tag("efgh"))(i)
+ }
+
+ assert_eq!(
+ terminated_abcd_efgh(&b"abcdefghijkl"[..]),
+ Ok((&b"ijkl"[..], &b"abcd"[..]))
+ );
+ assert_eq!(
+ terminated_abcd_efgh(&b"ab"[..]),
+ Err(Err::Incomplete(Needed::new(2)))
+ );
+ assert_eq!(
+ terminated_abcd_efgh(&b"abcde"[..]),
+ Err(Err::Incomplete(Needed::new(3)))
+ );
+ assert_eq!(
+ terminated_abcd_efgh(&b"xxx"[..]),
+ Err(Err::Error(error_position!(&b"xxx"[..], ErrorKind::Tag)))
+ );
+ assert_eq!(
+ terminated_abcd_efgh(&b"xxxxdef"[..]),
+ Err(Err::Error(error_position!(&b"xxxxdef"[..], ErrorKind::Tag)))
+ );
+ assert_eq!(
+ terminated_abcd_efgh(&b"abcdxxxx"[..]),
+ Err(Err::Error(error_position!(&b"xxxx"[..], ErrorKind::Tag)))
+ );
+}
+
+#[test]
+fn delimited_test() {
+ fn delimited_abc_def_ghi(i: &[u8]) -> IResult<&[u8], &[u8]> {
+ delimited(tag("abc"), tag("def"), tag("ghi"))(i)
+ }
+
+ assert_eq!(
+ delimited_abc_def_ghi(&b"abcdefghijkl"[..]),
+ Ok((&b"jkl"[..], &b"def"[..]))
+ );
+ assert_eq!(
+ delimited_abc_def_ghi(&b"ab"[..]),
+ Err(Err::Incomplete(Needed::new(1)))
+ );
+ assert_eq!(
+ delimited_abc_def_ghi(&b"abcde"[..]),
+ Err(Err::Incomplete(Needed::new(1)))
+ );
+ assert_eq!(
+ delimited_abc_def_ghi(&b"abcdefgh"[..]),
+ Err(Err::Incomplete(Needed::new(1)))
+ );
+ assert_eq!(
+ delimited_abc_def_ghi(&b"xxx"[..]),
+ Err(Err::Error(error_position!(&b"xxx"[..], ErrorKind::Tag)))
+ );
+ assert_eq!(
+ delimited_abc_def_ghi(&b"xxxdefghi"[..]),
+ Err(Err::Error(error_position!(
+ &b"xxxdefghi"[..],
+ ErrorKind::Tag
+ ),))
+ );
+ assert_eq!(
+ delimited_abc_def_ghi(&b"abcxxxghi"[..]),
+ Err(Err::Error(error_position!(&b"xxxghi"[..], ErrorKind::Tag)))
+ );
+ assert_eq!(
+ delimited_abc_def_ghi(&b"abcdefxxx"[..]),
+ Err(Err::Error(error_position!(&b"xxx"[..], ErrorKind::Tag)))
+ );
+}
+
+#[test]
+fn tuple_test() {
+ fn tuple_3(i: &[u8]) -> IResult<&[u8], (u16, &[u8], &[u8])> {
+ tuple((be_u16, take(3u8), tag("fg")))(i)
+ }
+
+ assert_eq!(
+ tuple_3(&b"abcdefgh"[..]),
+ Ok((&b"h"[..], (0x6162u16, &b"cde"[..], &b"fg"[..])))
+ );
+ assert_eq!(tuple_3(&b"abcd"[..]), Err(Err::Incomplete(Needed::new(1))));
+ assert_eq!(tuple_3(&b"abcde"[..]), Err(Err::Incomplete(Needed::new(2))));
+ assert_eq!(
+ tuple_3(&b"abcdejk"[..]),
+ Err(Err::Error(error_position!(&b"jk"[..], ErrorKind::Tag)))
+ );
+}
+
+#[test]
+fn unit_type() {
+ assert_eq!(
+ tuple::<&'static str, (), Error<&'static str>, ()>(())("abxsbsh"),
+ Ok(("abxsbsh", ()))
+ );
+ assert_eq!(
+ tuple::<&'static str, (), Error<&'static str>, ()>(())("sdfjakdsas"),
+ Ok(("sdfjakdsas", ()))
+ );
+ assert_eq!(
+ tuple::<&'static str, (), Error<&'static str>, ()>(())(""),
+ Ok(("", ()))
+ );
+}