Trait winnow::Parser

source ·
pub trait Parser<I, O, E> {
Show 20 methods fn parse_next(&mut self, input: I) -> IResult<I, O, E>; fn parse(&mut self, input: I) -> Result<O, E>
    where
        I: Stream + StreamIsPartial + Clone,
        E: ParseError<I>
, { ... } fn by_ref(&mut self) -> ByRef<'_, Self>
    where
        Self: Sized
, { ... } fn value<O2>(self, val: O2) -> Value<Self, I, O, O2, E>
    where
        Self: Sized,
        O2: Clone
, { ... } fn void(self) -> Void<Self, I, O, E>
    where
        Self: Sized
, { ... } fn output_into<O2>(self) -> OutputInto<Self, I, O, O2, E>
    where
        Self: Sized,
        O: Into<O2>
, { ... } fn recognize(self) -> Recognize<Self, I, O, E>
    where
        Self: Sized,
        I: Stream + Offset
, { ... } fn with_recognized(self) -> WithRecognized<Self, I, O, E>
    where
        Self: Sized,
        I: Stream + Offset
, { ... } fn span(self) -> Span<Self, I, O, E>
    where
        Self: Sized,
        I: Stream + Location
, { ... } fn with_span(self) -> WithSpan<Self, I, O, E>
    where
        Self: Sized,
        I: Stream + Location
, { ... } fn map<G, O2>(self, map: G) -> Map<Self, G, I, O, O2, E>
    where
        G: Fn(O) -> O2,
        Self: Sized
, { ... } fn map_res<G, O2, E2>(self, map: G) -> MapRes<Self, G, I, O, O2, E, E2>
    where
        Self: Sized,
        G: FnMut(O) -> Result<O2, E2>,
        I: Clone,
        E: FromExternalError<I, E2>
, { ... } fn verify_map<G, O2>(self, map: G) -> VerifyMap<Self, G, I, O, O2, E>
    where
        Self: Sized,
        G: FnMut(O) -> Option<O2>,
        I: Clone,
        E: ParseError<I>
, { ... } fn flat_map<G, H, O2>(self, map: G) -> FlatMap<Self, G, H, I, O, O2, E>
    where
        Self: Sized,
        G: FnMut(O) -> H,
        H: Parser<I, O2, E>
, { ... } fn and_then<G, O2>(self, inner: G) -> AndThen<Self, G, I, O, O2, E>
    where
        Self: Sized,
        G: Parser<O, O2, E>,
        O: StreamIsPartial
, { ... } fn parse_to<O2>(self) -> ParseTo<Self, I, O, O2, E>
    where
        Self: Sized,
        I: Stream,
        O: ParseSlice<O2>,
        E: ParseError<I>
, { ... } fn verify<G, O2>(self, filter: G) -> Verify<Self, G, I, O, O2, E>
    where
        Self: Sized,
        G: Fn(&O2) -> bool,
        I: Clone,
        O: Borrow<O2>,
        O2: ?Sized,
        E: ParseError<I>
, { ... } fn context<C>(self, context: C) -> Context<Self, I, O, E, C>
    where
        Self: Sized,
        I: Stream,
        E: ContextError<I, C>,
        C: Clone + Debug
, { ... } fn complete_err(self) -> CompleteErr<Self>
    where
        Self: Sized
, { ... } fn err_into<E2>(self) -> ErrInto<Self, I, O, E, E2>
    where
        Self: Sized,
        E: Into<E2>
, { ... }
}
Expand description

Core trait for parsing

The simplest way to implement a Parser is with a function

use winnow::prelude::*;

fn success(input: &str) -> IResult<&str, ()> {
    let output = ();
    Ok((input, output))
}

let (input, output) = success.parse_next("Hello").unwrap();
assert_eq!(input, "Hello");  // We didn't consume any input

which can be made stateful by returning a function

use winnow::prelude::*;

fn success<O: Clone>(output: O) -> impl FnMut(&str) -> IResult<&str, O> {
    move |input: &str| {
        let output = output.clone();
        Ok((input, output))
    }
}

let (input, output) = success("World").parse_next("Hello").unwrap();
assert_eq!(input, "Hello");  // We didn't consume any input
assert_eq!(output, "World");

Additionally, some basic types implement Parser as well, including

Required Methods§

Take tokens from the Stream, turning it into the output

This includes advancing the Stream to the next location.

Provided Methods§

Parse all of input, generating O from it

Treat &mut Self as a parser

This helps when needing to move a Parser when all you have is a &mut Parser.

Example

Because parsers are FnMut, they can be called multiple times. This prevents moving f into length_data and g into Parser::complete_err:

pub fn length_value<'i, O, E: ParseError<&'i [u8]>>(
    mut f: impl Parser<&'i [u8], usize, E>,
    mut g: impl Parser<&'i [u8], O, E>
) -> impl FnMut(&'i [u8]) -> IResult<&'i [u8], O, E> {
  move |i: &'i [u8]| {
    let (i, data) = length_data(f).parse_next(i)?;
    let (_, o) = g.complete().parse_next(data)?;
    Ok((i, o))
  }
}

By adding by_ref, we can make this work:

pub fn length_value<'i, O, E: ParseError<&'i [u8]>>(
    mut f: impl Parser<&'i [u8], usize, E>,
    mut g: impl Parser<&'i [u8], O, E>
) -> impl FnMut(&'i [u8]) -> IResult<&'i [u8], O, E> {
  move |i: &'i [u8]| {
    let (i, data) = length_data(f.by_ref()).parse_next(i)?;
    let (_, o) = g.by_ref().complete_err().parse_next(data)?;
    Ok((i, o))
  }
}

Produce the provided value

Example
use winnow::character::alpha1;

let mut parser = alpha1.value(1234);

assert_eq!(parser.parse_next("abcd"), Ok(("", 1234)));
assert_eq!(parser.parse_next("123abcd;"), Err(ErrMode::Backtrack(Error::new("123abcd;", ErrorKind::Slice))));

Discards the output of the Parser

Example
use winnow::character::alpha1;

let mut parser = alpha1.void();

assert_eq!(parser.parse_next("abcd"), Ok(("", ())));
assert_eq!(parser.parse_next("123abcd;"), Err(ErrMode::Backtrack(Error::new("123abcd;", ErrorKind::Slice))));

Convert the parser’s output to another type using std::convert::From

Example
use winnow::character::alpha1;

 fn parser1(i: &str) -> IResult<&str, &str> {
   alpha1(i)
 }

 let mut parser2 = parser1.output_into();

// the parser converts the &str output of the child parser into a Vec<u8>
let bytes: IResult<&str, Vec<u8>> = parser2.parse_next("abcd");
assert_eq!(bytes, Ok(("", vec![97, 98, 99, 100])));

Produce the consumed input as produced value.

Example
use winnow::character::{alpha1};
use winnow::sequence::separated_pair;

let mut parser = separated_pair(alpha1, ',', alpha1).recognize();

assert_eq!(parser.parse_next("abcd,efgh"), Ok(("", "abcd,efgh")));
assert_eq!(parser.parse_next("abcd;"),Err(ErrMode::Backtrack(Error::new(";", ErrorKind::Verify))));

Produce the consumed input with the output

Functions similarly to recognize 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 (produced output, consumed input).

Example
use winnow::character::{alpha1};
use winnow::bytes::tag;
use winnow::sequence::separated_pair;

fn inner_parser(input: &str) -> IResult<&str, bool> {
    "1234".value(true).parse_next(input)
}


let mut consumed_parser = separated_pair(alpha1, ',', alpha1).value(true).with_recognized();

assert_eq!(consumed_parser.parse_next("abcd,efgh1"), Ok(("1", (true, "abcd,efgh"))));
assert_eq!(consumed_parser.parse_next("abcd;"),Err(ErrMode::Backtrack(Error::new(";", ErrorKind::Verify))));

// the second output (representing the consumed input)
// should be the same as that of the `recognize` parser.
let mut recognize_parser = inner_parser.recognize();
let mut consumed_parser = inner_parser.with_recognized().map(|(output, consumed)| consumed);

assert_eq!(recognize_parser.parse_next("1234"), consumed_parser.parse_next("1234"));
assert_eq!(recognize_parser.parse_next("abcd"), consumed_parser.parse_next("abcd"));

Produce the location of the consumed input as produced value.

Example
use winnow::stream::Located;
use winnow::character::alpha1;
use winnow::sequence::separated_pair;

let mut parser = separated_pair(alpha1.span(), ',', alpha1.span());

assert_eq!(parser.parse(Located::new("abcd,efgh")), Ok((0..4, 5..9)));
assert_eq!(parser.parse_next(Located::new("abcd;")),Err(ErrMode::Backtrack(Error::new(Located::new("abcd;").next_slice(4).0, ErrorKind::Verify))));

Produce the location of consumed input with the output

Functions similarly to Parser::span 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 (produced output, consumed input).

Example
use winnow::stream::Located;
use winnow::character::alpha1;
use winnow::bytes::tag;
use winnow::sequence::separated_pair;

fn inner_parser(input: Located<&str>) -> IResult<Located<&str>, bool> {
    "1234".value(true).parse_next(input)
}


let mut consumed_parser = separated_pair(alpha1.value(1).with_span(), ',', alpha1.value(2).with_span());

assert_eq!(consumed_parser.parse(Located::new("abcd,efgh")), Ok(((1, 0..4), (2, 5..9))));
assert_eq!(consumed_parser.parse_next(Located::new("abcd;")),Err(ErrMode::Backtrack(Error::new(Located::new("abcd;").next_slice(4).0, ErrorKind::Verify))));

// the second output (representing the consumed input)
// should be the same as that of the `span` parser.
let mut recognize_parser = inner_parser.span();
let mut consumed_parser = inner_parser.with_span().map(|(output, consumed)| consumed);

assert_eq!(recognize_parser.parse_next(Located::new("1234")), consumed_parser.parse_next(Located::new("1234")));
assert_eq!(recognize_parser.parse_next(Located::new("abcd")), consumed_parser.parse_next(Located::new("abcd")));

Maps a function over the output of a parser

Example
use winnow::{error::ErrMode,error::ErrorKind, error::Error, IResult,Parser};
use winnow::character::digit1;

let mut parser = digit1.map(|s: &str| s.len());

// the parser will count how many characters were returned by digit1
assert_eq!(parser.parse_next("123456"), Ok(("", 6)));

// this will fail if digit1 fails
assert_eq!(parser.parse_next("abc"), Err(ErrMode::Backtrack(Error::new("abc", ErrorKind::Slice))));

Applies a function returning a Result over the output of a parser.

Example
use winnow::character::digit1;

let mut parse = digit1.map_res(|s: &str| s.parse::<u8>());

// the parser will convert the result of digit1 to a number
assert_eq!(parse.parse_next("123"), Ok(("", 123)));

// this will fail if digit1 fails
assert_eq!(parse.parse_next("abc"), Err(ErrMode::Backtrack(Error::new("abc", ErrorKind::Slice))));

// this will fail if the mapped function fails (a `u8` is too small to hold `123456`)
assert_eq!(parse.parse_next("123456"), Err(ErrMode::Backtrack(Error::new("123456", ErrorKind::Verify))));

Apply both Parser::verify and Parser::map.

Example
use winnow::character::digit1;

let mut parse = digit1.verify_map(|s: &str| s.parse::<u8>().ok());

// the parser will convert the result of digit1 to a number
assert_eq!(parse.parse_next("123"), Ok(("", 123)));

// this will fail if digit1 fails
assert_eq!(parse.parse_next("abc"), Err(ErrMode::Backtrack(Error::new("abc", ErrorKind::Slice))));

// this will fail if the mapped function fails (a `u8` is too small to hold `123456`)
assert_eq!(parse.parse_next("123456"), Err(ErrMode::Backtrack(Error::new("123456", ErrorKind::Verify))));

Creates a parser from the output of this one

Example
use winnow::bytes::take;
use winnow::number::u8;

fn length_data(input: &[u8]) -> IResult<&[u8], &[u8]> {
    u8.flat_map(take).parse_next(input)
}

assert_eq!(length_data.parse_next(&[2, 0, 1, 2][..]), Ok((&[2][..], &[0, 1][..])));
assert_eq!(length_data.parse_next(&[4, 0, 1, 2][..]), Err(ErrMode::Backtrack(Error::new(&[0, 1, 2][..], ErrorKind::Slice))));

which is the same as

use winnow::bytes::take;
use winnow::number::u8;

fn length_data(input: &[u8]) -> IResult<&[u8], &[u8]> {
    let (input, length) = u8.parse_next(input)?;
    let (input, data) = take(length).parse_next(input)?;
    Ok((input, data))
}

assert_eq!(length_data.parse_next(&[2, 0, 1, 2][..]), Ok((&[2][..], &[0, 1][..])));
assert_eq!(length_data.parse_next(&[4, 0, 1, 2][..]), Err(ErrMode::Backtrack(Error::new(&[0, 1, 2][..], ErrorKind::Slice))));

Applies a second parser over the output of the first one

Example
use winnow::character::digit1;
use winnow::bytes::take;

let mut digits = take(5u8).and_then(digit1);

assert_eq!(digits.parse_next("12345"), Ok(("", "12345")));
assert_eq!(digits.parse_next("123ab"), Ok(("", "123")));
assert_eq!(digits.parse_next("123"), Err(ErrMode::Backtrack(Error::new("123", ErrorKind::Slice))));

Apply std::str::FromStr to the output of the parser

Example
use winnow::{error::ErrMode,error::ErrorKind, error::Error, IResult,Parser};
use winnow::character::digit1;

fn parser(input: &str) -> IResult<&str, u64> {
    digit1.parse_to().parse_next(input)
}

// the parser will count how many characters were returned by digit1
assert_eq!(parser.parse_next("123456"), Ok(("", 123456)));

// this will fail if digit1 fails
assert_eq!(parser.parse_next("abc"), Err(ErrMode::Backtrack(Error::new("abc", ErrorKind::Slice))));

Returns the output of the child parser if it satisfies a verification function.

The verification function takes as argument a reference to the output of the parser.

Example

let mut parser = alpha1.verify(|s: &str| s.len() == 4);

assert_eq!(parser.parse_next("abcd"), Ok(("", "abcd")));
assert_eq!(parser.parse_next("abcde"), Err(ErrMode::Backtrack(Error::new("abcde", ErrorKind::Verify))));
assert_eq!(parser.parse_next("123abcd;"),Err(ErrMode::Backtrack(Error::new("123abcd;", ErrorKind::Slice))));

If parsing fails, add context to the error

This is used mainly to add user friendly information to errors when backtracking through a parse tree.

Transforms Incomplete into Backtrack

Example

let mut parser = take(5u8).complete_err();

assert_eq!(parser.parse_next(Partial::new("abcdefg")), Ok((Partial::new("fg"), "abcde")));
assert_eq!(parser.parse_next(Partial::new("abcd")), Err(ErrMode::Backtrack(Error::new(Partial::new("abcd"), ErrorKind::Complete))));

Convert the parser’s error to another type using std::convert::From

Trait Implementations§

Take tokens from the Stream, turning it into the output Read more
Treat &mut Self as a parser Read more
Produce the provided value Read more
Discards the output of the Parser Read more
Convert the parser’s output to another type using std::convert::From Read more
Maps a function over the output of a parser Read more
Creates a parser from the output of this one Read more
Convert the parser’s error to another type using std::convert::From

Implementations on Foreign Types§

This is a shortcut for one_of.

Example

fn parser(i: &[u8]) -> IResult<&[u8], u8> {
    b'a'.parse_next(i)
}
assert_eq!(parser(&b"abc"[..]), Ok((&b"bc"[..], b'a')));
assert_eq!(parser(&b" abc"[..]), Err(ErrMode::Backtrack(Error::new(&b" abc"[..], ErrorKind::Verify))));
assert_eq!(parser(&b"bc"[..]), Err(ErrMode::Backtrack(Error::new(&b"bc"[..], ErrorKind::Verify))));
assert_eq!(parser(&b""[..]), Err(ErrMode::Backtrack(Error::new(&b""[..], ErrorKind::Token))));

This is a shortcut for one_of.

Example

fn parser(i: &str) -> IResult<&str, char> {
    'a'.parse_next(i)
}
assert_eq!(parser("abc"), Ok(("bc", 'a')));
assert_eq!(parser(" abc"), Err(ErrMode::Backtrack(Error::new(" abc", ErrorKind::Verify))));
assert_eq!(parser("bc"), Err(ErrMode::Backtrack(Error::new("bc", ErrorKind::Verify))));
assert_eq!(parser(""), Err(ErrMode::Backtrack(Error::new("", ErrorKind::Token))));

This is a shortcut for tag.

Example


fn parser(s: &[u8]) -> IResult<&[u8], &[u8]> {
  alt((&"Hello"[..], take(5usize))).parse_next(s)
}

assert_eq!(parser(&b"Hello, World!"[..]), Ok((&b", World!"[..], &b"Hello"[..])));
assert_eq!(parser(&b"Something"[..]), Ok((&b"hing"[..], &b"Somet"[..])));
assert_eq!(parser(&b"Some"[..]), Err(ErrMode::Backtrack(Error::new(&b"Some"[..], ErrorKind::Slice))));
assert_eq!(parser(&b""[..]), Err(ErrMode::Backtrack(Error::new(&b""[..], ErrorKind::Slice))));

This is a shortcut for tag.

Example


fn parser(s: &[u8]) -> IResult<&[u8], &[u8]> {
  alt((b"Hello", take(5usize))).parse_next(s)
}

assert_eq!(parser(&b"Hello, World!"[..]), Ok((&b", World!"[..], &b"Hello"[..])));
assert_eq!(parser(&b"Something"[..]), Ok((&b"hing"[..], &b"Somet"[..])));
assert_eq!(parser(&b"Some"[..]), Err(ErrMode::Backtrack(Error::new(&b"Some"[..], ErrorKind::Slice))));
assert_eq!(parser(&b""[..]), Err(ErrMode::Backtrack(Error::new(&b""[..], ErrorKind::Slice))));

This is a shortcut for tag.

Example


fn parser(s: &str) -> IResult<&str, &str> {
  alt(("Hello", take(5usize))).parse_next(s)
}

assert_eq!(parser("Hello, World!"), Ok((", World!", "Hello")));
assert_eq!(parser("Something"), Ok(("hing", "Somet")));
assert_eq!(parser("Some"), Err(ErrMode::Backtrack(Error::new("Some", ErrorKind::Slice))));
assert_eq!(parser(""), Err(ErrMode::Backtrack(Error::new("", ErrorKind::Slice))));

Implementors§