diff --git a/doc/choosing_a_combinator.md b/doc/choosing_a_combinator.md index 07744efa..3363f63c 100644 --- a/doc/choosing_a_combinator.md +++ b/doc/choosing_a_combinator.md @@ -33,11 +33,11 @@ Those are used to recognize the lowest level elements of your grammar, like, "he | combinator | usage | input | output | comment | |---|---|---|---|---| -| [delimited](https://docs.rs/nom/latest/nom/sequence/fn.delimited.html) | `delimited(char('('), take(2), char(')'))` | `"(ab)cd"` | `Ok(("cd", "ab"))` || -| [preceded](https://docs.rs/nom/latest/nom/sequence/fn.preceded.html) | `preceded(tag("ab"), tag("XY"))` | `"abXYZ"` | `Ok(("Z", "XY"))` || -| [terminated](https://docs.rs/nom/latest/nom/sequence/fn.terminated.html) | `terminated(tag("ab"), tag("XY"))` | `"abXYZ"` | `Ok(("Z", "ab"))` || -| [pair](https://docs.rs/nom/latest/nom/sequence/fn.pair.html) | `pair(tag("ab"), tag("XY"))` | `"abXYZ"` | `Ok(("Z", ("ab", "XY")))` || -| [separated_pair](https://docs.rs/nom/latest/nom/sequence/fn.separated_pair.html) | `separated_pair(tag("hello"), char(','), tag("world"))` | `"hello,world!"` | `Ok(("!", ("hello", "world")))` || +| [delimited](https://docs.rs/nom/latest/nom/sequence/fn.delimited.html) | `delimited(char('('), take(2), char(')'))` | `"(ab)cd"` | `Ok(("cd", "ab"))` |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.| +| [preceded](https://docs.rs/nom/latest/nom/sequence/fn.preceded.html) | `preceded(tag("ab"), tag("XY"))` | `"abXYZ"` | `Ok(("Z", "XY"))` |Matches an object from the first parser and discards it, then gets an object from the second parser.| +| [terminated](https://docs.rs/nom/latest/nom/sequence/fn.terminated.html) | `terminated(tag("ab"), tag("XY"))` | `"abXYZ"` | `Ok(("Z", "ab"))` |Gets an object from the first parser, then matches an object from the second parser and discards it.| +| [pair](https://docs.rs/nom/latest/nom/sequence/fn.pair.html) | `pair(tag("ab"), tag("XY"))` | `"abXYZ"` | `Ok(("Z", ("ab", "XY")))` |Gets an object from the first parser, then gets another object from the second parser.| +| [separated_pair](https://docs.rs/nom/latest/nom/sequence/fn.separated_pair.html) | `separated_pair(tag("hello"), char(','), tag("world"))` | `"hello,world!"` | `Ok(("!", ("hello", "world")))` |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.| | [tuple](https://docs.rs/nom/latest/nom/sequence/fn.tuple.html) | `tuple((tag("ab"), tag("XY"), take(1)))` | `"abXYZ!"` | `Ok(("!", ("ab", "XY", "Z")))` | Chains parsers and assemble the sub results in a tuple. You can use as many child parsers as you can put elements in a tuple| ## Applying a parser multiple times diff --git a/src/multi/mod.rs b/src/multi/mod.rs index a1436d6d..d78611f9 100644 --- a/src/multi/mod.rs +++ b/src/multi/mod.rs @@ -335,7 +335,7 @@ where /// [`cut`][crate::combinator::cut]. /// /// # Arguments -/// * `sep` Parses the separator between list elements. Must be consuming. +/// * `sep` Parses the separator between list elements. /// * `f` Parses the elements of the list. /// /// ```rust @@ -457,7 +457,7 @@ where /// [`cut`][crate::combinator::cut]. /// /// # Arguments -/// * `sep` Parses the separator between list elements. Must be consuming. +/// * `sep` Parses the separator between list elements. /// * `f` Parses the elements of the list. /// ```rust /// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult, Parser}; diff --git a/src/multi/tests.rs b/src/multi/tests.rs index 080240cd..1003552f 100644 --- a/src/multi/tests.rs +++ b/src/multi/tests.rs @@ -82,6 +82,9 @@ fn separated_list1_test() { fn multi_longsep(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { separated_list1(tag(".."), tag("abcd")).parse(i) } + fn empty_both(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> { + separated_list0(tag(""), tag("")).parse(i) + } let a = &b"abcdef"[..]; let b = &b"abcd,abcdef"[..]; @@ -100,6 +103,10 @@ fn separated_list1_test() { multi(c), Err(Err::Error(error_position!(c, ErrorKind::Tag))) ); + assert_eq!( + empty_both(f), + Err(Err::Error(error_position!(f, ErrorKind::SeparatedList))) + ); let res3 = vec![&b"abcd"[..], &b"abcd"[..]]; assert_eq!(multi(d), Ok((&b",ef"[..], res3)));