diff --git a/src/lib.rs b/src/lib.rs index f411a62..2807dc3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,35 +1,51 @@ #![feature(assert_matches)] #![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 { +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> { +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(((), &input[expected.len()..])), - _ => Err(input) + Some(next) if next == expected => Ok((expected, &input[expected.len()..])), + _ => Err(input), } } +fn map
(parser: P, map_fn: F) -> impl Parser +where + P: Parser, + F: Fn(O1) -> O2, +{ + move |input| parser.parse(input).map(|(result, rest)| (map_fn(result), rest)) +} + #[cfg(test)] mod tests { use super::*; use std::assert_matches::assert_matches; #[test] - fn parsing() { + fn test_parsing() { let output = literal("a")("a yolo"); - assert_matches!(output.unwrap(), ((), " yolo")); + assert_matches!(output.unwrap(), ("a", " yolo")); + } + + #[test] + fn test_map() { + let lit_a = literal("a"); + let output = map(lit_a, |s| s.to_uppercase()).parse("a yolo"); + assert_matches!(output.unwrap(), (s, " yolo") if s == "A"); } }