pub trait Parser<I: Clone, O> {
type Error: Error<I>;
Show 35 methods
fn parse_recovery<'a, Iter, S>(
&self,
stream: S
) -> (Option<O>, Vec<Self::Error>)
where
Self: Sized,
Iter: Iterator<Item = (I, <Self::Error as Error<I>>::Span)> + 'a,
S: Into<Stream<'a, I, <Self::Error as Error<I>>::Span, Iter>>,
{ ... }
fn parse_recovery_verbose<'a, Iter, S>(
&self,
stream: S
) -> (Option<O>, Vec<Self::Error>)
where
Self: Sized,
Iter: Iterator<Item = (I, <Self::Error as Error<I>>::Span)> + 'a,
S: Into<Stream<'a, I, <Self::Error as Error<I>>::Span, Iter>>,
{ ... }
fn parse<'a, Iter, S>(&self, stream: S) -> Result<O, Vec<Self::Error>>
where
Self: Sized,
Iter: Iterator<Item = (I, <Self::Error as Error<I>>::Span)> + 'a,
S: Into<Stream<'a, I, <Self::Error as Error<I>>::Span, Iter>>,
{ ... }
fn debug<T>(self, x: T) -> Debug<Self>
where
Self: Sized,
T: Display + 'static,
{ ... }
fn map<U, F>(self, f: F) -> Map<Self, F, O>
where
Self: Sized,
F: Fn(O) -> U,
{ ... }
fn map_with_span<U, F>(self, f: F) -> MapWithSpan<Self, F, O>
where
Self: Sized,
F: Fn(O, <Self::Error as Error<I>>::Span) -> U,
{ ... }
fn map_err<F>(self, f: F) -> MapErr<Self, F>
where
Self: Sized,
F: Fn(Self::Error) -> Self::Error,
{ ... }
fn or_else<F>(self, f: F) -> OrElse<Self, F>
where
Self: Sized,
F: Fn(Self::Error) -> Result<O, Self::Error>,
{ ... }
fn map_err_with_span<F>(self, f: F) -> MapErrWithSpan<Self, F>
where
Self: Sized,
F: Fn(Self::Error, <Self::Error as Error<I>>::Span) -> Self::Error,
{ ... }
fn try_map<U, F>(self, f: F) -> TryMap<Self, F, O>
where
Self: Sized,
F: Fn(O, <Self::Error as Error<I>>::Span) -> Result<U, Self::Error>,
{ ... }
fn validate<F, U>(self, f: F) -> Validate<Self, O, F>
where
Self: Sized,
F: Fn(O, <Self::Error as Error<I>>::Span, &mut dyn FnMut(Self::Error)) -> U,
{ ... }
fn labelled<L>(self, label: L) -> Label<Self, L>
where
Self: Sized,
L: Into<<Self::Error as Error<I>>::Label> + Clone,
{ ... }
fn to<U>(self, x: U) -> To<Self, O, U>
where
Self: Sized,
U: Clone,
{ ... }
fn foldl<A, B, F>(self, f: F) -> Foldl<Self, F, A, B>
where
Self: Parser<I, (A, B)> + Sized,
B: IntoIterator,
F: Fn(A, B::Item) -> A,
{ ... }
fn foldr<'a, A, B, F>(self, f: F) -> Foldr<Self, F, A, B>
where
Self: Parser<I, (A, B)> + Sized,
A: IntoIterator,
A::IntoIter: DoubleEndedIterator,
F: Fn(A::Item, B) -> B + 'a,
{ ... }
fn ignored(self) -> Ignored<Self, O>
where
Self: Sized,
{ ... }
fn collect<C>(self) -> Map<Self, fn(_: O) -> C, O>
where
Self: Sized,
O: IntoIterator,
C: FromIterator<O::Item>,
{ ... }
fn then<U, P>(self, other: P) -> Then<Self, P>
where
Self: Sized,
P: Parser<I, U, Error = Self::Error>,
{ ... }
fn then_with<U, P, F: Fn(O) -> P>(
self,
other: F
) -> ThenWith<I, O, U, Self, P, F>
where
Self: Sized,
P: Parser<I, U, Error = Self::Error>,
{ ... }
fn chain<T, U, P>(
self,
other: P
) -> Map<Then<Self, P>, fn(_: (O, U)) -> Vec<T>, (O, U)>
where
Self: Sized,
U: Chain<T>,
O: Chain<T>,
P: Parser<I, U, Error = Self::Error>,
{ ... }
fn flatten<T, Inner>(self) -> Map<Self, fn(_: O) -> Vec<T>, O>
where
Self: Sized,
O: IntoIterator<Item = Inner>,
Inner: IntoIterator<Item = T>,
{ ... }
fn ignore_then<U, P>(self, other: P) -> IgnoreThen<Self, P, O, U>
where
Self: Sized,
P: Parser<I, U, Error = Self::Error>,
{ ... }
fn then_ignore<U, P>(self, other: P) -> ThenIgnore<Self, P, O, U>
where
Self: Sized,
P: Parser<I, U, Error = Self::Error>,
{ ... }
fn padded_by<U, P>(
self,
other: P
) -> ThenIgnore<IgnoreThen<P, Self, U, O>, P, O, U>
where
Self: Sized,
P: Parser<I, U, Error = Self::Error> + Clone,
{ ... }
fn delimited_by<U, V, L, R>(
self,
start: L,
end: R
) -> DelimitedBy<Self, L, R, U, V>
where
Self: Sized,
L: Parser<I, U, Error = Self::Error>,
R: Parser<I, V, Error = Self::Error>,
{ ... }
fn or<P>(self, other: P) -> Or<Self, P>
where
Self: Sized,
P: Parser<I, O, Error = Self::Error>,
{ ... }
fn recover_with<S>(self, strategy: S) -> Recovery<Self, S>
where
Self: Sized,
S: Strategy<I, O, Self::Error>,
{ ... }
fn or_not(self) -> OrNot<Self>
where
Self: Sized,
{ ... }
fn not(self) -> Not<Self, O>
where
Self: Sized,
{ ... }
fn repeated(self) -> Repeated<Self>
where
Self: Sized,
{ ... }
fn separated_by<U, P>(self, other: P) -> SeparatedBy<Self, P, U>
where
Self: Sized,
P: Parser<I, U, Error = Self::Error>,
{ ... }
fn rewind(self) -> Rewind<Self>
where
Self: Sized,
{ ... }
fn boxed<'a>(self) -> BoxedParser<'a, I, O, Self::Error>
where
Self: Sized + 'a,
{ ... }
fn from_str<U>(self) -> Map<Self, fn(_: O) -> Result<U, U::Err>, O>
where
Self: Sized,
U: FromStr,
O: AsRef<str>,
{ ... }
fn unwrapped<U, E>(
self
) -> Unwrapped<Self, E, <Self as Parser<I, O>>::Error>
where
Self: Sized + Parser<I, Result<U, E>>,
E: Debug,
{ ... }
}
Expand description
A trait implemented by parsers.
Parsers take a stream of tokens of type I
and attempt to parse them into a value of type O
. In doing so, they
may encounter errors. These need not be fatal to the parsing process: syntactic errors can be recovered from and a
valid output may still be generated alongside any syntax errors that were encountered along the way. Usually, this
output comes in the form of an Abstract Syntax Tree (AST).
You should not need to implement this trait by hand. If you cannot combine existing combintors (and in particular
custom
) to create the combinator you’re looking for, please
open an issue! If you really need to implement this trait,
please check the documentation in the source: some implementation details have been deliberately hidden.
Required Associated Types§
Provided Methods§
sourcefn parse_recovery<'a, Iter, S>(&self, stream: S) -> (Option<O>, Vec<Self::Error>)where
Self: Sized,
Iter: Iterator<Item = (I, <Self::Error as Error<I>>::Span)> + 'a,
S: Into<Stream<'a, I, <Self::Error as Error<I>>::Span, Iter>>,
fn parse_recovery<'a, Iter, S>(&self, stream: S) -> (Option<O>, Vec<Self::Error>)where
Self: Sized,
Iter: Iterator<Item = (I, <Self::Error as Error<I>>::Span)> + 'a,
S: Into<Stream<'a, I, <Self::Error as Error<I>>::Span, Iter>>,
Parse a stream of tokens, yielding an output if possible, and any errors encountered along the way.
If None
is returned (i.e: parsing failed) then there will always be at least one item in the error Vec
.
If you don’t care about producing an output if errors are encountered, use Parser::parse
instead.
Although the signature of this function looks complicated, it’s simpler than you think! You can pass a
&[I]
, a &str
, or a Stream
to it.
sourcefn parse_recovery_verbose<'a, Iter, S>(
&self,
stream: S
) -> (Option<O>, Vec<Self::Error>)where
Self: Sized,
Iter: Iterator<Item = (I, <Self::Error as Error<I>>::Span)> + 'a,
S: Into<Stream<'a, I, <Self::Error as Error<I>>::Span, Iter>>,
fn parse_recovery_verbose<'a, Iter, S>(
&self,
stream: S
) -> (Option<O>, Vec<Self::Error>)where
Self: Sized,
Iter: Iterator<Item = (I, <Self::Error as Error<I>>::Span)> + 'a,
S: Into<Stream<'a, I, <Self::Error as Error<I>>::Span, Iter>>,
Parse a stream of tokens, yielding an output if possible, and any errors encountered along the way. Unlike
Parser::parse_recovery
, this function will produce verbose debugging output as it executes.
If None
is returned (i.e: parsing failed) then there will always be at least one item in the error Vec
.
If you don’t care about producing an output if errors are encountered, use Parser::parse
instead.
Although the signature of this function looks complicated, it’s simpler than you think! You can pass a
&[I]
, a &str
, or a Stream
to it.
You’ll probably want to make sure that this doesn’t end up in production code: it exists only to help you debug your parser. Additionally, its API is quite likely to change in future versions.
This method will receive more extensive documentation as the crate’s debugging features mature.
sourcefn parse<'a, Iter, S>(&self, stream: S) -> Result<O, Vec<Self::Error>>where
Self: Sized,
Iter: Iterator<Item = (I, <Self::Error as Error<I>>::Span)> + 'a,
S: Into<Stream<'a, I, <Self::Error as Error<I>>::Span, Iter>>,
fn parse<'a, Iter, S>(&self, stream: S) -> Result<O, Vec<Self::Error>>where
Self: Sized,
Iter: Iterator<Item = (I, <Self::Error as Error<I>>::Span)> + 'a,
S: Into<Stream<'a, I, <Self::Error as Error<I>>::Span, Iter>>,
Parse a stream of tokens, yielding an output or any errors that were encountered along the way.
If you wish to attempt to produce an output even if errors are encountered, use Parser::parse_recovery
.
Although the signature of this function looks complicated, it’s simpler than you think! You can pass a
[&[I]
], a &str
, or a Stream
to it.
sourcefn debug<T>(self, x: T) -> Debug<Self>where
Self: Sized,
T: Display + 'static,
fn debug<T>(self, x: T) -> Debug<Self>where
Self: Sized,
T: Display + 'static,
Include this parser in the debugging output produced by Parser::parse_recovery_verbose
.
You’ll probably want to make sure that this doesn’t end up in production code: it exists only to help you debug your parser. Additionally, its API is quite likely to change in future versions. Use this parser like a print statement, to display whatever you pass as the argument ‘x’
This method will receive more extensive documentation as the crate’s debugging features mature.
sourcefn map<U, F>(self, f: F) -> Map<Self, F, O>where
Self: Sized,
F: Fn(O) -> U,
fn map<U, F>(self, f: F) -> Map<Self, F, O>where
Self: Sized,
F: Fn(O) -> U,
Map the output of this parser to another value.
The output type of this parser is U
, the same as the function’s output.
Examples
#[derive(Debug, PartialEq)]
enum Token { Word(String), Num(u64) }
let word = filter::<_, _, Cheap<char>>(|c: &char| c.is_alphabetic())
.repeated().at_least(1)
.collect::<String>()
.map(Token::Word);
let num = filter::<_, _, Cheap<char>>(|c: &char| c.is_ascii_digit())
.repeated().at_least(1)
.collect::<String>()
.map(|s| Token::Num(s.parse().unwrap()));
let token = word.or(num);
assert_eq!(token.parse("test"), Ok(Token::Word("test".to_string())));
assert_eq!(token.parse("42"), Ok(Token::Num(42)));
sourcefn map_with_span<U, F>(self, f: F) -> MapWithSpan<Self, F, O>where
Self: Sized,
F: Fn(O, <Self::Error as Error<I>>::Span) -> U,
fn map_with_span<U, F>(self, f: F) -> MapWithSpan<Self, F, O>where
Self: Sized,
F: Fn(O, <Self::Error as Error<I>>::Span) -> U,
Map the output of this parser to another value, making use of the pattern’s span when doing so.
This is very useful when generating an AST that attaches a span to each AST node.
The output type of this parser is U
, the same as the function’s output.
Examples
use std::ops::Range;
// It's common for AST nodes to use a wrapper type that allows attaching span information to them
#[derive(Debug, PartialEq)]
pub struct Spanned<T>(T, Range<usize>);
let ident = text::ident::<_, Simple<char>>()
.map_with_span(|ident, span| Spanned(ident, span))
.padded();
assert_eq!(ident.parse("hello"), Ok(Spanned("hello".to_string(), 0..5)));
assert_eq!(ident.parse(" hello "), Ok(Spanned("hello".to_string(), 7..12)));
sourcefn map_err<F>(self, f: F) -> MapErr<Self, F>where
Self: Sized,
F: Fn(Self::Error) -> Self::Error,
fn map_err<F>(self, f: F) -> MapErr<Self, F>where
Self: Sized,
F: Fn(Self::Error) -> Self::Error,
Map the primary error of this parser to another value.
This function is most useful when using a custom error type, allowing you to augment errors according to context.
The output type of this parser is O
, the same as the original parser.
sourcefn or_else<F>(self, f: F) -> OrElse<Self, F>where
Self: Sized,
F: Fn(Self::Error) -> Result<O, Self::Error>,
fn or_else<F>(self, f: F) -> OrElse<Self, F>where
Self: Sized,
F: Fn(Self::Error) -> Result<O, Self::Error>,
Map the primary error of this parser to a result. If the result is Ok
, the parser succeeds with that value.
Note that even if the function returns an Ok
, the input stream will still be ‘stuck’ at the input following
the input that triggered the error. You’ll need to follow uses of this combinator with a parser that resets
the input stream to a known-good state (for example, take_until
).
The output type of this parser is U
, the Ok
type of the result.
sourcefn map_err_with_span<F>(self, f: F) -> MapErrWithSpan<Self, F>where
Self: Sized,
F: Fn(Self::Error, <Self::Error as Error<I>>::Span) -> Self::Error,
fn map_err_with_span<F>(self, f: F) -> MapErrWithSpan<Self, F>where
Self: Sized,
F: Fn(Self::Error, <Self::Error as Error<I>>::Span) -> Self::Error,
Map the primary error of this parser to another value, making use of the span from the start of the attempted to the point at which the error was encountered.
This function is useful for augmenting errors to allow them to display the span of the initial part of a pattern, for example to add a “while parsing” clause to your error messages.
The output type of this parser is O
, the same as the original parser.
sourcefn try_map<U, F>(self, f: F) -> TryMap<Self, F, O>where
Self: Sized,
F: Fn(O, <Self::Error as Error<I>>::Span) -> Result<U, Self::Error>,
fn try_map<U, F>(self, f: F) -> TryMap<Self, F, O>where
Self: Sized,
F: Fn(O, <Self::Error as Error<I>>::Span) -> Result<U, Self::Error>,
After a successful parse, apply a fallible function to the output. If the function produces an error, treat it as a parsing error.
If you wish parsing of this pattern to continue when an error is generated instead of halting, consider using
Parser::validate
instead.
The output type of this parser is U
, the Ok
return value of the function.
Examples
let byte = text::int::<_, Simple<char>>(10)
.try_map(|s, span| s
.parse::<u8>()
.map_err(|e| Simple::custom(span, format!("{}", e))));
assert!(byte.parse("255").is_ok());
assert!(byte.parse("256").is_err()); // Out of range
sourcefn validate<F, U>(self, f: F) -> Validate<Self, O, F>where
Self: Sized,
F: Fn(O, <Self::Error as Error<I>>::Span, &mut dyn FnMut(Self::Error)) -> U,
fn validate<F, U>(self, f: F) -> Validate<Self, O, F>where
Self: Sized,
F: Fn(O, <Self::Error as Error<I>>::Span, &mut dyn FnMut(Self::Error)) -> U,
Validate an output, producing non-terminal errors if it does not fulfil certain criteria.
This function also permits mapping the output to a value of another type, similar to Parser::map
.
If you wish parsing of this pattern to halt when an error is generated instead of continuing, consider using
Parser::try_map
instead.
The output type of this parser is O
, the same as the original parser.
Examples
let large_int = text::int::<char, _>(10)
.from_str()
.unwrapped()
.validate(|x: u32, span, emit| {
if x < 256 { emit(Simple::custom(span, format!("{} must be 256 or higher.", x))) }
x
});
assert_eq!(large_int.parse("537"), Ok(537));
assert!(large_int.parse("243").is_err());
sourcefn labelled<L>(self, label: L) -> Label<Self, L>where
Self: Sized,
L: Into<<Self::Error as Error<I>>::Label> + Clone,
fn labelled<L>(self, label: L) -> Label<Self, L>where
Self: Sized,
L: Into<<Self::Error as Error<I>>::Label> + Clone,
Label the pattern parsed by this parser for more useful error messages.
This is useful when you want to give users a more useful description of an expected pattern than simply a list of possible initial tokens. For example, it’s common to use the term “expression” at a catch-all for a number of different constructs in many languages.
This does not label recovered errors generated by sub-patterns within the parser, only error directly emitted by the parser.
This does not label errors where the labelled pattern consumed input (i.e: in unambiguous cases).
The output type of this parser is O
, the same as the original parser.
Note: There is a chance that this method will be deprecated in favour of a more general solution in later versions of the crate.
Examples
let frac = text::digits(10)
.chain(just('.'))
.chain::<char, _, _>(text::digits(10))
.collect::<String>()
.then_ignore(end())
.labelled("number");
assert_eq!(frac.parse("42.3"), Ok("42.3".to_string()));
assert_eq!(frac.parse("hello"), Err(vec![Cheap::expected_input_found(0..1, Vec::new(), Some('h')).with_label("number")]));
assert_eq!(frac.parse("42!"), Err(vec![Cheap::expected_input_found(2..3, vec![Some('.')], Some('!')).with_label("number")]));
sourcefn to<U>(self, x: U) -> To<Self, O, U>where
Self: Sized,
U: Clone,
fn to<U>(self, x: U) -> To<Self, O, U>where
Self: Sized,
U: Clone,
Transform all outputs of this parser to a pretermined value.
The output type of this parser is U
, the type of the predetermined value.
Examples
#[derive(Clone, Debug, PartialEq)]
enum Op { Add, Sub, Mul, Div }
let op = just::<_, _, Cheap<char>>('+').to(Op::Add)
.or(just('-').to(Op::Sub))
.or(just('*').to(Op::Mul))
.or(just('/').to(Op::Div));
assert_eq!(op.parse("+"), Ok(Op::Add));
assert_eq!(op.parse("/"), Ok(Op::Div));
sourcefn foldl<A, B, F>(self, f: F) -> Foldl<Self, F, A, B>where
Self: Parser<I, (A, B)> + Sized,
B: IntoIterator,
F: Fn(A, B::Item) -> A,
fn foldl<A, B, F>(self, f: F) -> Foldl<Self, F, A, B>where
Self: Parser<I, (A, B)> + Sized,
B: IntoIterator,
F: Fn(A, B::Item) -> A,
Left-fold the output of the parser into a single value.
The output of the original parser must be of type (A, impl IntoIterator<Item = B>)
.
The output type of this parser is A
, the left-hand component of the original parser’s output.
Examples
let int = text::int::<char, Cheap<char>>(10)
.from_str()
.unwrapped();
let sum = int
.then(just('+').ignore_then(int).repeated())
.foldl(|a, b| a + b);
assert_eq!(sum.parse("1+12+3+9"), Ok(25));
assert_eq!(sum.parse("6"), Ok(6));
sourcefn foldr<'a, A, B, F>(self, f: F) -> Foldr<Self, F, A, B>where
Self: Parser<I, (A, B)> + Sized,
A: IntoIterator,
A::IntoIter: DoubleEndedIterator,
F: Fn(A::Item, B) -> B + 'a,
fn foldr<'a, A, B, F>(self, f: F) -> Foldr<Self, F, A, B>where
Self: Parser<I, (A, B)> + Sized,
A: IntoIterator,
A::IntoIter: DoubleEndedIterator,
F: Fn(A::Item, B) -> B + 'a,
Right-fold the output of the parser into a single value.
The output of the original parser must be of type (impl IntoIterator<Item = A>, B)
. Because right-folds work
backwards, the iterator must implement DoubleEndedIterator
so that it can be reversed.
The output type of this parser is B
, the right-hand component of the original parser’s output.
Examples
let int = text::int::<char, Cheap<char>>(10)
.from_str()
.unwrapped();
let signed = just('+').to(1)
.or(just('-').to(-1))
.repeated()
.then(int)
.foldr(|a, b| a * b);
assert_eq!(signed.parse("3"), Ok(3));
assert_eq!(signed.parse("-17"), Ok(-17));
assert_eq!(signed.parse("--+-+-5"), Ok(5));
sourcefn ignored(self) -> Ignored<Self, O>where
Self: Sized,
fn ignored(self) -> Ignored<Self, O>where
Self: Sized,
Ignore the output of this parser, yielding ()
as an output instead.
This can be used to reduce the cost of parsing by avoiding unnecessary allocations (most collections containing
ZSTs
do not allocate). For example, it’s common to
want to ignore whitespace in many grammars (see text::whitespace
).
The output type of this parser is ()
.
Examples
// A parser that parses any number of whitespace characters without allocating
let whitespace = filter::<_, _, Cheap<char>>(|c: &char| c.is_whitespace())
.ignored()
.repeated();
assert_eq!(whitespace.parse(" "), Ok(vec![(); 4]));
assert_eq!(whitespace.parse(" hello"), Ok(vec![(); 2]));
sourcefn collect<C>(self) -> Map<Self, fn(_: O) -> C, O>where
Self: Sized,
O: IntoIterator,
C: FromIterator<O::Item>,
fn collect<C>(self) -> Map<Self, fn(_: O) -> C, O>where
Self: Sized,
O: IntoIterator,
C: FromIterator<O::Item>,
Collect the output of this parser into a type implementing FromIterator
.
This is commonly useful for collecting Vec<char>
outputs into String
s, or [(T, U)
] into a
HashMap
and is analogous to Iterator::collect
.
The output type of this parser is C
, the type being collected into.
Examples
let word = filter::<_, _, Cheap<char>>(|c: &char| c.is_alphabetic()) // This parser produces an output of `char`
.repeated() // This parser produces an output of `Vec<char>`
.collect::<String>(); // But `Vec<char>` is less useful than `String`, so convert to the latter
assert_eq!(word.parse("hello"), Ok("hello".to_string()));
sourcefn then<U, P>(self, other: P) -> Then<Self, P>where
Self: Sized,
P: Parser<I, U, Error = Self::Error>,
fn then<U, P>(self, other: P) -> Then<Self, P>where
Self: Sized,
P: Parser<I, U, Error = Self::Error>,
Parse one thing and then another thing, yielding a tuple of the two outputs.
The output type of this parser is (O, U)
, a combination of the outputs of both parsers.
Examples
let word = filter::<_, _, Cheap<char>>(|c: &char| c.is_alphabetic())
.repeated().at_least(1)
.collect::<String>();
let two_words = word.then_ignore(just(' ')).then(word);
assert_eq!(two_words.parse("dog cat"), Ok(("dog".to_string(), "cat".to_string())));
assert!(two_words.parse("hedgehog").is_err());
sourcefn then_with<U, P, F: Fn(O) -> P>(
self,
other: F
) -> ThenWith<I, O, U, Self, P, F>where
Self: Sized,
P: Parser<I, U, Error = Self::Error>,
fn then_with<U, P, F: Fn(O) -> P>(
self,
other: F
) -> ThenWith<I, O, U, Self, P, F>where
Self: Sized,
P: Parser<I, U, Error = Self::Error>,
Parse one thing and then another thing, creating the second parser from the result of
the first. If you only have a couple cases to handle, prefer Parser::or
.
The output of this parser is U
, the result of the second parser
Error recovery for this parser may be sub-optimal, as if the first parser succeeds on recovery then the second produces an error, the primary error will point to the location in the second parser which failed, ignoring that the first parser may be the root cause. There may be other pathological errors cases as well.
Examples
// A parser that parses a single letter and then its successor
let successive_letters = one_of::<_, _, Cheap<u8>>((b'a'..=b'z').collect::<Vec<u8>>())
.then_with(|letter: u8| just(letter + 1));
assert_eq!(successive_letters.parse(*b"ab"), Ok(b'b')); // 'b' follows 'a'
assert!(successive_letters.parse(*b"ac").is_err()); // 'c' does not follow 'a'
sourcefn chain<T, U, P>(
self,
other: P
) -> Map<Then<Self, P>, fn(_: (O, U)) -> Vec<T>, (O, U)>where
Self: Sized,
U: Chain<T>,
O: Chain<T>,
P: Parser<I, U, Error = Self::Error>,
fn chain<T, U, P>(
self,
other: P
) -> Map<Then<Self, P>, fn(_: (O, U)) -> Vec<T>, (O, U)>where
Self: Sized,
U: Chain<T>,
O: Chain<T>,
P: Parser<I, U, Error = Self::Error>,
Parse one thing and then another thing, attempting to chain the two outputs into a Vec
.
The output type of this parser is Vec<T>
, composed of the elements of the outputs of both parsers.
Examples
let int = just('-').or_not()
.chain(filter::<_, _, Cheap<char>>(|c: &char| c.is_ascii_digit() && *c != '0')
.chain(filter::<_, _, Cheap<char>>(|c: &char| c.is_ascii_digit()).repeated()))
.or(just('0').map(|c| vec![c]))
.then_ignore(end())
.collect::<String>()
.from_str()
.unwrapped();
assert_eq!(int.parse("0"), Ok(0));
assert_eq!(int.parse("415"), Ok(415));
assert_eq!(int.parse("-50"), Ok(-50));
assert!(int.parse("-0").is_err());
assert!(int.parse("05").is_err());
sourcefn flatten<T, Inner>(self) -> Map<Self, fn(_: O) -> Vec<T>, O>where
Self: Sized,
O: IntoIterator<Item = Inner>,
Inner: IntoIterator<Item = T>,
fn flatten<T, Inner>(self) -> Map<Self, fn(_: O) -> Vec<T>, O>where
Self: Sized,
O: IntoIterator<Item = Inner>,
Inner: IntoIterator<Item = T>,
Flatten a nested collection.
This use-cases of this method are broadly similar to those of Iterator::flatten
.
The output type of this parser is Vec<T>
, where the original parser output was
impl IntoIterator<Item = impl IntoIterator<Item = T>>
.
sourcefn ignore_then<U, P>(self, other: P) -> IgnoreThen<Self, P, O, U>where
Self: Sized,
P: Parser<I, U, Error = Self::Error>,
fn ignore_then<U, P>(self, other: P) -> IgnoreThen<Self, P, O, U>where
Self: Sized,
P: Parser<I, U, Error = Self::Error>,
Parse one thing and then another thing, yielding only the output of the latter.
The output type of this parser is U
, the same as the second parser.
Examples
let zeroes = filter::<_, _, Cheap<char>>(|c: &char| *c == '0').ignored().repeated();
let digits = filter(|c: &char| c.is_ascii_digit()).repeated();
let integer = zeroes
.ignore_then(digits)
.collect::<String>()
.from_str()
.unwrapped();
assert_eq!(integer.parse("00064"), Ok(64));
assert_eq!(integer.parse("32"), Ok(32));
sourcefn then_ignore<U, P>(self, other: P) -> ThenIgnore<Self, P, O, U>where
Self: Sized,
P: Parser<I, U, Error = Self::Error>,
fn then_ignore<U, P>(self, other: P) -> ThenIgnore<Self, P, O, U>where
Self: Sized,
P: Parser<I, U, Error = Self::Error>,
Parse one thing and then another thing, yielding only the output of the former.
The output type of this parser is O
, the same as the original parser.
Examples
let word = filter::<_, _, Cheap<char>>(|c: &char| c.is_alphabetic())
.repeated().at_least(1)
.collect::<String>();
let punctuated = word
.then_ignore(just('!').or(just('?')).or_not());
let sentence = punctuated
.padded() // Allow for whitespace gaps
.repeated();
assert_eq!(
sentence.parse("hello! how are you?"),
Ok(vec![
"hello".to_string(),
"how".to_string(),
"are".to_string(),
"you".to_string(),
]),
);
sourcefn padded_by<U, P>(
self,
other: P
) -> ThenIgnore<IgnoreThen<P, Self, U, O>, P, O, U>where
Self: Sized,
P: Parser<I, U, Error = Self::Error> + Clone,
fn padded_by<U, P>(
self,
other: P
) -> ThenIgnore<IgnoreThen<P, Self, U, O>, P, O, U>where
Self: Sized,
P: Parser<I, U, Error = Self::Error> + Clone,
Parse a pattern, but with an instance of another pattern on either end, yielding the output of the inner.
The output type of this parser is O
, the same as the original parser.
Examples
let ident = text::ident::<_, Simple<char>>()
.padded_by(just('!'));
assert_eq!(ident.parse("!hello!"), Ok("hello".to_string()));
assert!(ident.parse("hello!").is_err());
assert!(ident.parse("!hello").is_err());
assert!(ident.parse("hello").is_err());
sourcefn delimited_by<U, V, L, R>(
self,
start: L,
end: R
) -> DelimitedBy<Self, L, R, U, V>where
Self: Sized,
L: Parser<I, U, Error = Self::Error>,
R: Parser<I, V, Error = Self::Error>,
fn delimited_by<U, V, L, R>(
self,
start: L,
end: R
) -> DelimitedBy<Self, L, R, U, V>where
Self: Sized,
L: Parser<I, U, Error = Self::Error>,
R: Parser<I, V, Error = Self::Error>,
Parse the pattern surrounded by the given delimiters.
The output type of this parser is O
, the same as the original parser.
Examples
// A LISP-style S-expression
#[derive(Debug, PartialEq)]
enum SExpr {
Ident(String),
Num(u64),
List(Vec<SExpr>),
}
let ident = filter::<_, _, Cheap<char>>(|c: &char| c.is_alphabetic())
.repeated().at_least(1)
.collect::<String>();
let num = text::int(10)
.from_str()
.unwrapped();
let s_expr = recursive(|s_expr| s_expr
.padded()
.repeated()
.map(SExpr::List)
.delimited_by(just('('), just(')'))
.or(ident.map(SExpr::Ident))
.or(num.map(SExpr::Num)));
// A valid input
assert_eq!(
s_expr.parse_recovery("(add (mul 42 3) 15)"),
(
Some(SExpr::List(vec![
SExpr::Ident("add".to_string()),
SExpr::List(vec![
SExpr::Ident("mul".to_string()),
SExpr::Num(42),
SExpr::Num(3),
]),
SExpr::Num(15),
])),
Vec::new(), // No errors!
),
);
sourcefn or<P>(self, other: P) -> Or<Self, P>where
Self: Sized,
P: Parser<I, O, Error = Self::Error>,
fn or<P>(self, other: P) -> Or<Self, P>where
Self: Sized,
P: Parser<I, O, Error = Self::Error>,
Parse one thing or, on failure, another thing.
The output of both parsers must be of the same type, because either output can be produced.
If both parser succeed, the output of the first parser is guaranteed to be prioritised over the output of the second.
If both parsers produce errors, the combinator will attempt to select from or combine the errors to produce an error that is most likely to be useful to a human attempting to understand the problem. The exact algorithm used is left unspecified, and is not part of the crate’s semver guarantees, although regressions in error quality should be reported in the issue tracker of the main repository.
Please note that long chains of Parser::or
combinators have been known to result in poor compilation times.
If you feel you are experiencing this, consider using choice
instead.
The output type of this parser is O
, the output of both parsers.
Examples
let op = just::<_, _, Cheap<char>>('+')
.or(just('-'))
.or(just('*'))
.or(just('/'));
assert_eq!(op.parse("+"), Ok('+'));
assert_eq!(op.parse("/"), Ok('/'));
assert!(op.parse("!").is_err());
sourcefn recover_with<S>(self, strategy: S) -> Recovery<Self, S>where
Self: Sized,
S: Strategy<I, O, Self::Error>,
fn recover_with<S>(self, strategy: S) -> Recovery<Self, S>where
Self: Sized,
S: Strategy<I, O, Self::Error>,
Apply a fallback recovery strategy to this parser should it fail.
There is no silver bullet for error recovery, so this function allows you to specify one of several different strategies at the location of your choice. Prefer an error recovery strategy that more precisely mirrors valid syntax where possible to make error recovery more reliable.
Because chumsky is a PEG parser, which always take the first successful parsing route through a grammar, recovering from an error may cause the parser to erroneously miss alternative valid routes through the grammar that do not generate recoverable errors. If you run into cases where valid syntax fails to parse without errors, this might be happening: consider removing error recovery or switching to a more specific error recovery strategy.
The output type of this parser is O
, the same as the original parser.
Examples
#[derive(Debug, PartialEq)]
enum Expr {
Error,
Int(String),
List(Vec<Expr>),
}
let expr = recursive::<_, _, _, _, Simple<char>>(|expr| expr
.separated_by(just(','))
.delimited_by(just('['), just(']'))
.map(Expr::List)
// If parsing a list expression fails, recover at the next delimiter, generating an error AST node
.recover_with(nested_delimiters('[', ']', [], |_| Expr::Error))
.or(text::int(10).map(Expr::Int))
.padded());
assert!(expr.parse("five").is_err()); // Text is not a valid expression in this language...
assert!(expr.parse("[1, 2, 3]").is_ok()); // ...but lists and numbers are!
// This input has two syntax errors...
let (ast, errors) = expr.parse_recovery("[[1, two], [3, four]]");
// ...and error recovery allows us to catch both of them!
assert_eq!(errors.len(), 2);
// Additionally, the AST we get back still has useful information.
assert_eq!(ast, Some(Expr::List(vec![Expr::Error, Expr::Error])));
sourcefn or_not(self) -> OrNot<Self>where
Self: Sized,
fn or_not(self) -> OrNot<Self>where
Self: Sized,
Attempt to parse something, but only if it exists.
If parsing of the pattern is successful, the output is Some(_)
. Otherwise, the output is None
.
The output type of this parser is Option<O>
.
Examples
let word = filter::<_, _, Cheap<char>>(|c: &char| c.is_alphabetic())
.repeated().at_least(1)
.collect::<String>();
let word_or_question = word
.then(just('?').or_not());
assert_eq!(word_or_question.parse("hello?"), Ok(("hello".to_string(), Some('?'))));
assert_eq!(word_or_question.parse("wednesday"), Ok(("wednesday".to_string(), None)));
sourcefn not(self) -> Not<Self, O>where
Self: Sized,
fn not(self) -> Not<Self, O>where
Self: Sized,
Parses a single token if, and only if, the pattern fails to parse.
The output type of this parser is I
.
Examples
#[derive(Debug, PartialEq)]
enum Tree {
Text(String),
Group(Vec<Self>),
}
// Arbitrary text, nested in a tree with { ... } delimiters
let tree = recursive::<_, _, _, _, Cheap<char>>(|tree| {
let text = one_of("{}")
.not()
.repeated()
.at_least(1)
.collect()
.map(Tree::Text);
let group = tree
.repeated()
.delimited_by(just('{'), just('}'))
.map(Tree::Group);
text.or(group)
});
assert_eq!(
tree.parse("{abcd{efg{hijk}lmn{opq}rs}tuvwxyz}"),
Ok(Tree::Group(vec![
Tree::Text("abcd".to_string()),
Tree::Group(vec![
Tree::Text("efg".to_string()),
Tree::Group(vec![
Tree::Text("hijk".to_string()),
]),
Tree::Text("lmn".to_string()),
Tree::Group(vec![
Tree::Text("opq".to_string()),
]),
Tree::Text("rs".to_string()),
]),
Tree::Text("tuvwxyz".to_string()),
])),
);
sourcefn repeated(self) -> Repeated<Self>where
Self: Sized,
fn repeated(self) -> Repeated<Self>where
Self: Sized,
Parse a pattern any number of times (including zero times).
Input is eagerly parsed. Be aware that the parser will accept no occurrences of the pattern too. Consider using
Repeated::at_least
instead if it better suits your use-case.
The output type of this parser is Vec<O>
.
Examples
let num = filter::<_, _, Cheap<char>>(|c: &char| c.is_ascii_digit())
.repeated().at_least(1)
.collect::<String>()
.from_str()
.unwrapped();
let sum = num.then(just('+').ignore_then(num).repeated())
.foldl(|a, b| a + b);
assert_eq!(sum.parse("2+13+4+0+5"), Ok(24));
sourcefn separated_by<U, P>(self, other: P) -> SeparatedBy<Self, P, U>where
Self: Sized,
P: Parser<I, U, Error = Self::Error>,
fn separated_by<U, P>(self, other: P) -> SeparatedBy<Self, P, U>where
Self: Sized,
P: Parser<I, U, Error = Self::Error>,
Parse a pattern, separated by another, any number of times.
You can use SeparatedBy::allow_leading
or SeparatedBy::allow_trailing
to allow leading or trailing
separators.
The output type of this parser is Vec<O>
.
Examples
let shopping = text::ident::<_, Simple<char>>()
.padded()
.separated_by(just(','));
assert_eq!(shopping.parse("eggs"), Ok(vec!["eggs".to_string()]));
assert_eq!(shopping.parse("eggs, flour, milk"), Ok(vec!["eggs".to_string(), "flour".to_string(), "milk".to_string()]));
See SeparatedBy::allow_leading
and SeparatedBy::allow_trailing
for more examples.
sourcefn rewind(self) -> Rewind<Self>where
Self: Sized,
fn rewind(self) -> Rewind<Self>where
Self: Sized,
Parse a pattern. Afterwards, the input stream will be rewound to its original state, as if parsing had not occurred.
This combinator is useful for cases in which you wish to avoid a parser accidentally consuming too much input, causing later parsers to fail as a result. A typical use-case of this is that you want to parse something that is not followed by something else.
The output type of this parser is O
, the same as the original parser.
Examples
let just_numbers = text::digits::<_, Simple<char>>(10)
.padded()
.then_ignore(none_of("+-*/").rewind())
.separated_by(just(','));
// 3 is not parsed because it's followed by '+'.
assert_eq!(just_numbers.parse("1, 2, 3 + 4"), Ok(vec!["1".to_string(), "2".to_string()]));
sourcefn boxed<'a>(self) -> BoxedParser<'a, I, O, Self::Error>where
Self: Sized + 'a,
fn boxed<'a>(self) -> BoxedParser<'a, I, O, Self::Error>where
Self: Sized + 'a,
Box the parser, yielding a parser that performs parsing through dynamic dispatch.
Boxing a parser might be useful for:
-
Dynamically building up parsers at runtime
-
Improving compilation times (Rust can struggle to compile code containing very long types)
-
Passing a parser over an FFI boundary
-
Getting around compiler implementation problems with long types such as this.
-
Places where you need to name the type of a parser
Boxing a parser is broadly equivalent to boxing other combinators via dynamic dispatch, such as Iterator
.
The output type of this parser is O
, the same as the original parser.
sourcefn from_str<U>(self) -> Map<Self, fn(_: O) -> Result<U, U::Err>, O>where
Self: Sized,
U: FromStr,
O: AsRef<str>,
fn from_str<U>(self) -> Map<Self, fn(_: O) -> Result<U, U::Err>, O>where
Self: Sized,
U: FromStr,
O: AsRef<str>,
Attempt to convert the output of this parser into something else using Rust’s FromStr
trait.
This is most useful when wanting to convert literal values into their corresponding Rust type, such as when parsing integers.
The output type of this parser is Result<U, U::Err>
, the result of attempting to parse the output, O
, into
the value U
.
Examples
let uint64 = text::int::<_, Simple<char>>(10)
.from_str::<u64>()
.unwrapped();
assert_eq!(uint64.parse("7"), Ok(7));
assert_eq!(uint64.parse("42"), Ok(42));
sourcefn unwrapped<U, E>(self) -> Unwrapped<Self, E, <Self as Parser<I, O>>::Error>where
Self: Sized + Parser<I, Result<U, E>>,
E: Debug,
fn unwrapped<U, E>(self) -> Unwrapped<Self, E, <Self as Parser<I, O>>::Error>where
Self: Sized + Parser<I, Result<U, E>>,
E: Debug,
For parsers that produce a Result
as their output, unwrap the result (panicking if an Err
is
encountered).
In general, this method should be avoided except in cases where all possible that the parser might produce can
by parsed using FromStr
without producing an error.
This combinator is not named unwrap
to avoid confusion: it unwraps during parsing, not immediately.
The output type of this parser is U
, the Ok
value of the Result
.
Examples
let boolean = just::<_, _, Simple<char>>("true")
.or(just("false"))
.from_str::<bool>()
.unwrapped(); // Cannot panic: the only possible outputs generated by the parser are "true" or "false"
assert_eq!(boolean.parse("true"), Ok(true));
assert_eq!(boolean.parse("false"), Ok(false));
// Does not panic, because the original parser only accepts "true" or "false"
assert!(boolean.parse("42").is_err());