Skip to content

Instantly share code, notes, and snippets.

@Geal
Created May 8, 2019 09:32
Show Gist options
  • Save Geal/6c8f82260660c8f3a2f775aafc6f092d to your computer and use it in GitHub Desktop.
Save Geal/6c8f82260660c8f3a2f775aafc6f092d to your computer and use it in GitHub Desktop.
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