Created
May 8, 2019 09:32
-
-
Save Geal/6c8f82260660c8f3a2f775aafc6f092d to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
extern crate nom; | |
use nom::IResult; | |
use nom::bytes::complete::tag; | |
use nom::sequence::{separated_pair, terminated}; | |
use nom::character::complete::alphanumeric1; | |
use std::cell::{Cell, RefCell}; | |
use std::rc::Rc; | |
use std::iter::Iterator; | |
use std::collections::HashMap; | |
fn main() { | |
let data = Rc::new(Cell::new("abcabcabcabc")); | |
let data2 = data.clone(); | |
fn parser(i: &str) -> IResult<&str, &str> { | |
tag("abc")(i) | |
} | |
{ | |
let it = std::iter::from_fn(move|| { | |
match parser(data.get()) { | |
Ok((i, o)) => { | |
data.set(i); | |
println!("parsing, data is now {}", data.get()); | |
Some(o) | |
}, | |
_ => None | |
} | |
}); | |
for value in it { | |
println!("parser returned: {}", value); | |
} | |
} | |
println!("\ndata is now: {:?}", data2); | |
let data = "abcabcabcabc"; | |
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); | |
let data = "key1:value1,key2:value2,key3:value3,;"; | |
let (iterator, fin) = iterator(data, terminated(separated_pair(alphanumeric1, tag(":"), alphanumeric1), tag(","))); | |
let res = iterator.collect::<HashMap<_, _>>(); | |
let parser_result: IResult<_, _> = fin.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); | |
} | |
use nom::{Needed, Err, error::ParseError}; | |
pub enum State<E> { | |
Running, | |
Done, | |
Failure(E), | |
Incomplete(Needed), | |
} | |
pub struct NomItState<Input, E> { | |
pub input: Input, | |
pub state: State<E> | |
} | |
impl<I, E> NomItState<I,E> { | |
pub fn set_input(&mut self, input: I) { | |
self.input = input; | |
} | |
pub fn set_state(&mut self, s: State<E>) { | |
self.state = s; | |
} | |
} | |
pub struct NomIt<Input, E, F> { | |
iterator: F, | |
state: Rc<RefCell<NomItState<Input, E>>>, | |
} | |
pub struct NomItFinish<Input, E> { | |
state: Rc<RefCell<NomItState<Input, E>>>, | |
} | |
pub fn iterator<Input, Output, Error, F>(input: Input, f: F) -> (NomIt<Input, Error, F>, NomItFinish<Input, Error>) | |
where | |
F: Fn(Input) -> IResult<Input, Output, Error>, | |
Error: ParseError<Input> { | |
let state = Rc::new(RefCell::new(NomItState { | |
input: input, | |
state: State::Running, | |
})); | |
(NomIt { | |
iterator: f, | |
state: state.clone(), | |
}, | |
NomItFinish { | |
state | |
}) | |
} | |
impl<I: Clone, E: Clone> NomItFinish<I, E> { | |
pub fn finish(self) -> IResult<I, (), E> { | |
let state = (*self.state).borrow(); | |
match &state.state { | |
State::Running | State::Done => Ok((state.input.clone(), ())), | |
State::Failure(e) => Err(Err::Failure(e.clone())), | |
State::Incomplete(i) => Err(Err::Incomplete(i.clone())), | |
} | |
} | |
} | |
impl<Input ,Output ,Error, F> Iterator for NomIt<Input, Error, F> | |
where | |
F: Fn(Input) -> IResult<Input, Output, Error>, | |
Input: Clone | |
{ | |
type Item = Output; | |
#[inline] | |
fn next(&mut self) -> Option<Self::Item> { | |
let mut state = (*self.state).borrow_mut(); | |
if let State::Running = (*state).state { | |
let input = state.input.clone(); | |
match (self.iterator)(input) { | |
Ok((i, o)) => { | |
state.set_input(i); | |
println!("parser ok"); | |
Some(o) | |
}, | |
Err(Err::Error(_)) => { | |
println!("parser err"); | |
state.set_state(State::Done); | |
None | |
}, | |
Err(Err::Failure(e)) => { | |
println!("parser failure"); | |
state.set_state(State::Failure(e)); | |
None | |
}, | |
Err(Err::Incomplete(i)) => { | |
println!("parser incomplete"); | |
state.set_state(State::Incomplete(i)); | |
None | |
}, | |
} | |
} else { | |
None | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment