/rust/registry/src/index.crates.io-1949cf8c6b5b557f/winnow-0.7.6/src/macros/dispatch.rs
Line | Count | Source |
1 | | /// `match` for parsers |
2 | | /// |
3 | | /// While `match` works by accepting a value and returning values: |
4 | | /// ```rust,ignore |
5 | | /// let result_value = match scrutinee_value { |
6 | | /// ArmPattern => arm_value, |
7 | | /// }; |
8 | | /// ``` |
9 | | /// `dispatch!` composes parsers: |
10 | | /// ```rust,ignore |
11 | | /// let result_parser = dispatch!{scrutinee_parser; |
12 | | /// ArmPattern => arm_parser, |
13 | | /// }; |
14 | | /// ``` |
15 | | /// |
16 | | /// This is useful when parsers have unique prefixes to test for. |
17 | | /// This offers better performance over |
18 | | /// [`alt`][crate::combinator::alt] though it might be at the cost of duplicating parts of your grammar |
19 | | /// if you needed to [`peek(input_parser)`][crate::combinator::peek] the scrutinee. |
20 | | /// |
21 | | /// For tight control over the error in a catch-all case, use [`fail`][crate::combinator::fail]. |
22 | | /// |
23 | | /// # Example |
24 | | /// |
25 | | /// ```rust |
26 | | /// use winnow::prelude::*; |
27 | | /// use winnow::combinator::dispatch; |
28 | | /// # use winnow::token::take; |
29 | | /// # use winnow::token::take_while; |
30 | | /// # use winnow::combinator::fail; |
31 | | /// |
32 | | /// fn integer(input: &mut &str) -> ModalResult<u64> { |
33 | | /// dispatch! {take(2usize); |
34 | | /// "0b" => take_while(1.., '0'..='1').try_map(|s| u64::from_str_radix(s, 2)), |
35 | | /// "0o" => take_while(1.., '0'..='7').try_map(|s| u64::from_str_radix(s, 8)), |
36 | | /// "0d" => take_while(1.., '0'..='9').try_map(|s| u64::from_str_radix(s, 10)), |
37 | | /// "0x" => take_while(1.., ('0'..='9', 'a'..='f', 'A'..='F')).try_map(|s| u64::from_str_radix(s, 16)), |
38 | | /// _ => fail::<_, u64, _>, |
39 | | /// } |
40 | | /// .parse_next(input) |
41 | | /// } |
42 | | /// |
43 | | /// assert_eq!(integer.parse_peek("0x100 Hello"), Ok((" Hello", 0x100))); |
44 | | /// ``` |
45 | | /// |
46 | | /// ```rust |
47 | | /// use winnow::prelude::*; |
48 | | /// use winnow::combinator::dispatch; |
49 | | /// # use winnow::token::any; |
50 | | /// # use winnow::combinator::preceded; |
51 | | /// # use winnow::combinator::empty; |
52 | | /// # use winnow::combinator::fail; |
53 | | /// |
54 | | /// fn escaped(input: &mut &str) -> ModalResult<char> { |
55 | | /// preceded('\\', escape_seq_char).parse_next(input) |
56 | | /// } |
57 | | /// |
58 | | /// fn escape_seq_char(input: &mut &str) -> ModalResult<char> { |
59 | | /// dispatch! {any; |
60 | | /// 'b' => empty.value('\u{8}'), |
61 | | /// 'f' => empty.value('\u{c}'), |
62 | | /// 'n' => empty.value('\n'), |
63 | | /// 'r' => empty.value('\r'), |
64 | | /// 't' => empty.value('\t'), |
65 | | /// '\\' => empty.value('\\'), |
66 | | /// '"' => empty.value('"'), |
67 | | /// _ => fail::<_, char, _>, |
68 | | /// } |
69 | | /// .parse_next(input) |
70 | | /// } |
71 | | /// |
72 | | /// assert_eq!(escaped.parse_peek("\\nHello"), Ok(("Hello", '\n'))); |
73 | | /// ``` |
74 | | #[macro_export] |
75 | | #[doc(hidden)] // forced to be visible in intended location |
76 | | macro_rules! dispatch { |
77 | | ( |
78 | | $scrutinee_parser:expr; |
79 | | $( $arm_pat:pat $(if $arm_pred:expr)? => $arm_parser: expr ),+ $(,)? |
80 | | ) => { |
81 | | $crate::combinator::trace("dispatch", move |i: &mut _| |
82 | 0 | { |
83 | | use $crate::Parser; |
84 | 0 | let initial = $scrutinee_parser.parse_next(i)?; |
85 | 0 | match initial { |
86 | | $( |
87 | 0 | $arm_pat $(if $arm_pred)? => $arm_parser.parse_next(i), |
88 | | )* |
89 | | } |
90 | 0 | }) Unexecuted instantiation: winnow::ascii::take_float_or_exceptions::<_, _>::{closure#0}Unexecuted instantiation: winnow::ascii::take_unsigned_float_or_exceptions::<_, _>::{closure#0}Unexecuted instantiation: winnow::ascii::take_exp::<_, _>::{closure#0}Unexecuted instantiation: winnow::ascii::dec_int::<_, _, _>::{closure#0}::{closure#1} |
91 | | } |
92 | | } |