Trait parser_compose::Parser
source · pub trait Parser<In, Out, E> {
// Required method
fn try_parse(&self, input: In) -> Res<In, Out, E>;
// Provided methods
fn map<F, Mapped>(self, f: F) -> Map<Self, F, Out>
where Self: Sized,
F: Fn(Out) -> Mapped { ... }
fn map_err<F, M>(self, f: F) -> MapErr<Self, F, E>
where Self: Sized,
F: Fn(Error<E>) -> Error<M> { ... }
fn or<P>(self, next: P) -> Or<Self, P>
where Self: Sized { ... }
fn when<F>(self, pred: F) -> Predicate<Self, F>
where Self: Sized,
F: Fn(Out) -> bool { ... }
fn repeated<R: RepetitionArgument>(self, count: R) -> Repeat<Self, R>
where Self: Sized { ... }
fn optional(self) -> Optional<Self>
where Self: Sized { ... }
fn peeked(self) -> Peeked<Self>
where Self: Sized { ... }
fn not_peeked(self) -> NotPeeked<Self, Out>
where Self: Sized { ... }
fn and_then<F, U>(self, f: F) -> AndThen<Self, F, Out>
where Self: Sized,
F: Fn(Out) -> Result<U, Error<E>> { ... }
}
Expand description
A trait for parsers
A parser takes in input and either outputs a value or reports an error.
Implementing the trait
- Decide what types to provide for the input, output and error. For example a type that
implements
Parser<&str, u8, String>
can accept&str
as input totry_parse()
, and is expected to outputu8
s. If an error occurs, it is reported asError\<String\>
. - Implement
try_parse()
- Use combinators.
- ??profit??
The Parser
trait is already implemented for a couple primitive types. Check out the impl
sections below for more concrete examples
Required Methods§
Provided Methods§
sourcefn map<F, Mapped>(self, f: F) -> Map<Self, F, Out>where
Self: Sized,
F: Fn(Out) -> Mapped,
fn map<F, Mapped>(self, f: F) -> Map<Self, F, Out>where Self: Sized, F: Fn(Out) -> Mapped,
Returns a parser that maps a Parser<In, Out, E>
to Parser<In, Mapped, E>
by applying a
function to the result of the parser if it succeeded.
use parser_compose::Parser;
let msg = "a";
let (value, _) = "a".map(str::to_ascii_uppercase).try_parse(msg).unwrap();
assert_eq!(value, "A");
sourcefn map_err<F, M>(self, f: F) -> MapErr<Self, F, E>where
Self: Sized,
F: Fn(Error<E>) -> Error<M>,
fn map_err<F, M>(self, f: F) -> MapErr<Self, F, E>where Self: Sized, F: Fn(Error<E>) -> Error<M>,
Returns a parser that maps a Parser<In, Out, E>
to Parser<In, Out, Mapped>
by applying
a function to the error reported by the parser if it failed.
use parser_compose::{Error, Parser};
enum MyError { Fail }
let msg = "a";
let result = "b".map_err(|_| Error::Custom(MyError::Fail)).try_parse(msg);
assert!(result.is_err());
assert!(matches!(result, Err(Error::Custom(MyError::Fail))));
sourcefn or<P>(self, next: P) -> Or<Self, P>where
Self: Sized,
fn or<P>(self, next: P) -> Or<Self, P>where Self: Sized,
Returns a parser that succeeds if self
does. Otherwise, it’s outcome is that of next
.
use parser_compose::Parser;
let msg = "a";
let (value, _) = "1".or("a").try_parse(msg).unwrap();
assert_eq!(value, "a");
sourcefn when<F>(self, pred: F) -> Predicate<Self, F>where
Self: Sized,
F: Fn(Out) -> bool,
fn when<F>(self, pred: F) -> Predicate<Self, F>where Self: Sized, F: Fn(Out) -> bool,
Returns a new parser that succeeds if the predicate returns true. The predicate is given the extracted value of the current parser as an argument
use parser_compose::{any_str,Parser};
let msg = "boo";
let (value, _) = any_str.when(|s| s == "b").try_parse(msg).unwrap();
assert_eq!(value, "b");
sourcefn repeated<R: RepetitionArgument>(self, count: R) -> Repeat<Self, R>where
Self: Sized,
fn repeated<R: RepetitionArgument>(self, count: R) -> Repeat<Self, R>where Self: Sized,
Returns a parser that suceeds if it is able to repeat count
times.
count
can be:
- A single
usize
(e.g.8
): The parser will try to match at least 8 times and return aVec
of length 8 if it succeeds
use parser_compose::Parser;
let msg = "AAAA";
let (value, rest) = "A".repeated(3).try_parse(msg).unwrap();
assert_eq!(value, vec!["A", "A", "A"]);
assert_eq!(rest, "A");
- A range bounded inclusively from below (e.g.
3..
): The parser will try to match at least 3 times, but possibly more. If it succeeds, the returnedVec
is be guaranteed to have a value greater than 3.
use parser_compose::Parser;
let msg = "AAAA";
let (value, rest) = "A".repeated(2..).try_parse(msg).unwrap();
assert_eq!(value, vec!["A", "A", "A", "A"]);
assert_eq!(rest, "");
- A range bounded inclusively from above (e.g.
..=4
): The parser will try to match at most 4 times, but possibly less (including zero times!). If it succeeds, the returnedVec
will have at most 4 elements
use parser_compose::Parser;
let msg = "AA";
let (value, rest) = "A".repeated(..=4).try_parse(msg).unwrap();
assert_eq!(value, vec!["A", "A"]);
assert_eq!(rest, "");
- A range bounded inclusively from above and below (e.g.
3..=5
): The parser will try to match at least 3 times and at most 5 times. If it succeeds, the returnedVec
will have a length between 3 and 5
use parser_compose::Parser;
let msg = "AAAA";
let (value, rest) = "A".repeated(2..=3).try_parse(msg).unwrap();
assert_eq!(value, vec!["A", "A", "A"]);
assert_eq!(rest, "A");
sourcefn optional(self) -> Optional<Self>where
Self: Sized,
fn optional(self) -> Optional<Self>where Self: Sized,
Returns a parser always succeeds but wraps the output in an Option<Out>
. If the original
parser would have failed, the parser outputs a None
.
use parser_compose::Parser;
let msg = "a";
let ((b, a), _) = ("b".optional(), "a").try_parse(msg).unwrap();
assert_eq!(b, None);
assert_eq!(a, "a");
sourcefn peeked(self) -> Peeked<Self>where
Self: Sized,
fn peeked(self) -> Peeked<Self>where Self: Sized,
Returns a parser that succeeds or fails as normal, but never consumes any input regardless of the outcome. This can be used to look ahead.
It corresponds to the “and-predicate” operator in Parsing Expression Grammars.
use parser_compose::Parser;
// Recognize the sequence "a" followed by "b", but only if it is followed by a "c"
let a_then_b = ("a", "b", "c".peeked());
let (value, rest) = a_then_b.try_parse("abc").unwrap();
// note: the value gets recognized and returned, but it does not consume it.
assert_eq!(value, ("a", "b", "c"));
assert_eq!(rest, "c");
let result = a_then_b.try_parse("abb");
assert!(result.is_err());
sourcefn not_peeked(self) -> NotPeeked<Self, Out>where
Self: Sized,
fn not_peeked(self) -> NotPeeked<Self, Out>where Self: Sized,
Reverse of peeked()
. Returns a parse that succeeds if it was not
able to recognize the input and fails if it was able to.
It corresponds to the “not-predicate” operator in Parsing Expression Grammars.
use parser_compose::Parser;
// This parser matches "foo", but only if it is not followed by "bar"
let parser = ("foo", "bar".not_peeked());
let msg = "foobar";
let result = parser.try_parse(msg);
assert!(result.is_err());
let (value, rest) = parser.try_parse("foobaz").unwrap();
assert_eq!(value, ("foo", ()));
assert_eq!(rest, "baz");
sourcefn and_then<F, U>(self, f: F) -> AndThen<Self, F, Out>where
Self: Sized,
F: Fn(Out) -> Result<U, Error<E>>,
fn and_then<F, U>(self, f: F) -> AndThen<Self, F, Out>where Self: Sized, F: Fn(Out) -> Result<U, Error<E>>,
Returns a parser that is similar to map()
in its behavior, except
that the provided closure may fail, which affects the outcome of the parser.
use std::str::from_utf8;
use parser_compose::{Error,Parser};
let msg = [98].as_slice();
let (value, _) = [98].and_then(|b| {
// converting to utf8 can fail
from_utf8(b).map_err(|_| Error::Mismatch)
}).try_parse(msg).unwrap();
assert_eq!("b", value);
Implementations on Foreign Types§
source§impl<In, P0, O0, P1, O1, P2, O2, P3, O3, P4, O4, P5, O5, E> Parser<In, (O0, O1, O2, O3, O4, O5), E> for (P0, P1, P2, P3, P4, P5)where
P0: Parser<In, O0, E>,
P1: Parser<In, O1, E>,
P2: Parser<In, O2, E>,
P3: Parser<In, O3, E>,
P4: Parser<In, O4, E>,
P5: Parser<In, O5, E>,
impl<In, P0, O0, P1, O1, P2, O2, P3, O3, P4, O4, P5, O5, E> Parser<In, (O0, O1, O2, O3, O4, O5), E> for (P0, P1, P2, P3, P4, P5)where P0: Parser<In, O0, E>, P1: Parser<In, O1, E>, P2: Parser<In, O2, E>, P3: Parser<In, O3, E>, P4: Parser<In, O4, E>, P5: Parser<In, O5, E>,
A tuple of parsers is treated as a parser that tries its inner parsers in turn, feeding the leftover input from the first as the input to the other and so on
Calling the .try_parse()
on the tuple returns a new tuple containing the extracted values.
This is implemented for tuples up to 12 items long
fn try_parse(&self, input: In) -> Res<In, (O0, O1, O2, O3, O4, O5), E>
source§impl<'pat, 'input, T> Parser<&'input [T], &'pat [T], ()> for &'pat [T]where
T: PartialEq,
impl<'pat, 'input, T> Parser<&'input [T], &'pat [T], ()> for &'pat [T]where T: PartialEq,
A slice is treated as a parser that tries to match itself at the start of some longer slice
The Parser
trait is implemented for all slices, which all
&[T]
will have the try_parse()
method for all T
.
Calling it will try to do a prefix match of the input with the slice used as the pattern.
use parser_compose::Parser;
let msg = &['H', 'E', 'L', 'L', 'O'][..];
let (res, rest) = ['H', 'E'].as_slice().try_parse(msg).unwrap();
assert_eq!(res, &['H', 'E'][..]);
assert_eq!(rest, &['L', 'L', 'O'][..]);
source§impl<In, P0, O0, P1, O1, P2, O2, P3, O3, P4, O4, E> Parser<In, (O0, O1, O2, O3, O4), E> for (P0, P1, P2, P3, P4)where
P0: Parser<In, O0, E>,
P1: Parser<In, O1, E>,
P2: Parser<In, O2, E>,
P3: Parser<In, O3, E>,
P4: Parser<In, O4, E>,
impl<In, P0, O0, P1, O1, P2, O2, P3, O3, P4, O4, E> Parser<In, (O0, O1, O2, O3, O4), E> for (P0, P1, P2, P3, P4)where P0: Parser<In, O0, E>, P1: Parser<In, O1, E>, P2: Parser<In, O2, E>, P3: Parser<In, O3, E>, P4: Parser<In, O4, E>,
A tuple of parsers is treated as a parser that tries its inner parsers in turn, feeding the leftover input from the first as the input to the other and so on
Calling the .try_parse()
on the tuple returns a new tuple containing the extracted values.
This is implemented for tuples up to 12 items long
fn try_parse(&self, input: In) -> Res<In, (O0, O1, O2, O3, O4), E>
source§impl<In, P0, O0, P1, O1, P2, O2, P3, O3, P4, O4, P5, O5, P6, O6, E> Parser<In, (O0, O1, O2, O3, O4, O5, O6), E> for (P0, P1, P2, P3, P4, P5, P6)where
P0: Parser<In, O0, E>,
P1: Parser<In, O1, E>,
P2: Parser<In, O2, E>,
P3: Parser<In, O3, E>,
P4: Parser<In, O4, E>,
P5: Parser<In, O5, E>,
P6: Parser<In, O6, E>,
impl<In, P0, O0, P1, O1, P2, O2, P3, O3, P4, O4, P5, O5, P6, O6, E> Parser<In, (O0, O1, O2, O3, O4, O5, O6), E> for (P0, P1, P2, P3, P4, P5, P6)where P0: Parser<In, O0, E>, P1: Parser<In, O1, E>, P2: Parser<In, O2, E>, P3: Parser<In, O3, E>, P4: Parser<In, O4, E>, P5: Parser<In, O5, E>, P6: Parser<In, O6, E>,
A tuple of parsers is treated as a parser that tries its inner parsers in turn, feeding the leftover input from the first as the input to the other and so on
Calling the .try_parse()
on the tuple returns a new tuple containing the extracted values.
This is implemented for tuples up to 12 items long
fn try_parse(&self, input: In) -> Res<In, (O0, O1, O2, O3, O4, O5, O6), E>
source§impl<In, P0, O0, P1, O1, E> Parser<In, (O0, O1), E> for (P0, P1)where
P0: Parser<In, O0, E>,
P1: Parser<In, O1, E>,
impl<In, P0, O0, P1, O1, E> Parser<In, (O0, O1), E> for (P0, P1)where P0: Parser<In, O0, E>, P1: Parser<In, O1, E>,
A tuple of parsers is treated as a parser that tries its inner parsers in turn, feeding the leftover input from the first as the input to the other and so on
Calling the .try_parse()
on the tuple returns a new tuple containing the extracted values.
This is implemented for tuples up to 12 items long
source§impl<In, P0, O0, P1, O1, P2, O2, P3, O3, P4, O4, P5, O5, P6, O6, P7, O7, P8, O8, P9, O9, E> Parser<In, (O0, O1, O2, O3, O4, O5, O6, O7, O8, O9), E> for (P0, P1, P2, P3, P4, P5, P6, P7, P8, P9)where
P0: Parser<In, O0, E>,
P1: Parser<In, O1, E>,
P2: Parser<In, O2, E>,
P3: Parser<In, O3, E>,
P4: Parser<In, O4, E>,
P5: Parser<In, O5, E>,
P6: Parser<In, O6, E>,
P7: Parser<In, O7, E>,
P8: Parser<In, O8, E>,
P9: Parser<In, O9, E>,
impl<In, P0, O0, P1, O1, P2, O2, P3, O3, P4, O4, P5, O5, P6, O6, P7, O7, P8, O8, P9, O9, E> Parser<In, (O0, O1, O2, O3, O4, O5, O6, O7, O8, O9), E> for (P0, P1, P2, P3, P4, P5, P6, P7, P8, P9)where P0: Parser<In, O0, E>, P1: Parser<In, O1, E>, P2: Parser<In, O2, E>, P3: Parser<In, O3, E>, P4: Parser<In, O4, E>, P5: Parser<In, O5, E>, P6: Parser<In, O6, E>, P7: Parser<In, O7, E>, P8: Parser<In, O8, E>, P9: Parser<In, O9, E>,
A tuple of parsers is treated as a parser that tries its inner parsers in turn, feeding the leftover input from the first as the input to the other and so on
Calling the .try_parse()
on the tuple returns a new tuple containing the extracted values.
This is implemented for tuples up to 12 items long
fn try_parse( &self, input: In ) -> Res<In, (O0, O1, O2, O3, O4, O5, O6, O7, O8, O9), E>
source§impl<In, P0, O0, E> Parser<In, (O0,), E> for (P0,)where
P0: Parser<In, O0, E>,
impl<In, P0, O0, E> Parser<In, (O0,), E> for (P0,)where P0: Parser<In, O0, E>,
A tuple of parsers is treated as a parser that tries its inner parsers in turn, feeding the leftover input from the first as the input to the other and so on
Calling the .try_parse()
on the tuple returns a new tuple containing the extracted values.
This is implemented for tuples up to 12 items long
source§impl<In, P0, O0, P1, O1, P2, O2, P3, O3, P4, O4, P5, O5, P6, O6, P7, O7, E> Parser<In, (O0, O1, O2, O3, O4, O5, O6, O7), E> for (P0, P1, P2, P3, P4, P5, P6, P7)where
P0: Parser<In, O0, E>,
P1: Parser<In, O1, E>,
P2: Parser<In, O2, E>,
P3: Parser<In, O3, E>,
P4: Parser<In, O4, E>,
P5: Parser<In, O5, E>,
P6: Parser<In, O6, E>,
P7: Parser<In, O7, E>,
impl<In, P0, O0, P1, O1, P2, O2, P3, O3, P4, O4, P5, O5, P6, O6, P7, O7, E> Parser<In, (O0, O1, O2, O3, O4, O5, O6, O7), E> for (P0, P1, P2, P3, P4, P5, P6, P7)where P0: Parser<In, O0, E>, P1: Parser<In, O1, E>, P2: Parser<In, O2, E>, P3: Parser<In, O3, E>, P4: Parser<In, O4, E>, P5: Parser<In, O5, E>, P6: Parser<In, O6, E>, P7: Parser<In, O7, E>,
A tuple of parsers is treated as a parser that tries its inner parsers in turn, feeding the leftover input from the first as the input to the other and so on
Calling the .try_parse()
on the tuple returns a new tuple containing the extracted values.
This is implemented for tuples up to 12 items long
fn try_parse(&self, input: In) -> Res<In, (O0, O1, O2, O3, O4, O5, O6, O7), E>
source§impl<In, P0, O0, P1, O1, P2, O2, P3, O3, P4, O4, P5, O5, P6, O6, P7, O7, P8, O8, P9, O9, P10, O10, P11, O11, E> Parser<In, (O0, O1, O2, O3, O4, O5, O6, O7, O8, O9, O10, O11), E> for (P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11)where
P0: Parser<In, O0, E>,
P1: Parser<In, O1, E>,
P2: Parser<In, O2, E>,
P3: Parser<In, O3, E>,
P4: Parser<In, O4, E>,
P5: Parser<In, O5, E>,
P6: Parser<In, O6, E>,
P7: Parser<In, O7, E>,
P8: Parser<In, O8, E>,
P9: Parser<In, O9, E>,
P10: Parser<In, O10, E>,
P11: Parser<In, O11, E>,
impl<In, P0, O0, P1, O1, P2, O2, P3, O3, P4, O4, P5, O5, P6, O6, P7, O7, P8, O8, P9, O9, P10, O10, P11, O11, E> Parser<In, (O0, O1, O2, O3, O4, O5, O6, O7, O8, O9, O10, O11), E> for (P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11)where P0: Parser<In, O0, E>, P1: Parser<In, O1, E>, P2: Parser<In, O2, E>, P3: Parser<In, O3, E>, P4: Parser<In, O4, E>, P5: Parser<In, O5, E>, P6: Parser<In, O6, E>, P7: Parser<In, O7, E>, P8: Parser<In, O8, E>, P9: Parser<In, O9, E>, P10: Parser<In, O10, E>, P11: Parser<In, O11, E>,
A tuple of parsers is treated as a parser that tries its inner parsers in turn, feeding the leftover input from the first as the input to the other and so on
Calling the .try_parse()
on the tuple returns a new tuple containing the extracted values.
This is implemented for tuples up to 12 items long
fn try_parse( &self, input: In ) -> Res<In, (O0, O1, O2, O3, O4, O5, O6, O7, O8, O9, O10, O11), E>
source§impl<In, P0, O0, P1, O1, P2, O2, E> Parser<In, (O0, O1, O2), E> for (P0, P1, P2)where
P0: Parser<In, O0, E>,
P1: Parser<In, O1, E>,
P2: Parser<In, O2, E>,
impl<In, P0, O0, P1, O1, P2, O2, E> Parser<In, (O0, O1, O2), E> for (P0, P1, P2)where P0: Parser<In, O0, E>, P1: Parser<In, O1, E>, P2: Parser<In, O2, E>,
A tuple of parsers is treated as a parser that tries its inner parsers in turn, feeding the leftover input from the first as the input to the other and so on
Calling the .try_parse()
on the tuple returns a new tuple containing the extracted values.
This is implemented for tuples up to 12 items long
fn try_parse(&self, input: In) -> Res<In, (O0, O1, O2), E>
source§impl<'input, 'pat> Parser<&'input str, &'pat str, ()> for &'pat str
impl<'input, 'pat> Parser<&'input str, &'pat str, ()> for &'pat str
The Parser
trait is implemented for string slices, which means all
&str
s will have the try_parse()
method.
Calling it will try to do a prefix match of the input with the &str
used as the pattern.
use parser_compose::Parser;
let msg = "HELLO";
let (res, rest) = "HE".try_parse(msg).unwrap();
assert_eq!(res, "HE");
assert_eq!(rest, "LLO");
source§impl<In, P0, O0, P1, O1, P2, O2, P3, O3, E> Parser<In, (O0, O1, O2, O3), E> for (P0, P1, P2, P3)where
P0: Parser<In, O0, E>,
P1: Parser<In, O1, E>,
P2: Parser<In, O2, E>,
P3: Parser<In, O3, E>,
impl<In, P0, O0, P1, O1, P2, O2, P3, O3, E> Parser<In, (O0, O1, O2, O3), E> for (P0, P1, P2, P3)where P0: Parser<In, O0, E>, P1: Parser<In, O1, E>, P2: Parser<In, O2, E>, P3: Parser<In, O3, E>,
A tuple of parsers is treated as a parser that tries its inner parsers in turn, feeding the leftover input from the first as the input to the other and so on
Calling the .try_parse()
on the tuple returns a new tuple containing the extracted values.
This is implemented for tuples up to 12 items long
fn try_parse(&self, input: In) -> Res<In, (O0, O1, O2, O3), E>
source§impl<In, P0, O0, P1, O1, P2, O2, P3, O3, P4, O4, P5, O5, P6, O6, P7, O7, P8, O8, P9, O9, P10, O10, E> Parser<In, (O0, O1, O2, O3, O4, O5, O6, O7, O8, O9, O10), E> for (P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10)where
P0: Parser<In, O0, E>,
P1: Parser<In, O1, E>,
P2: Parser<In, O2, E>,
P3: Parser<In, O3, E>,
P4: Parser<In, O4, E>,
P5: Parser<In, O5, E>,
P6: Parser<In, O6, E>,
P7: Parser<In, O7, E>,
P8: Parser<In, O8, E>,
P9: Parser<In, O9, E>,
P10: Parser<In, O10, E>,
impl<In, P0, O0, P1, O1, P2, O2, P3, O3, P4, O4, P5, O5, P6, O6, P7, O7, P8, O8, P9, O9, P10, O10, E> Parser<In, (O0, O1, O2, O3, O4, O5, O6, O7, O8, O9, O10), E> for (P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10)where P0: Parser<In, O0, E>, P1: Parser<In, O1, E>, P2: Parser<In, O2, E>, P3: Parser<In, O3, E>, P4: Parser<In, O4, E>, P5: Parser<In, O5, E>, P6: Parser<In, O6, E>, P7: Parser<In, O7, E>, P8: Parser<In, O8, E>, P9: Parser<In, O9, E>, P10: Parser<In, O10, E>,
A tuple of parsers is treated as a parser that tries its inner parsers in turn, feeding the leftover input from the first as the input to the other and so on
Calling the .try_parse()
on the tuple returns a new tuple containing the extracted values.
This is implemented for tuples up to 12 items long
fn try_parse( &self, input: In ) -> Res<In, (O0, O1, O2, O3, O4, O5, O6, O7, O8, O9, O10), E>
source§impl<In, P0, O0, P1, O1, P2, O2, P3, O3, P4, O4, P5, O5, P6, O6, P7, O7, P8, O8, E> Parser<In, (O0, O1, O2, O3, O4, O5, O6, O7, O8), E> for (P0, P1, P2, P3, P4, P5, P6, P7, P8)where
P0: Parser<In, O0, E>,
P1: Parser<In, O1, E>,
P2: Parser<In, O2, E>,
P3: Parser<In, O3, E>,
P4: Parser<In, O4, E>,
P5: Parser<In, O5, E>,
P6: Parser<In, O6, E>,
P7: Parser<In, O7, E>,
P8: Parser<In, O8, E>,
impl<In, P0, O0, P1, O1, P2, O2, P3, O3, P4, O4, P5, O5, P6, O6, P7, O7, P8, O8, E> Parser<In, (O0, O1, O2, O3, O4, O5, O6, O7, O8), E> for (P0, P1, P2, P3, P4, P5, P6, P7, P8)where P0: Parser<In, O0, E>, P1: Parser<In, O1, E>, P2: Parser<In, O2, E>, P3: Parser<In, O3, E>, P4: Parser<In, O4, E>, P5: Parser<In, O5, E>, P6: Parser<In, O6, E>, P7: Parser<In, O7, E>, P8: Parser<In, O8, E>,
A tuple of parsers is treated as a parser that tries its inner parsers in turn, feeding the leftover input from the first as the input to the other and so on
Calling the .try_parse()
on the tuple returns a new tuple containing the extracted values.
This is implemented for tuples up to 12 items long
fn try_parse( &self, input: In ) -> Res<In, (O0, O1, O2, O3, O4, O5, O6, O7, O8), E>
Implementors§
impl<'input> Parser<&'input str, &'input str, ()> for AsciiStr
impl<'input> Parser<&'input [u8], &'input [u8], ()> for Byte
impl<In, Out, E, F> Parser<In, Out, E> for Fwhere F: Fn(In) -> Res<In, Out, E>,
The Parser
trait is automatically implemented for any function with
the following signature:
Fn(In) -> parser_compose::Res<In, Out, Err>
See the trait documentation for more info about the type parameters.
Let’s say you have a VecDeque<String>
that you want to parse. No methods in this crate
explicitly take a VecDeque<String>
, but that is not a problem. All the combinators are
generic over input, output and errors. So you only need to implement one parser:
use parser_compose::{Parser, Error, Res} ;
use std::collections::vec_deque::VecDeque;
// A parser that matches any string at the start of the input.
fn any_string(mut input: VecDeque<String>) -> Res<VecDeque<String>, String, ()> {
let first = input.pop_front().ok_or(Error::Mismatch)?;
Ok((first, input))
}
let msg = VecDeque::from([
String::from("Hello"),
String::from("Hello"),
String::from("World"),
]);
// The function can be used with combinators
let parse_hellos = any_string.when(|s| s == "Hello").repeated(2);
let parse_world = any_string.when(|s| s == "World");
let ((hellos, world), rest) = (parse_hellos, parse_world).try_parse(msg).unwrap();
assert_eq!(hellos, vec!["Hello", "Hello"]);
assert_eq!(world, "World");
assert_eq!(rest, VecDeque::<String>::new());