Coverage Report

Created: 2025-07-12 07:18

/rust/registry/src/index.crates.io-6f17d22bba15001f/nom-7.1.3/src/branch/mod.rs
Line
Count
Source (jump to first uncovered line)
1
//! Choice combinators
2
3
#[cfg(test)]
4
mod tests;
5
6
use crate::error::ErrorKind;
7
use crate::error::ParseError;
8
use crate::internal::{Err, IResult, Parser};
9
10
/// Helper trait for the [alt()] combinator.
11
///
12
/// This trait is implemented for tuples of up to 21 elements
13
pub trait Alt<I, O, E> {
14
  /// Tests each parser in the tuple and returns the result of the first one that succeeds
15
  fn choice(&mut self, input: I) -> IResult<I, O, E>;
16
}
17
18
/// Tests a list of parsers one by one until one succeeds.
19
///
20
/// It takes as argument a tuple of parsers. There is a maximum of 21
21
/// parsers. If you need more, it is possible to nest them in other `alt` calls,
22
/// like this: `alt(parser_a, alt(parser_b, parser_c))`
23
///
24
/// ```rust
25
/// # use nom::error_position;
26
/// # use nom::{Err,error::ErrorKind, Needed, IResult};
27
/// use nom::character::complete::{alpha1, digit1};
28
/// use nom::branch::alt;
29
/// # fn main() {
30
/// fn parser(input: &str) -> IResult<&str, &str> {
31
///   alt((alpha1, digit1))(input)
32
/// };
33
///
34
/// // the first parser, alpha1, recognizes the input
35
/// assert_eq!(parser("abc"), Ok(("", "abc")));
36
///
37
/// // the first parser returns an error, so alt tries the second one
38
/// assert_eq!(parser("123456"), Ok(("", "123456")));
39
///
40
/// // both parsers failed, and with the default error type, alt will return the last error
41
/// assert_eq!(parser(" "), Err(Err::Error(error_position!(" ", ErrorKind::Digit))));
42
/// # }
43
/// ```
44
///
45
/// With a custom error type, it is possible to have alt return the error of the parser
46
/// that went the farthest in the input data
47
0
pub fn alt<I: Clone, O, E: ParseError<I>, List: Alt<I, O, E>>(
48
0
  mut l: List,
49
0
) -> impl FnMut(I) -> IResult<I, O, E> {
50
0
  move |i: I| l.choice(i)
Unexecuted instantiation: nom::branch::alt::<&str, &str, nom::error::Error<&str>, (nom::character::complete::line_ending<&str, nom::error::Error<&str>>, nom::combinator::eof<&str, nom::error::Error<&str>>)>::{closure#0}
Unexecuted instantiation: nom::branch::alt::<_, _, _, _>::{closure#0}
51
0
}
Unexecuted instantiation: nom::branch::alt::<&str, &str, nom::error::Error<&str>, (nom::character::complete::line_ending<&str, nom::error::Error<&str>>, nom::combinator::eof<&str, nom::error::Error<&str>>)>
Unexecuted instantiation: nom::branch::alt::<_, _, _, _>
52
53
/// Helper trait for the [permutation()] combinator.
54
///
55
/// This trait is implemented for tuples of up to 21 elements
56
pub trait Permutation<I, O, E> {
57
  /// Tries to apply all parsers in the tuple in various orders until all of them succeed
58
  fn permutation(&mut self, input: I) -> IResult<I, O, E>;
59
}
60
61
/// Applies a list of parsers in any order.
62
///
63
/// Permutation will succeed if all of the child parsers succeeded.
64
/// It takes as argument a tuple of parsers, and returns a
65
/// tuple of the parser results.
66
///
67
/// ```rust
68
/// # use nom::{Err,error::{Error, ErrorKind}, Needed, IResult};
69
/// use nom::character::complete::{alpha1, digit1};
70
/// use nom::branch::permutation;
71
/// # fn main() {
72
/// fn parser(input: &str) -> IResult<&str, (&str, &str)> {
73
///   permutation((alpha1, digit1))(input)
74
/// }
75
///
76
/// // permutation recognizes alphabetic characters then digit
77
/// assert_eq!(parser("abc123"), Ok(("", ("abc", "123"))));
78
///
79
/// // but also in inverse order
80
/// assert_eq!(parser("123abc"), Ok(("", ("abc", "123"))));
81
///
82
/// // it will fail if one of the parsers failed
83
/// assert_eq!(parser("abc;"), Err(Err::Error(Error::new(";", ErrorKind::Digit))));
84
/// # }
85
/// ```
86
///
87
/// The parsers are applied greedily: if there are multiple unapplied parsers
88
/// that could parse the next slice of input, the first one is used.
89
/// ```rust
90
/// # use nom::{Err, error::{Error, ErrorKind}, IResult};
91
/// use nom::branch::permutation;
92
/// use nom::character::complete::{anychar, char};
93
///
94
/// fn parser(input: &str) -> IResult<&str, (char, char)> {
95
///   permutation((anychar, char('a')))(input)
96
/// }
97
///
98
/// // anychar parses 'b', then char('a') parses 'a'
99
/// assert_eq!(parser("ba"), Ok(("", ('b', 'a'))));
100
///
101
/// // anychar parses 'a', then char('a') fails on 'b',
102
/// // even though char('a') followed by anychar would succeed
103
/// assert_eq!(parser("ab"), Err(Err::Error(Error::new("b", ErrorKind::Char))));
104
/// ```
105
///
106
0
pub fn permutation<I: Clone, O, E: ParseError<I>, List: Permutation<I, O, E>>(
107
0
  mut l: List,
108
0
) -> impl FnMut(I) -> IResult<I, O, E> {
109
0
  move |i: I| l.permutation(i)
110
0
}
111
112
macro_rules! alt_trait(
113
  ($first:ident $second:ident $($id: ident)+) => (
114
    alt_trait!(__impl $first $second; $($id)+);
115
  );
116
  (__impl $($current:ident)*; $head:ident $($id: ident)+) => (
117
    alt_trait_impl!($($current)*);
118
119
    alt_trait!(__impl $($current)* $head; $($id)+);
120
  );
121
  (__impl $($current:ident)*; $head:ident) => (
122
    alt_trait_impl!($($current)*);
123
    alt_trait_impl!($($current)* $head);
124
  );
125
);
126
127
macro_rules! alt_trait_impl(
128
  ($($id:ident)+) => (
129
    impl<
130
      Input: Clone, Output, Error: ParseError<Input>,
131
      $($id: Parser<Input, Output, Error>),+
132
    > Alt<Input, Output, Error> for ( $($id),+ ) {
133
134
0
      fn choice(&mut self, input: Input) -> IResult<Input, Output, Error> {
135
0
        match self.0.parse(input.clone()) {
136
0
          Err(Err::Error(e)) => alt_trait_inner!(1, self, input, e, $($id)+),
137
0
          res => res,
138
        }
139
0
      }
Unexecuted instantiation: <(nom::character::complete::line_ending<&str, nom::error::Error<&str>>, nom::combinator::eof<&str, nom::error::Error<&str>>) as nom::branch::Alt<&str, &str, nom::error::Error<&str>>>::choice
Unexecuted instantiation: <(_, _) as nom::branch::Alt<_, _, _>>::choice
Unexecuted instantiation: <(_, _, _) as nom::branch::Alt<_, _, _>>::choice
Unexecuted instantiation: <(_, _, _, _) as nom::branch::Alt<_, _, _>>::choice
Unexecuted instantiation: <(_, _, _, _, _) as nom::branch::Alt<_, _, _>>::choice
Unexecuted instantiation: <(_, _, _, _, _, _) as nom::branch::Alt<_, _, _>>::choice
Unexecuted instantiation: <(_, _, _, _, _, _, _) as nom::branch::Alt<_, _, _>>::choice
Unexecuted instantiation: <(_, _, _, _, _, _, _, _) as nom::branch::Alt<_, _, _>>::choice
Unexecuted instantiation: <(_, _, _, _, _, _, _, _, _) as nom::branch::Alt<_, _, _>>::choice
Unexecuted instantiation: <(_, _, _, _, _, _, _, _, _, _) as nom::branch::Alt<_, _, _>>::choice
Unexecuted instantiation: <(_, _, _, _, _, _, _, _, _, _, _) as nom::branch::Alt<_, _, _>>::choice
Unexecuted instantiation: <(_, _, _, _, _, _, _, _, _, _, _, _) as nom::branch::Alt<_, _, _>>::choice
Unexecuted instantiation: <(_, _, _, _, _, _, _, _, _, _, _, _, _) as nom::branch::Alt<_, _, _>>::choice
Unexecuted instantiation: <(_, _, _, _, _, _, _, _, _, _, _, _, _, _) as nom::branch::Alt<_, _, _>>::choice
Unexecuted instantiation: <(_, _, _, _, _, _, _, _, _, _, _, _, _, _, _) as nom::branch::Alt<_, _, _>>::choice
Unexecuted instantiation: <(_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) as nom::branch::Alt<_, _, _>>::choice
Unexecuted instantiation: <(_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) as nom::branch::Alt<_, _, _>>::choice
Unexecuted instantiation: <(_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) as nom::branch::Alt<_, _, _>>::choice
Unexecuted instantiation: <(_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) as nom::branch::Alt<_, _, _>>::choice
Unexecuted instantiation: <(_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) as nom::branch::Alt<_, _, _>>::choice
Unexecuted instantiation: <(_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) as nom::branch::Alt<_, _, _>>::choice
140
    }
141
  );
142
);
143
144
macro_rules! alt_trait_inner(
145
  ($it:tt, $self:expr, $input:expr, $err:expr, $head:ident $($id:ident)+) => (
146
    match $self.$it.parse($input.clone()) {
147
      Err(Err::Error(e)) => {
148
        let err = $err.or(e);
149
        succ!($it, alt_trait_inner!($self, $input, err, $($id)+))
150
      }
151
      res => res,
152
    }
153
  );
154
  ($it:tt, $self:expr, $input:expr, $err:expr, $head:ident) => (
155
    Err(Err::Error(Error::append($input, ErrorKind::Alt, $err)))
156
  );
157
);
158
159
alt_trait!(A B C D E F G H I J K L M N O P Q R S T U);
160
161
// Manually implement Alt for (A,), the 1-tuple type
162
impl<Input, Output, Error: ParseError<Input>, A: Parser<Input, Output, Error>>
163
  Alt<Input, Output, Error> for (A,)
164
{
165
0
  fn choice(&mut self, input: Input) -> IResult<Input, Output, Error> {
166
0
    self.0.parse(input)
167
0
  }
168
}
169
170
macro_rules! permutation_trait(
171
  (
172
    $name1:ident $ty1:ident $item1:ident
173
    $name2:ident $ty2:ident $item2:ident
174
    $($name3:ident $ty3:ident $item3:ident)*
175
  ) => (
176
    permutation_trait!(__impl $name1 $ty1 $item1, $name2 $ty2 $item2; $($name3 $ty3 $item3)*);
177
  );
178
  (
179
    __impl $($name:ident $ty:ident $item:ident),+;
180
    $name1:ident $ty1:ident $item1:ident $($name2:ident $ty2:ident $item2:ident)*
181
  ) => (
182
    permutation_trait_impl!($($name $ty $item),+);
183
    permutation_trait!(__impl $($name $ty $item),+ , $name1 $ty1 $item1; $($name2 $ty2 $item2)*);
184
  );
185
  (__impl $($name:ident $ty:ident $item:ident),+;) => (
186
    permutation_trait_impl!($($name $ty $item),+);
187
  );
188
);
189
190
macro_rules! permutation_trait_impl(
191
  ($($name:ident $ty:ident $item:ident),+) => (
192
    impl<
193
      Input: Clone, $($ty),+ , Error: ParseError<Input>,
194
      $($name: Parser<Input, $ty, Error>),+
195
    > Permutation<Input, ( $($ty),+ ), Error> for ( $($name),+ ) {
196
197
0
      fn permutation(&mut self, mut input: Input) -> IResult<Input, ( $($ty),+ ), Error> {
198
0
        let mut res = ($(Option::<$ty>::None),+);
199
200
        loop {
201
0
          let mut err: Option<Error> = None;
202
0
          permutation_trait_inner!(0, self, input, res, err, $($name)+);
203
204
          // If we reach here, every iterator has either been applied before,
205
          // or errored on the remaining input
206
0
          if let Some(err) = err {
207
            // There are remaining parsers, and all errored on the remaining input
208
0
            return Err(Err::Error(Error::append(input, ErrorKind::Permutation, err)));
209
0
          }
210
211
          // All parsers were applied
212
0
          match res {
213
0
            ($(Some($item)),+) => return Ok((input, ($($item),+))),
214
0
            _ => unreachable!(),
215
          }
216
        }
217
0
      }
Unexecuted instantiation: <(_, _) as nom::branch::Permutation<_, (_, _), _>>::permutation
Unexecuted instantiation: <(_, _, _) as nom::branch::Permutation<_, (_, _, _), _>>::permutation
Unexecuted instantiation: <(_, _, _, _) as nom::branch::Permutation<_, (_, _, _, _), _>>::permutation
Unexecuted instantiation: <(_, _, _, _, _) as nom::branch::Permutation<_, (_, _, _, _, _), _>>::permutation
Unexecuted instantiation: <(_, _, _, _, _, _) as nom::branch::Permutation<_, (_, _, _, _, _, _), _>>::permutation
Unexecuted instantiation: <(_, _, _, _, _, _, _) as nom::branch::Permutation<_, (_, _, _, _, _, _, _), _>>::permutation
Unexecuted instantiation: <(_, _, _, _, _, _, _, _) as nom::branch::Permutation<_, (_, _, _, _, _, _, _, _), _>>::permutation
Unexecuted instantiation: <(_, _, _, _, _, _, _, _, _) as nom::branch::Permutation<_, (_, _, _, _, _, _, _, _, _), _>>::permutation
Unexecuted instantiation: <(_, _, _, _, _, _, _, _, _, _) as nom::branch::Permutation<_, (_, _, _, _, _, _, _, _, _, _), _>>::permutation
Unexecuted instantiation: <(_, _, _, _, _, _, _, _, _, _, _) as nom::branch::Permutation<_, (_, _, _, _, _, _, _, _, _, _, _), _>>::permutation
Unexecuted instantiation: <(_, _, _, _, _, _, _, _, _, _, _, _) as nom::branch::Permutation<_, (_, _, _, _, _, _, _, _, _, _, _, _), _>>::permutation
Unexecuted instantiation: <(_, _, _, _, _, _, _, _, _, _, _, _, _) as nom::branch::Permutation<_, (_, _, _, _, _, _, _, _, _, _, _, _, _), _>>::permutation
Unexecuted instantiation: <(_, _, _, _, _, _, _, _, _, _, _, _, _, _) as nom::branch::Permutation<_, (_, _, _, _, _, _, _, _, _, _, _, _, _, _), _>>::permutation
Unexecuted instantiation: <(_, _, _, _, _, _, _, _, _, _, _, _, _, _, _) as nom::branch::Permutation<_, (_, _, _, _, _, _, _, _, _, _, _, _, _, _, _), _>>::permutation
Unexecuted instantiation: <(_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) as nom::branch::Permutation<_, (_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _), _>>::permutation
Unexecuted instantiation: <(_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) as nom::branch::Permutation<_, (_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _), _>>::permutation
Unexecuted instantiation: <(_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) as nom::branch::Permutation<_, (_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _), _>>::permutation
Unexecuted instantiation: <(_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) as nom::branch::Permutation<_, (_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _), _>>::permutation
Unexecuted instantiation: <(_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) as nom::branch::Permutation<_, (_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _), _>>::permutation
Unexecuted instantiation: <(_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) as nom::branch::Permutation<_, (_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _), _>>::permutation
218
    }
219
  );
220
);
221
222
macro_rules! permutation_trait_inner(
223
  ($it:tt, $self:expr, $input:ident, $res:expr, $err:expr, $head:ident $($id:ident)*) => (
224
    if $res.$it.is_none() {
225
      match $self.$it.parse($input.clone()) {
226
        Ok((i, o)) => {
227
          $input = i;
228
          $res.$it = Some(o);
229
          continue;
230
        }
231
        Err(Err::Error(e)) => {
232
          $err = Some(match $err {
233
            Some(err) => err.or(e),
234
            None => e,
235
          });
236
        }
237
        Err(e) => return Err(e),
238
      };
239
    }
240
    succ!($it, permutation_trait_inner!($self, $input, $res, $err, $($id)*));
241
  );
242
  ($it:tt, $self:expr, $input:ident, $res:expr, $err:expr,) => ();
243
);
244
245
permutation_trait!(
246
  FnA A a
247
  FnB B b
248
  FnC C c
249
  FnD D d
250
  FnE E e
251
  FnF F f
252
  FnG G g
253
  FnH H h
254
  FnI I i
255
  FnJ J j
256
  FnK K k
257
  FnL L l
258
  FnM M m
259
  FnN N n
260
  FnO O o
261
  FnP P p
262
  FnQ Q q
263
  FnR R r
264
  FnS S s
265
  FnT T t
266
  FnU U u
267
);