diff --git a/src/lib.rs b/src/lib.rs index 7a0fb80..89ed7e9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,93 +1,10 @@ #![feature(assert_matches)] #![allow(dead_code)] //TODO eventually turn this off mod bnf; +mod parser; mod sequence; -use bnf::Bnf; -use std::rc::Rc; - -pub type ParseResult = Result<(O, I), E>; - -pub trait Parser { - fn parse(&self, input: I) -> ParseResult; - fn bnf(&self) -> Option { - None - } - - fn map<'a, F, O2>(self, map_fn: F) -> BoxedParser<'a, I, O2, E> - where - Self: Sized + 'a, - I: 'a, - E: 'a, - O: 'a, - O2: 'a, - F: Fn(O) -> O2 + 'a, - { - BoxedParser::new(map(self, map_fn)) - } - - fn to<'a, O2>(self, item: O2) -> BoxedParser<'a, I, O2, E> - where - Self: Sized + 'a, - I: 'a, - O: 'a, - O2: Clone + 'a, - E: 'a, - { - self.map(move |_| item.clone()) - } - - fn then<'a, P, O2>(self, next_parser: P) -> BoxedParser<'a, I, (O, O2), E> - where - Self: Sized + 'a, - I: 'a, - O: 'a, - O2: 'a, - E: 'a, - P: Parser + 'a, - { - BoxedParser::new(sequence::tuple2(self, next_parser)) - } -} - -pub struct BoxedParser<'a, I, O, E> { - inner: Box + 'a>, -} - -impl<'a, I, O, E> BoxedParser<'a, I, O, E> { - fn new

(inner: P) -> Self - where - P: Parser + 'a, - { - BoxedParser { - inner: Box::new(inner), - } - } -} - -impl<'a, I, O, E> Parser for BoxedParser<'a, I, O, E> { - fn parse(&self, input: I) -> ParseResult { - self.inner.parse(input) - } -} - -impl Parser for F -where - F: Fn(I) -> ParseResult, -{ - fn parse(&self, input: I) -> ParseResult { - self(input) - } -} - -impl Parser for Rc -where - T: Parser, -{ - fn parse(&self, input: I) -> ParseResult { - self.as_ref().parse(input) - } -} +use parser::{ParseResult, Parser}; fn literal(expected: &'static str) -> impl Fn(&str) -> ParseResult<&str, &str, &str> { move |input| match input.get(0..expected.len()) { diff --git a/src/parser.rs b/src/parser.rs new file mode 100644 index 0000000..87d0bad --- /dev/null +++ b/src/parser.rs @@ -0,0 +1,85 @@ +use crate::bnf::Bnf; +use std::rc::Rc; + +pub type ParseResult = Result<(O, I), E>; + +pub trait Parser { + fn parse(&self, input: I) -> ParseResult; + fn bnf(&self) -> Option { + None + } + + fn map<'a, F, O2>(self, map_fn: F) -> BoxedParser<'a, I, O2, E> + where + Self: Sized + 'a, + I: 'a, + E: 'a, + O: 'a, + O2: 'a, + F: Fn(O) -> O2 + 'a, + { + BoxedParser::new(crate::map(self, map_fn)) + } + + fn to<'a, O2>(self, item: O2) -> BoxedParser<'a, I, O2, E> + where + Self: Sized + 'a, + I: 'a, + O: 'a, + O2: Clone + 'a, + E: 'a, + { + self.map(move |_| item.clone()) + } + + fn then<'a, P, O2>(self, next_parser: P) -> BoxedParser<'a, I, (O, O2), E> + where + Self: Sized + 'a, + I: 'a, + O: 'a, + O2: 'a, + E: 'a, + P: Parser + 'a, + { + BoxedParser::new(crate::sequence::tuple2(self, next_parser)) + } +} + +pub struct BoxedParser<'a, I, O, E> { + inner: Box + 'a>, +} + +impl<'a, I, O, E> BoxedParser<'a, I, O, E> { + fn new

(inner: P) -> Self + where + P: Parser + 'a, + { + BoxedParser { + inner: Box::new(inner), + } + } +} + +impl<'a, I, O, E> Parser for BoxedParser<'a, I, O, E> { + fn parse(&self, input: I) -> ParseResult { + self.inner.parse(input) + } +} + +impl Parser for F +where + F: Fn(I) -> ParseResult, +{ + fn parse(&self, input: I) -> ParseResult { + self(input) + } +} + +impl Parser for Rc +where + T: Parser, +{ + fn parse(&self, input: I) -> ParseResult { + self.as_ref().parse(input) + } +}