diff --git a/src/bnf.rs b/src/bnf.rs index 20f9dc6..4de5862 100644 --- a/src/bnf.rs +++ b/src/bnf.rs @@ -1,4 +1,6 @@ -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq)] pub enum Bnf { Production, + Choice(Vec), + Unknown, } diff --git a/src/choice/mod.rs b/src/choice/mod.rs index 781a3b8..f3ff6a3 100644 --- a/src/choice/mod.rs +++ b/src/choice/mod.rs @@ -1,3 +1,4 @@ +use crate::bnf::Bnf; use crate::parser::{ParseResult, Parser, ParserInput}; pub fn choice2(parser1: P1, parser2: P2) -> impl Parser @@ -12,16 +13,19 @@ where } } -pub fn choice(choices: C) -> impl Parser +pub fn choice(choices: C) -> (impl Parser, Bnf) where C: Choice, I: ParserInput + Clone, { - move |input| choices.parse(input) + let bnf = choices.bnf(); + (move |input| choices.parse(input), bnf) } pub trait Choice { fn parse(&self, input: I) -> ParseResult; + + fn bnf(&self) -> Bnf; } impl Choice for (P1, P2) @@ -34,6 +38,16 @@ where let parsers = vec![&self.0 as &dyn Parser, &self.1]; choice_loop(input, parsers) } + + fn bnf(&self) -> Bnf { + let parsers = vec![&self.0 as &dyn Parser, &self.1]; + Bnf::Choice( + parsers + .into_iter() + .map(|p| p.bnf().unwrap_or(Bnf::Unknown)) + .collect(), + ) + } } impl Choice for (P1, P2, P3) @@ -47,6 +61,16 @@ where let parsers = vec![&self.0 as &dyn Parser, &self.1, &self.2]; choice_loop(input, parsers) } + + fn bnf(&self) -> Bnf { + let parsers = vec![&self.0 as &dyn Parser, &self.1, &self.2]; + Bnf::Choice( + parsers + .into_iter() + .map(|p| p.bnf().unwrap_or(Bnf::Unknown)) + .collect(), + ) + } } impl Choice for (P1, P2, P3, P4) @@ -61,6 +85,16 @@ where let parsers = vec![&self.0 as &dyn Parser, &self.1, &self.2, &self.3]; choice_loop(input, parsers) } + + fn bnf(&self) -> Bnf { + let parsers = vec![&self.0 as &dyn Parser, &self.1, &self.2, &self.3]; + Bnf::Choice( + parsers + .into_iter() + .map(|p| p.bnf().unwrap_or(Bnf::Unknown)) + .collect(), + ) + } } impl Choice for (P1, P2, P3, P4, P5) @@ -82,6 +116,22 @@ where ]; choice_loop(input, parsers) } + + fn bnf(&self) -> Bnf { + let parsers = vec![ + &self.0 as &dyn Parser, + &self.1, + &self.2, + &self.3, + &self.4, + ]; + Bnf::Choice( + parsers + .into_iter() + .map(|p| p.bnf().unwrap_or(Bnf::Unknown)) + .collect(), + ) + } } impl Choice for (P1, P2, P3, P4, P5, P6) @@ -105,6 +155,23 @@ where ]; choice_loop(input, parsers) } + + fn bnf(&self) -> Bnf { + let parsers = vec![ + &self.0 as &dyn Parser, + &self.1, + &self.2, + &self.3, + &self.4, + &self.5, + ]; + Bnf::Choice( + parsers + .into_iter() + .map(|p| p.bnf().unwrap_or(Bnf::Unknown)) + .collect(), + ) + } } fn choice_loop(input: I, parsers: Vec<&dyn Parser>) -> ParseResult diff --git a/src/lib.rs b/src/lib.rs index f172bc1..acc8164 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,6 +5,8 @@ mod parser; pub mod primitives; pub mod sequence; +#[cfg(test)] +use bnf::Bnf; pub use parser::{ParseResult, Parser, ParserInput}; #[cfg(test)] @@ -221,4 +223,10 @@ mod tests { let parsed_json = json_object().parse(test_json); assert!(parsed_json.is_ok()); } + + #[test] + fn bnf_representation() { + let bnf = json_object().bnf().unwrap(); + assert_eq!(bnf, Bnf::Production); + } } diff --git a/src/parser/boxed_parser.rs b/src/parser/boxed_parser.rs index a3b3e68..d759a8b 100644 --- a/src/parser/boxed_parser.rs +++ b/src/parser/boxed_parser.rs @@ -20,7 +20,6 @@ where inner: Box::new(inner), } } - } impl<'a, I: ParserInput, O, E> Parser for BoxedParser<'a, I, O, E> { @@ -32,7 +31,10 @@ impl<'a, I: ParserInput, O, E> Parser for BoxedParser<'a, I, O, E> { self.inner.bnf() } - fn boxed<'b>(self) -> BoxedParser<'b, I, O, E> where Self: Sized + 'b { + fn boxed<'b>(self) -> BoxedParser<'b, I, O, E> + where + Self: Sized + 'b, + { self } } diff --git a/src/parser/mod.rs b/src/parser/mod.rs index dea519b..13397ca 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -23,7 +23,10 @@ where None } - fn boxed<'a>(self) -> BoxedParser<'a, I, O, E> where Self: Sized + 'a { + fn boxed<'a>(self) -> BoxedParser<'a, I, O, E> + where + Self: Sized + 'a, + { BoxedParser::new(self) } @@ -71,8 +74,7 @@ where E: 'a, P: Parser + 'a, { - crate::sequence::tuple2(self, next_parser) - .map(|(_, next_output)| next_output) + crate::sequence::tuple2(self, next_parser).map(|(_, next_output)| next_output) } fn then_ignore<'a, P, O2>(self, next_parser: P) -> BoxedParser<'a, I, O, E> @@ -84,8 +86,7 @@ where E: 'a, P: Parser + 'a, { - crate::sequence::tuple2(self, next_parser) - .map(|(this_output, _)| this_output) + crate::sequence::tuple2(self, next_parser).map(|(this_output, _)| this_output) } fn delimited<'a, P1, O1, P2, O2>(self, left: P1, right: P2) -> BoxedParser<'a, I, O, E> @@ -149,12 +150,12 @@ where } } -impl Parser for (F, Bnf) +impl Parser for (P, Bnf) where - F: Fn(I) -> ParseResult, + P: Parser, { fn parse(&self, input: I) -> ParseResult { - self.0(input) + self.0.parse(input) } fn bnf(&self) -> Option {