Use ParserInput trait
This commit is contained in:
parent
a8370ad216
commit
9198fdd407
@ -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;
|
||||
|
@ -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),
|
||||
|
@ -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 {
|
||||
|
@ -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> {
|
||||
|
@ -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,
|
||||
{
|
||||
|
@ -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>,
|
||||
|
Loading…
Reference in New Issue
Block a user