winnow/macros/
dispatch.rs

1/// `match` for parsers
2///
3/// When parsers have unique prefixes to test for, this offers better performance over
4/// [`alt`][crate::combinator::alt] though it might be at the cost of duplicating parts of your grammar
5/// if you needed to [`peek`][crate::combinator::peek].
6///
7/// For tight control over the error in a catch-all case, use [`fail`][crate::combinator::fail].
8///
9/// # Example
10///
11/// ```rust
12/// use winnow::prelude::*;
13/// use winnow::combinator::dispatch;
14/// # use winnow::token::any;
15/// # use winnow::combinator::peek;
16/// # use winnow::combinator::preceded;
17/// # use winnow::combinator::empty;
18/// # use winnow::combinator::fail;
19///
20/// fn escaped(input: &mut &str) -> PResult<char> {
21///     preceded('\\', escape_seq_char).parse_next(input)
22/// }
23///
24/// fn escape_seq_char(input: &mut &str) -> PResult<char> {
25///     dispatch! {any;
26///         'b' => empty.value('\u{8}'),
27///         'f' => empty.value('\u{c}'),
28///         'n' => empty.value('\n'),
29///         'r' => empty.value('\r'),
30///         't' => empty.value('\t'),
31///         '\\' => empty.value('\\'),
32///         '"' => empty.value('"'),
33///         _ => fail::<_, char, _>,
34///     }
35///     .parse_next(input)
36/// }
37///
38/// assert_eq!(escaped.parse_peek("\\nHello"), Ok(("Hello", '\n')));
39/// ```
40#[macro_export]
41#[doc(hidden)] // forced to be visible in intended location
42macro_rules! dispatch {
43    ($match_parser: expr; $( $pat:pat $(if $pred:expr)? => $expr: expr ),+ $(,)? ) => {
44        $crate::combinator::trace("dispatch", move |i: &mut _|
45        {
46            use $crate::Parser;
47            let initial = $match_parser.parse_next(i)?;
48            match initial {
49                $(
50                    $pat $(if $pred)? => $expr.parse_next(i),
51                )*
52            }
53        })
54    }
55}