Put Parser in separate module
This commit is contained in:
parent
a9f2d4d771
commit
364ddeac00
87
src/lib.rs
87
src/lib.rs
@ -1,93 +1,10 @@
|
|||||||
#![feature(assert_matches)]
|
#![feature(assert_matches)]
|
||||||
#![allow(dead_code)] //TODO eventually turn this off
|
#![allow(dead_code)] //TODO eventually turn this off
|
||||||
mod bnf;
|
mod bnf;
|
||||||
|
mod parser;
|
||||||
mod sequence;
|
mod sequence;
|
||||||
|
|
||||||
use bnf::Bnf;
|
use parser::{ParseResult, Parser};
|
||||||
use std::rc::Rc;
|
|
||||||
|
|
||||||
pub type ParseResult<I, O, E> = Result<(O, I), E>;
|
|
||||||
|
|
||||||
pub trait Parser<I, O, E> {
|
|
||||||
fn parse(&self, input: I) -> ParseResult<I, O, E>;
|
|
||||||
fn bnf(&self) -> Option<Bnf> {
|
|
||||||
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<I, O2, E> + 'a,
|
|
||||||
{
|
|
||||||
BoxedParser::new(sequence::tuple2(self, next_parser))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct BoxedParser<'a, I, O, E> {
|
|
||||||
inner: Box<dyn Parser<I, O, E> + 'a>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, I, O, E> BoxedParser<'a, I, O, E> {
|
|
||||||
fn new<P>(inner: P) -> Self
|
|
||||||
where
|
|
||||||
P: Parser<I, O, E> + 'a,
|
|
||||||
{
|
|
||||||
BoxedParser {
|
|
||||||
inner: Box::new(inner),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, I, 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
|
|
||||||
where
|
|
||||||
F: Fn(I) -> ParseResult<I, O, E>,
|
|
||||||
{
|
|
||||||
fn parse(&self, input: I) -> ParseResult<I, O, E> {
|
|
||||||
self(input)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<I, O, E, T> Parser<I, O, E> for Rc<T>
|
|
||||||
where
|
|
||||||
T: Parser<I, O, E>,
|
|
||||||
{
|
|
||||||
fn parse(&self, input: I) -> ParseResult<I, O, E> {
|
|
||||||
self.as_ref().parse(input)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn literal(expected: &'static str) -> impl Fn(&str) -> ParseResult<&str, &str, &str> {
|
fn literal(expected: &'static str) -> impl Fn(&str) -> ParseResult<&str, &str, &str> {
|
||||||
move |input| match input.get(0..expected.len()) {
|
move |input| match input.get(0..expected.len()) {
|
||||||
|
85
src/parser.rs
Normal file
85
src/parser.rs
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
use crate::bnf::Bnf;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
pub type ParseResult<I, O, E> = Result<(O, I), E>;
|
||||||
|
|
||||||
|
pub trait Parser<I, O, E> {
|
||||||
|
fn parse(&self, input: I) -> ParseResult<I, O, E>;
|
||||||
|
fn bnf(&self) -> Option<Bnf> {
|
||||||
|
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<I, O2, E> + 'a,
|
||||||
|
{
|
||||||
|
BoxedParser::new(crate::sequence::tuple2(self, next_parser))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct BoxedParser<'a, I, O, E> {
|
||||||
|
inner: Box<dyn Parser<I, O, E> + 'a>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, I, O, E> BoxedParser<'a, I, O, E> {
|
||||||
|
fn new<P>(inner: P) -> Self
|
||||||
|
where
|
||||||
|
P: Parser<I, O, E> + 'a,
|
||||||
|
{
|
||||||
|
BoxedParser {
|
||||||
|
inner: Box::new(inner),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, I, 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
|
||||||
|
where
|
||||||
|
F: Fn(I) -> ParseResult<I, O, E>,
|
||||||
|
{
|
||||||
|
fn parse(&self, input: I) -> ParseResult<I, O, E> {
|
||||||
|
self(input)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<I, O, E, T> Parser<I, O, E> for Rc<T>
|
||||||
|
where
|
||||||
|
T: Parser<I, O, E>,
|
||||||
|
{
|
||||||
|
fn parse(&self, input: I) -> ParseResult<I, O, E> {
|
||||||
|
self.as_ref().parse(input)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user