consumed (previously with_input) parser combinator (#1146)

* consumed parser

* Update

Add test and modify choosing a combinator
This commit is contained in:
Nia Calia-Bogan 2020-08-30 09:05:38 -04:00 committed by GitHub
parent 4a30ddc88d
commit 48c5a7cc3f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 71 additions and 1 deletions

View File

@ -85,6 +85,7 @@ Parsing integers from binary formats can be done in two ways: With parser functi
- `parse_to!`: Uses the parse method from `std::str::FromStr` to convert the current input to the specified type
- `peek!`: Returns a result without consuming the input
- `recognize!`: If the child parser was successful, return the consumed input as the produced value
- `consumed()`: If the child parser was successful, return a tuple of the consumed input and the produced output.
- `return_error!`: Prevents backtracking if the child parser fails
- `tap!`: Allows access to the parser's result without affecting it
- `verify!`: Returns the result of the child parser if it satisfies a verification function

View File

@ -660,7 +660,76 @@ where
recognize(parser)(input)
}
/// Transforms an error to failure.
/// if the child parser was successful, return the consumed input with the output
/// as a tuple. Functions similarly to [recognize](fn.recognize.html) except it
/// returns the parser output as well.
///
/// This can be useful especially in cases where the output is not the same type
/// as the input, or the input is a user defined type.
///
/// Returned tuple is of the format `(consumed input, produced output)`.
///
/// ```rust
/// # #[macro_use] extern crate nom;
/// # use nom::{Err,error::ErrorKind, IResult};
/// use nom::combinator::{consumed, value, recognize, map};
/// use nom::character::complete::{char, alpha1};
/// use nom::bytes::complete::tag;
/// use nom::sequence::separated_pair;
///
/// fn inner_parser(input: &str) -> IResult<&str, bool> {
/// value(true, tag("1234"))(input)
/// }
///
/// # fn main() {
///
/// let mut consumed_parser = consumed(value(true, separated_pair(alpha1, char(','), alpha1)));
///
/// assert_eq!(consumed_parser("abcd,efgh1"), Ok(("1", ("abcd,efgh", true))));
/// assert_eq!(consumed_parser("abcd;"),Err(Err::Error((";", ErrorKind::Char))));
///
///
/// // the first output (representing the consumed input)
/// // should be the same as that of the `recognize` parser.
/// let mut recognize_parser = recognize(inner_parser);
/// let mut consumed_parser = map(consumed(inner_parser), |(consumed, output)| consumed);
///
/// assert_eq!(recognize_parser("1234"), consumed_parser("1234"));
/// assert_eq!(recognize_parser("abcd"), consumed_parser("abcd"));
/// # }
/// ```
pub fn consumed<I, O, F, E>(mut parser: F) -> impl FnMut(I) -> IResult<I, (I, O), E>
where
I: Clone + Offset + Slice<RangeTo<usize>>,
E: ParseError<I>,
F: Parser<I, O, E>
{
move |input: I| {
let i = input.clone();
match parser.parse(i) {
Ok((remaining, result )) => {
let index = input.offset(&remaining);
let consumed = input.slice(..index);
Ok((remaining, (consumed, result)))
},
Err(e) => Err(e)
}
}
}
#[doc(hidden)]
pub fn consumedc<I, O, E: ParseError<I>, F>(
input: I,
parser: F
) -> IResult<I, (I, O), E>
where
I: Clone + Offset + Slice<RangeTo<usize>>,
E: ParseError<E>,
F: Fn(I) -> IResult<I, O, E>
{ consumed(parser)(input) }
/// transforms an error to failure
///
/// ```rust
/// # #[macro_use] extern crate nom;