• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use std::collections::HashMap;
2 use std::iter::Iterator;
3 
4 use nom::bytes::complete::tag;
5 use nom::character::complete::alphanumeric1;
6 use nom::combinator::iterator;
7 use nom::sequence::{separated_pair, terminated};
8 use nom::IResult;
9 
main()10 fn main() {
11   let mut data = "abcabcabcabc";
12 
13   fn parser(i: &str) -> IResult<&str, &str> {
14     tag("abc")(i)
15   }
16 
17   // `from_fn` (available from Rust 1.34) can create an iterator
18   // from a closure
19   let it = std::iter::from_fn(move || {
20     match parser(data) {
21       // when successful, a nom parser returns a tuple of
22       // the remaining input and the output value.
23       // So we replace the captured input data with the
24       // remaining input, to be parsed on the next call
25       Ok((i, o)) => {
26         data = i;
27         Some(o)
28       }
29       _ => None,
30     }
31   });
32 
33   for value in it {
34     println!("parser returned: {}", value);
35   }
36 
37   println!("\n********************\n");
38 
39   let data = "abcabcabcabc";
40 
41   // if `from_fn` is not available, it is possible to fold
42   // over an iterator of functions
43   let res =
44     std::iter::repeat(parser)
45       .take(3)
46       .try_fold((data, Vec::new()), |(data, mut acc), parser| {
47         parser(data).map(|(i, o)| {
48           acc.push(o);
49           (i, acc)
50         })
51       });
52 
53   // will print "parser iterator returned: Ok(("abc", ["abc", "abc", "abc"]))"
54   println!("\nparser iterator returned: {:?}", res);
55 
56   println!("\n********************\n");
57 
58   let data = "key1:value1,key2:value2,key3:value3,;";
59 
60   // `nom::combinator::iterator` will return an iterator
61   // producing the parsed values. Compared to the previous
62   // solutions:
63   // - we can work with a normal iterator like `from_fn`
64   // - we can get the remaining input afterwards, like with the `try_fold` trick
65   let mut nom_it = iterator(
66     data,
67     terminated(
68       separated_pair(alphanumeric1, tag(":"), alphanumeric1),
69       tag(","),
70     ),
71   );
72 
73   let res = nom_it
74     .map(|(k, v)| (k.to_uppercase(), v))
75     .collect::<HashMap<_, _>>();
76 
77   let parser_result: IResult<_, _> = nom_it.finish();
78   let (remaining_input, ()) = parser_result.unwrap();
79 
80   // will print "iterator returned {"key1": "value1", "key3": "value3", "key2": "value2"}, remaining input is ';'"
81   println!(
82     "iterator returned {:?}, remaining input is '{}'",
83     res, remaining_input
84   );
85 }
86