diff options
Diffstat (limited to 'third_party/rust/nom/src/sequence')
-rw-r--r-- | third_party/rust/nom/src/sequence/mod.rs | 270 | ||||
-rw-r--r-- | third_party/rust/nom/src/sequence/tests.rs | 274 |
2 files changed, 544 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..e09d413483 --- /dev/null +++ b/third_party/rust/nom/src/sequence/mod.rs @@ -0,0 +1,270 @@ +//! 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); + +///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..201579be47 --- /dev/null +++ b/third_party/rust/nom/src/sequence/tests.rs @@ -0,0 +1,274 @@ +use super::*; +use crate::bytes::streaming::{tag, take}; +use crate::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))) + ); +} |