1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
//! Combinators that parse alternatives.
use crate::errors::*;
use crate::parsers::*;
/// Run a parser and return its result on success or an empty result on failure.
///
/// ```
/// # use glue::prelude::*;
/// assert_eq!(optional(literal("foobar")).parse("foobar"), Ok((
/// "foobar", ""
/// )));
/// assert_eq!(optional(literal("foobar")).parse("boofar"), Ok((
/// "", "boofar"
/// )));
/// ```
pub fn optional<I: Parsable, C: Parser<I>>(callback: C) -> impl Parser<I> {
move |input: I| match callback.parse(input) {
Ok((result, next)) => Ok((result, next)),
Err(_) => Ok((input.take_empty(), input)),
}
}
/// Run either parser returning whichever succeeds.
///
/// ```
/// # use glue::prelude::*;
/// assert_eq!(either(literal("bar"), literal("foo")).parse("foobar"), Ok((
/// "foo", "bar"
/// )));
/// assert_eq!(either(literal("bar"), literal("foo")).parse("barfoo"), Ok((
/// "bar", "foo"
/// )));
/// ```
pub fn either<I: Parsable, O, C1: Parser<I, O>, C2: Parser<I, O>>(
first: C1,
second: C2,
) -> impl Parser<I, O> {
move |input: I| {
let mut errors = Vec::new();
match first.parse(input.clone()) {
Ok((result, input)) => return Ok((result, input)),
Err(error) => errors.push(error),
};
match second.parse(input.clone()) {
Ok((result, input)) => return Ok((result, input)),
Err(error) => errors.push(error),
};
Err(BranchFailed(input, errors))
}
}
/// Run each of the provided parsers and return the first that is successful.
///
/// ```
/// # use glue::prelude::*;
/// assert_eq!(any((literal("foo"), literal("bar"))).parse("foobar"), Ok((
/// "foo", "bar"
/// )));
/// ```
pub fn any<I: Parsable, O, C: BranchParser<I, O>>(callback: C) -> impl Parser<I, O> {
move |input: I| callback.parse(input)
}
#[test]
fn any_parses_with_literal() {
use crate::prelude::*;
assert_eq!(
any((literal("bar"), literal("foo"))).parse("foobar"),
Ok(("foo", "bar"))
);
}
#[test]
fn any_errors_without_match() {
use crate::prelude::*;
assert_eq!(
any((literal("bar"), literal("far"))).parse("foobar"),
Err(BranchFailed(
"foobar",
vec![LiteralMatchFailed("foobar"), LiteralMatchFailed("foobar")]
))
);
}