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