Use ParserInput trait

This commit is contained in:
Greg Shuflin 2022-10-21 16:19:41 -07:00
parent a8370ad216
commit 9198fdd407
6 changed files with 48 additions and 25 deletions

View File

@ -1,10 +1,10 @@
use crate::parser::{ParseResult, Parser};
use crate::parser::{ParseResult, Parser, ParserInput};
pub fn choice2<P1, P2, I, O, E>(parser1: P1, parser2: P2) -> impl Parser<I, O, E>
where
P1: Parser<I, O, E>,
P2: Parser<I, O, E>,
I: Clone,
I: ParserInput + Clone,
{
move |input: I| match parser1.parse(input.clone()) {
ok @ Ok(..) => ok,
@ -15,7 +15,7 @@ where
pub fn choice<C, I, O, E>(choices: C) -> impl Parser<I, O, E>
where
C: Choice<I, O, E>,
I: Clone,
I: ParserInput + Clone,
{
move |input| choices.parse(input)
}
@ -28,7 +28,7 @@ impl<I, O, E, P1, P2> Choice<I, O, E> for (P1, P2)
where
P1: Parser<I, O, E>,
P2: Parser<I, O, E>,
I: Clone,
I: ParserInput + Clone,
{
fn parse(&self, input: I) -> ParseResult<I, O, E> {
let parsers = vec![&self.0 as &dyn Parser<I, O, E>, &self.1];
@ -41,7 +41,7 @@ where
P1: Parser<I, O, E>,
P2: Parser<I, O, E>,
P3: Parser<I, O, E>,
I: Clone,
I: ParserInput + Clone,
{
fn parse(&self, input: I) -> ParseResult<I, O, E> {
let parsers = vec![&self.0 as &dyn Parser<I, O, E>, &self.1, &self.2];
@ -55,7 +55,7 @@ where
P2: Parser<I, O, E>,
P3: Parser<I, O, E>,
P4: Parser<I, O, E>,
I: Clone,
I: ParserInput + Clone,
{
fn parse(&self, input: I) -> ParseResult<I, O, E> {
let parsers = vec![&self.0 as &dyn Parser<I, O, E>, &self.1, &self.2, &self.3];
@ -70,7 +70,7 @@ where
P3: Parser<I, O, E>,
P4: Parser<I, O, E>,
P5: Parser<I, O, E>,
I: Clone,
I: ParserInput + Clone,
{
fn parse(&self, input: I) -> ParseResult<I, O, E> {
let parsers = vec![
@ -92,7 +92,7 @@ where
P4: Parser<I, O, E>,
P5: Parser<I, O, E>,
P6: Parser<I, O, E>,
I: Clone,
I: ParserInput + Clone,
{
fn parse(&self, input: I) -> ParseResult<I, O, E> {
let parsers = vec![
@ -109,7 +109,7 @@ where
fn choice_loop<I, O, E>(input: I, parsers: Vec<&dyn Parser<I, O, E>>) -> ParseResult<I, O, E>
where
I: Clone,
I: ParserInput + Clone,
{
//TODO need a more principled way to return an error when no choices work
let mut err = None;

View File

@ -1,9 +1,9 @@
use crate::parser::{BoxedParser, ParseResult, Parser};
use crate::parser::{BoxedParser, ParseResult, Parser, ParserInput};
pub fn optional<P, I, O, E>(parser: P) -> impl Parser<I, Option<O>, E>
where
P: Parser<I, O, E>,
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<P, F, I, O1, O2, E>(parser: P, map_fn: F) -> impl Parser<I, O2, E>
where
I: ParserInput,
P: Parser<I, O1, E>,
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<u16>,
@ -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, Vec<O>, I> for Repeated<'a, I, O>
where
I: Clone + 'a,
I: ParserInput + Clone + 'a,
{
fn parse(&self, input: I) -> ParseResult<I, Vec<O>, 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, Vec<O>, I> for SeparatedBy<'a, I, O>
where
I: Clone + 'a,
I: ParserInput + Clone + 'a,
{
fn parse(&self, input: I) -> ParseResult<I, Vec<O>, 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<I, O, I> + 'static,
I: Clone + 'static,
I: ParserInput + Clone + 'static,
{
Repeated {
inner_parser: BoxedParser::new(parser),

View File

@ -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 {

View File

@ -3,7 +3,15 @@ use std::rc::Rc;
pub type ParseResult<I, O, E> = Result<(O, I), E>;
pub trait Parser<I, O, E> {
pub trait ParserInput: std::fmt::Debug {}
impl ParserInput for &str {}
impl ParserInput for String {}
pub trait Parser<I, O, E>
where
I: ParserInput,
{
fn parse(&self, input: I) -> ParseResult<I, O, E>;
fn bnf(&self) -> Option<Bnf> {
None
@ -95,11 +103,17 @@ pub trait Parser<I, O, E> {
}
}
pub struct BoxedParser<'a, I, O, E> {
pub struct BoxedParser<'a, I, O, E>
where
I: ParserInput,
{
inner: Box<dyn Parser<I, O, E> + '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<P>(inner: P) -> Self
where
P: Parser<I, O, E> + 'a,
@ -110,13 +124,13 @@ impl<'a, I, O, E> BoxedParser<'a, I, O, E> {
}
}
impl<'a, I, O, E> Parser<I, O, E> for BoxedParser<'a, I, O, E> {
impl<'a, I: ParserInput, O, E> Parser<I, O, E> for BoxedParser<'a, I, O, E> {
fn parse(&self, input: I) -> ParseResult<I, O, E> {
self.inner.parse(input)
}
}
impl<I, O, E, F> Parser<I, O, E> for F
impl<I: ParserInput, O, E, F> Parser<I, O, E> for F
where
F: Fn(I) -> ParseResult<I, O, E>,
{
@ -127,6 +141,7 @@ where
impl<I, O, E, T> Parser<I, O, E> for Rc<T>
where
I: ParserInput,
T: Parser<I, O, E>,
{
fn parse(&self, input: I) -> ParseResult<I, O, E> {

View File

@ -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<P, F, I, O>(parser: P, pred_fn: F) -> impl Parser<I, O, I>
where
I: ParserInput,
P: Parser<I, O, I>,
F: Fn(&O) -> bool,
{

View File

@ -1,7 +1,8 @@
use crate::{ParseResult, Parser};
use crate::{ParseResult, Parser, ParserInput};
pub fn tuple2<P1, P2, I, O1, O2, E>(parser1: P1, parser2: P2) -> impl Parser<I, (O1, O2), E>
where
I: ParserInput,
P1: Parser<I, O1, E>,
P2: Parser<I, O2, E>,
{
@ -10,6 +11,7 @@ where
pub fn seq<T, I, O, E>(sequence: T) -> impl Parser<I, O, E>
where
I: ParserInput,
T: Sequence<I, O, E>,
{
move |input| sequence.parse(input)
@ -26,6 +28,7 @@ pub trait Sequence<I, O, E> {
impl<I, O1, O2, E, P1, P2> Sequence<I, (O1, O2), E> for (P1, P2)
where
I: ParserInput,
P1: Parser<I, O1, E>,
P2: Parser<I, O2, E>,
{
@ -42,6 +45,7 @@ where
impl<I, O1, O2, O3, E, P1, P2, P3> Sequence<I, (O1, O2, O3), E> for (P1, P2, P3)
where
I: ParserInput,
P1: Parser<I, O1, E>,
P2: Parser<I, O2, E>,
P3: Parser<I, O3, E>,
@ -61,6 +65,7 @@ where
impl<I, O1, O2, O3, O4, E, P1, P2, P3, P4> Sequence<I, (O1, O2, O3, O4), E> for (P1, P2, P3, P4)
where
I: ParserInput,
P1: Parser<I, O1, E>,
P2: Parser<I, O2, E>,
P3: Parser<I, O3, E>,
@ -84,6 +89,7 @@ where
impl<I, O1, O2, O3, O4, O5, E, P1, P2, P3, P4, P5> Sequence<I, (O1, O2, O3, O4, O5), E>
for (P1, P2, P3, P4, P5)
where
I: ParserInput,
P1: Parser<I, O1, E>,
P2: Parser<I, O2, E>,
P3: Parser<I, O3, E>,