#![allow(dead_code)] //TODO eventually turn this off type ParseResult = Result<(O, I), E>; trait Parser { fn parse(&self, input: I) -> ParseResult; } impl Parser for F where F: Fn(I) -> ParseResult, { fn parse(&self, input: I) -> ParseResult { self(input) } } fn literal(expected: &'static str) -> impl Fn(&str) -> ParseResult<&str, &str, &str> { move |input| match input.get(0..expected.len()) { Some(next) if next == expected => Ok((next, &input[expected.len()..])), _ => Err(input), } } fn sequence( first: impl Parser, second: impl Parser, ) -> impl Parser { move |input| -> ParseResult { first.parse(input).and_then(|(result1, rest)| { second .parse(rest) .map(|(result2, rest2)| ((result1, result2), rest2)) }) } } fn choice<'a, I, O, E>(parsers: &'a [&'a dyn Parser]) -> impl Parser + 'a where I: Clone, { move |input: I| { //TODO need a more principled way to return an error when no choices work let mut err = None; for parser in parsers.iter() { match parser.parse(input.clone()) { Ok(res) => return Ok(res), Err(e) => { err = Some(e); } } } Err(err.unwrap()) } } #[cfg(test)] mod tests { use super::*; #[test] fn parsing() { let (parsed, rest) = literal("a")("a yolo").unwrap(); assert_eq!(parsed, "a"); assert_eq!(rest, " yolo"); } #[test] fn test_sequence() { let parser = sequence(literal("bongo"), sequence(literal(" "), literal("jonzzz"))); let output = parser.parse("bongo jonzzz").unwrap(); assert_eq!(output.0 .0, "bongo"); assert_eq!(output.0 .1, (" ", "jonzzz")); assert_eq!(output.1, ""); } }