From 9198fdd407053042279ddfac1e1cf14b1bc8563b Mon Sep 17 00:00:00 2001 From: Greg Shuflin Date: Fri, 21 Oct 2022 16:19:41 -0700 Subject: [PATCH] Use ParserInput trait --- src/choice.rs | 18 +++++++++--------- src/combinators.rs | 17 +++++++++-------- src/lib.rs | 2 +- src/parser.rs | 25 ++++++++++++++++++++----- src/primitives.rs | 3 ++- src/sequence.rs | 8 +++++++- 6 files changed, 48 insertions(+), 25 deletions(-) diff --git a/src/choice.rs b/src/choice.rs index fb2cd16..781a3b8 100644 --- a/src/choice.rs +++ b/src/choice.rs @@ -1,10 +1,10 @@ -use crate::parser::{ParseResult, Parser}; +use crate::parser::{ParseResult, Parser, ParserInput}; pub fn choice2(parser1: P1, parser2: P2) -> impl Parser where P1: Parser, P2: Parser, - I: Clone, + I: ParserInput + Clone, { move |input: I| match parser1.parse(input.clone()) { ok @ Ok(..) => ok, @@ -15,7 +15,7 @@ where pub fn choice(choices: C) -> impl Parser where C: Choice, - I: Clone, + I: ParserInput + Clone, { move |input| choices.parse(input) } @@ -28,7 +28,7 @@ impl Choice for (P1, P2) where P1: Parser, P2: Parser, - I: Clone, + I: ParserInput + Clone, { fn parse(&self, input: I) -> ParseResult { let parsers = vec![&self.0 as &dyn Parser, &self.1]; @@ -41,7 +41,7 @@ where P1: Parser, P2: Parser, P3: Parser, - I: Clone, + I: ParserInput + Clone, { fn parse(&self, input: I) -> ParseResult { let parsers = vec![&self.0 as &dyn Parser, &self.1, &self.2]; @@ -55,7 +55,7 @@ where P2: Parser, P3: Parser, P4: Parser, - I: Clone, + I: ParserInput + Clone, { fn parse(&self, input: I) -> ParseResult { let parsers = vec![&self.0 as &dyn Parser, &self.1, &self.2, &self.3]; @@ -70,7 +70,7 @@ where P3: Parser, P4: Parser, P5: Parser, - I: Clone, + I: ParserInput + Clone, { fn parse(&self, input: I) -> ParseResult { let parsers = vec![ @@ -92,7 +92,7 @@ where P4: Parser, P5: Parser, P6: Parser, - I: Clone, + I: ParserInput + Clone, { fn parse(&self, input: I) -> ParseResult { let parsers = vec![ @@ -109,7 +109,7 @@ where fn choice_loop(input: I, parsers: Vec<&dyn Parser>) -> ParseResult where - I: Clone, + I: ParserInput + Clone, { //TODO need a more principled way to return an error when no choices work let mut err = None; diff --git a/src/combinators.rs b/src/combinators.rs index e0f7fc5..6ea5292 100644 --- a/src/combinators.rs +++ b/src/combinators.rs @@ -1,9 +1,9 @@ -use crate::parser::{BoxedParser, ParseResult, Parser}; +use crate::parser::{BoxedParser, ParseResult, Parser, ParserInput}; pub fn optional(parser: P) -> impl Parser, E> where P: Parser, - I: Clone, + I: ParserInput + Clone, { move |input: I| match parser.parse(input.clone()) { Ok((output, rest)) => Ok((Some(output), rest)), @@ -13,6 +13,7 @@ where pub fn map(parser: P, map_fn: F) -> impl Parser where + I: ParserInput, P: Parser, F: Fn(O1) -> O2, { @@ -25,7 +26,7 @@ where pub struct Repeated<'a, I, O> where - I: Clone, + I: ParserInput + Clone, { inner_parser: BoxedParser<'a, I, O, I>, at_least: Option, @@ -34,7 +35,7 @@ where impl<'a, I, O> Repeated<'a, I, O> where - I: Clone, + I: ParserInput + Clone, { pub fn at_least(self, n: u16) -> Self { Self { @@ -65,7 +66,7 @@ where impl<'a, I, O> Parser, I> for Repeated<'a, I, O> where - I: Clone + 'a, + I: ParserInput + Clone + 'a, { fn parse(&self, input: I) -> ParseResult, I> { let at_least = self.at_least.unwrap_or(0); @@ -97,7 +98,7 @@ where pub struct SeparatedBy<'a, I, O> where - I: Clone, + I: ParserInput + Clone, { inner_repeated: Repeated<'a, I, O>, delimiter: BoxedParser<'a, I, (), I>, @@ -106,7 +107,7 @@ where impl<'a, I, O> Parser, I> for SeparatedBy<'a, I, O> where - I: Clone + 'a, + I: ParserInput + Clone + 'a, { fn parse(&self, input: I) -> ParseResult, I> { let at_least = self.inner_repeated.at_least.unwrap_or(0); @@ -176,7 +177,7 @@ where pub fn repeated<'a, P, I, O>(parser: P) -> Repeated<'a, I, O> where P: Parser + 'static, - I: Clone + 'static, + I: ParserInput + Clone + 'static, { Repeated { inner_parser: BoxedParser::new(parser), diff --git a/src/lib.rs b/src/lib.rs index 8d726df..ab750fe 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,7 +6,7 @@ mod parser; mod primitives; mod sequence; -pub use parser::{ParseResult, Parser}; +pub use parser::{ParseResult, Parser, ParserInput}; #[cfg(test)] mod tests { diff --git a/src/parser.rs b/src/parser.rs index c68fda0..1ac465e 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -3,7 +3,15 @@ use std::rc::Rc; pub type ParseResult = Result<(O, I), E>; -pub trait Parser { +pub trait ParserInput: std::fmt::Debug {} + +impl ParserInput for &str {} +impl ParserInput for String {} + +pub trait Parser +where + I: ParserInput, +{ fn parse(&self, input: I) -> ParseResult; fn bnf(&self) -> Option { None @@ -95,11 +103,17 @@ pub trait Parser { } } -pub struct BoxedParser<'a, I, O, E> { +pub struct BoxedParser<'a, I, O, E> +where + I: ParserInput, +{ inner: Box + 'a>, } -impl<'a, I, O, E> BoxedParser<'a, I, O, E> { +impl<'a, I, O, E> BoxedParser<'a, I, O, E> +where + I: ParserInput, +{ pub(crate) fn new

(inner: P) -> Self where P: Parser + 'a, @@ -110,13 +124,13 @@ impl<'a, I, O, E> BoxedParser<'a, I, O, E> { } } -impl<'a, I, O, E> Parser for BoxedParser<'a, I, O, E> { +impl<'a, I: ParserInput, O, E> Parser for BoxedParser<'a, I, O, E> { fn parse(&self, input: I) -> ParseResult { self.inner.parse(input) } } -impl Parser for F +impl Parser for F where F: Fn(I) -> ParseResult, { @@ -127,6 +141,7 @@ where impl Parser for Rc where + I: ParserInput, T: Parser, { fn parse(&self, input: I) -> ParseResult { diff --git a/src/primitives.rs b/src/primitives.rs index b322b81..c280b41 100644 --- a/src/primitives.rs +++ b/src/primitives.rs @@ -1,4 +1,4 @@ -use crate::parser::{ParseResult, Parser}; +use crate::parser::{ParseResult, Parser, ParserInput}; pub fn literal_char(expected: char) -> impl Fn(&str) -> ParseResult<&str, char, &str> { move |input| match input.chars().next() { @@ -35,6 +35,7 @@ pub fn one_of<'a>(items: &'static str) -> impl Parser<&'a str, &'a str, &'a str> pub fn pred(parser: P, pred_fn: F) -> impl Parser where + I: ParserInput, P: Parser, F: Fn(&O) -> bool, { diff --git a/src/sequence.rs b/src/sequence.rs index 5e7000c..2c8c3de 100644 --- a/src/sequence.rs +++ b/src/sequence.rs @@ -1,7 +1,8 @@ -use crate::{ParseResult, Parser}; +use crate::{ParseResult, Parser, ParserInput}; pub fn tuple2(parser1: P1, parser2: P2) -> impl Parser where + I: ParserInput, P1: Parser, P2: Parser, { @@ -10,6 +11,7 @@ where pub fn seq(sequence: T) -> impl Parser where + I: ParserInput, T: Sequence, { move |input| sequence.parse(input) @@ -26,6 +28,7 @@ pub trait Sequence { impl Sequence for (P1, P2) where + I: ParserInput, P1: Parser, P2: Parser, { @@ -42,6 +45,7 @@ where impl Sequence for (P1, P2, P3) where + I: ParserInput, P1: Parser, P2: Parser, P3: Parser, @@ -61,6 +65,7 @@ where impl Sequence for (P1, P2, P3, P4) where + I: ParserInput, P1: Parser, P2: Parser, P3: Parser, @@ -84,6 +89,7 @@ where impl Sequence for (P1, P2, P3, P4, P5) where + I: ParserInput, P1: Parser, P2: Parser, P3: Parser,