[−][src]Module autumn::combinators
Traits for combining and modifying parsers
Combinators provide ways of modifying the behavior of parsers and combining parsers that is consistent across all parser implementations.
Parsing sequences
Parsing sequences of characters or values from input is done using parsers that produce a
Concat
and the ConcatParserExt
trait that is
implemented for all such parsers.
The ConcatParserExt
provides three combinators for manipulating
parsers over sequences of values:
maybe
repeats a parser zero or one times,multiple
repeats a parser one or more times, andand
uses two parsers in sequence, concatenating their results into a single list.
/// Parses C-like identifiers fn identifier(source: &str, location: Span) -> ParseResult<String> { alphabetic .or("_") .and(alphanumeric.or("_").multiple().maybe()) .copy_string() .parse(source, location) }
When using both multiple
and
maybe
to achieve zero or more repetitions,
multiple().maybe()
must be used; maybe().multiple()
can find an infinite number of ways to
apply any parser on even an empty string.
and
and
multiple
when used with parsers producing a
Span
must ensure that all spans are adjacent (don't use
drop
or skip
to
join a pair of Span
results that are not continuous).
Multiple potential parsers
The or
will take two parsers and attempt to evaluate both
of them returning any successful results produced by either of them. This can include duplicate
results if a given parse would be acceptable for either parser.
Changing the result of a parser
There are to ways in which the result of a parser can be changed:
- the output value and type can be simply mapped to a new value with a new type using the
map
operation, and - changing a successful (or already failing) parse into a potentially failing parse with the
and_then
operation.
#[derive(Clone)] struct InvalidIdentifier(String); /// Parses C-like identifiers fn identifier( source: &str, location: Span, ) -> ParseResult<Option<String>, InvalidIdentifier> { alphabetic .or("_") .and(alphanumeric.or("_").multiple()) .copy_string() .map(Some) .on_none( any_character .str_condition(|s| !s.chars().any(char::is_whitespace)) .multiple() .copy_string() .and_then(|identifier| throw(None, InvalidIdentifier(identifier))) ) .catch() .parse(source, location) }
Discarding the result of a parser
When using two parsers sequentially you may wish to discard the result of either sequence rather than concatenate the results.
The skip
method can be used to combine two parsers,
discarding the result of the first and keeping the result of the second.
The drop
method can be used to combine two parsers,
keeping the result of the first and discarding the result of the second.
// Produces "right" fn right() -> impl Parser<String> { "left".skip("right").copy_string() } let skipped = parse(right(), "leftright"); // Produces "left" fn left() -> impl Parser<String> { "left".drop("right").copy_string() } let dropped = parse(left(), "leftright");
Adding conditions to a parser
Two methods are provided to require the result of a parser to meet a certain condition:
condition
allows a certain condition to be specified as a function or closure, andmatching
allows a value to be provided which the result must match.
Ensuring a parser consumes all input
The end
can be used on any parser to ensure that after any
successful parse there is no text left un-parsed in the source. If not used, invoking a parser
directly can produce all prefixes that are themselves a valid parse of the source string.
Finding the source location for the result of a parser
When parsing a structured text input a parser may wish to know the location of a segment that
was parsed to produce a result. The meta
method will map
a parser such that its result is wrapped in a Meta
, binding it with
a Span
specifying the location in the source of the parsed text.
/// Parses integers fn integer(source: &str, location: Span) -> ParseResult<String> { digit.multiple().copy_string().parse(source, location) } /// Parse a list of integers and get the source location of each integer fn integer_list(source: &str, location: Span) -> ParseResult<Vec<Meta<String, Span>>> { integer .meta() .delimited_by(",".maybe_space_after(), ..) .surrounded_by("[".maybe_space_after(), "]") .collect() .parse(source, location) }
Matching parser types with dynamic dispatch
There are some cases where a parser may need to produce one of many values within the argument
to the and_then
method. In this case it helps to be
able to unify the types of the values with dynamic
dispatch.
This can be achieved simply with the boxed
method.
The value
, error
, and
throw
functions all produce boxed parsers with types that will
match as they are commonly used in this case.
fn alphabet(source: &str, location: Span) -> ParseResult<String, &'static str> { "abcde" .and(digit) .copy_string() .and_then(|text| { let text = text; if text.ends_with("0") { throw(text, "Token must not end with 0") } else { value(text) } }) .catch() .parse(source, location) }
Structs
And | The result of the |
AndThen | |
Boxed | The result of the |
Catch | |
Collect | The result of the |
Condition | |
DelimitedBy | The result of the |
Drop | |
End | |
Fold | |
ListMap | |
Map | |
Matching | |
Maybe | The result of the |
MaybeDrop | The result of the |
MaybeSpaceAfter | The result of the |
MaybeSpaceAround | The result of the |
MaybeSpaceBefore | The result of the |
MetaMap | |
Multiple | The result of the |
OnFailure | The result of the |
OnNone | |
Or | |
Pair | |
Referenced | The result of the |
Repeat | The result of the |
Skip | |
SpaceAfter | The result of the |
SpaceAround | The result of the |
SpaceBefore | The result of the |
StrCondition | The result of the |
StrictlyDelimitedBy | The result of the |
StringMap | The result of the |
SurroundedBy | The result of the |
Traits
BoxedParserExt | Boxing parsers for dynamic dispatch |
ConcatParserExt | Combinators on parsers that produce a |
ListParserExt | Combinators on parsers that produce a |
ParserExt | Combinators that can be used on all parsers |
TextParserExt | Combinators on parser that produce a list of characters |