1use std::collections::HashMap; 2use std::iter::Iterator; 3 4use nom::bytes::complete::tag; 5use nom::character::complete::alphanumeric1; 6use nom::combinator::iterator; 7use nom::sequence::{separated_pair, terminated}; 8use nom::IResult; 9 10fn 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