Skip to content

Instantly share code, notes, and snippets.

@haudan
Created October 4, 2017 09:19
Show Gist options
  • Save haudan/8cd7ade3d78cc8456abcf9602d61183a to your computer and use it in GitHub Desktop.
Save haudan/8cd7ade3d78cc8456abcf9602d61183a to your computer and use it in GitHub Desktop.
Parser Combinators 2
#![feature(conservative_impl_trait)]
use std::cmp::PartialEq;
type ParseResult<T, I: Iterator<Item = T>> = Result<ParseStatus<T, I>, ParseError>;
#[derive(Debug)]
enum ParseStatus<T, I: Iterator<Item = T>> {
Ok(Vec<T>, I),
NeedMoreData(usize), // # of units needed
}
#[derive(Debug)]
enum ParseError {
InvalidSlice,
}
trait Parser<T, I: Iterator<Item = T>> {
fn parse(&mut self, input: I) -> ParseResult<T, I>;
}
impl<T, I, F> Parser<T, I> for F
where
I: Iterator<Item = T>,
F: Fn(I) -> ParseResult<T, I>,
{
fn parse(&mut self, input: I) -> ParseResult<T, I> {
(*self)(input)
}
}
fn tag<'a, T, I>(tag: &'a [T]) -> impl Parser<T, I>
where
T: PartialEq,
I: Iterator<Item = T>,
{
move |mut input: I| {
let len = tag.len();
let mut parsed = Vec::new();
for i in 0..len {
let v = match input.next() {
Some(ref v) if *v != tag[i] => return Err(ParseError::InvalidSlice),
Some(v) => v,
None => return Ok(ParseStatus::NeedMoreData(len - i)),
};
parsed.push(v);
}
Ok(ParseStatus::Ok(parsed, input))
}
}
fn main() {
let mut tag_parser = tag(&['H', 'e', 'l', 'l', 'o']);
println!("{:?}", tag_parser.parse("Hello world!".chars()));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment