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