Skip to content

Commit 6dfc3d0

Browse files
committed
refactor(pc): Introducing MapDecorator
Makes parsers that rely on a single underlying parser and only map the successful result of that parser slightly less boilerplate in the implementation. Using a marker trait MapDecoratorMarker to resolve conflicts in blanket trait implementation of Parser.
1 parent ba8c050 commit 6dfc3d0

3 files changed

Lines changed: 61 additions & 14 deletions

File tree

rusty_pc/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ pub mod many;
1515
pub mod many_ctx;
1616
pub mod map;
1717
pub mod map_ctx;
18+
pub mod map_decorator;
1819
pub mod map_err;
1920
pub mod no_context;
2021
mod or;

rusty_pc/src/map.rs

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::map_decorator::{MapDecorator, MapDecoratorMarker};
12
use crate::{InputTrait, Parser};
23

34
pub struct MapParser<P, F> {
@@ -11,23 +12,27 @@ impl<P, F> MapParser<P, F> {
1112
}
1213
}
1314

14-
impl<I, C, P, F, U> Parser<I, C> for MapParser<P, F>
15+
impl<I, C, P, F, U> MapDecorator<I, C> for MapParser<P, F>
1516
where
1617
I: InputTrait,
1718
P: Parser<I, C>,
1819
F: Fn(P::Output) -> U,
1920
{
21+
type OriginalOutput = P::Output;
2022
type Output = U;
2123
type Error = P::Error;
22-
fn parse(&mut self, tokenizer: &mut I) -> Result<Self::Output, Self::Error> {
23-
self.parser.parse(tokenizer).map(&self.mapper)
24+
25+
fn decorated(&mut self) -> &mut impl Parser<I, C, Output = P::Output, Error = P::Error> {
26+
&mut self.parser
2427
}
2528

26-
fn set_context(&mut self, ctx: &C) {
27-
self.parser.set_context(ctx)
29+
fn map_ok(&self, ok: P::Output) -> U {
30+
(self.mapper)(ok)
2831
}
2932
}
3033

34+
impl<P, F> MapDecoratorMarker for MapParser<P, F> {}
35+
3136
/// MapToUnitParser is the same as `.map(|_| ())`.
3237
pub struct MapToUnitParser<P> {
3338
parser: P,
@@ -39,22 +44,20 @@ impl<P> MapToUnitParser<P> {
3944
}
4045
}
4146

42-
impl<I, C, P> Parser<I, C> for MapToUnitParser<P>
47+
impl<I, C, P> MapDecorator<I, C> for MapToUnitParser<P>
4348
where
4449
I: InputTrait,
4550
P: Parser<I, C>,
4651
{
52+
type OriginalOutput = P::Output;
4753
type Output = ();
4854
type Error = P::Error;
4955

50-
fn parse(&mut self, input: &mut I) -> Result<Self::Output, Self::Error> {
51-
match self.parser.parse(input) {
52-
Ok(_) => Ok(()),
53-
Err(err) => Err(err),
54-
}
56+
fn decorated(&mut self) -> &mut impl Parser<I, C, Output = P::Output, Error = P::Error> {
57+
&mut self.parser
5558
}
5659

57-
fn set_context(&mut self, ctx: &C) {
58-
self.parser.set_context(ctx)
59-
}
60+
fn map_ok(&self, _ok: P::Output) {}
6061
}
62+
63+
impl<P> MapDecoratorMarker for MapToUnitParser<P> {}

rusty_pc/src/map_decorator.rs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
use crate::{InputTrait, Parser, ParserErrorTrait};
2+
3+
/// A parser decorator that maps the result of the decorated parser.
4+
pub trait MapDecorator<I, C>
5+
where
6+
I: InputTrait,
7+
{
8+
type OriginalOutput;
9+
type Output;
10+
type Error: ParserErrorTrait;
11+
12+
/// Gets the decorated parser.
13+
fn decorated(
14+
&mut self,
15+
) -> &mut impl Parser<I, C, Output = Self::OriginalOutput, Error = Self::Error>;
16+
17+
/// Maps the successful result of the parser.
18+
fn map_ok(&self, ok: Self::OriginalOutput) -> Self::Output;
19+
}
20+
21+
/// Marker trait for `MapDecorator`.
22+
/// Allows for blanket trait implementation of `Parser`.
23+
pub trait MapDecoratorMarker {}
24+
25+
impl<I, C, D> Parser<I, C> for D
26+
where
27+
I: InputTrait,
28+
D: MapDecoratorMarker + MapDecorator<I, C>,
29+
{
30+
type Output = D::Output;
31+
type Error = D::Error;
32+
33+
fn parse(&mut self, input: &mut I) -> Result<Self::Output, Self::Error> {
34+
match self.decorated().parse(input) {
35+
Ok(ok) => Ok(self.map_ok(ok)),
36+
Err(err) => Err(err),
37+
}
38+
}
39+
40+
fn set_context(&mut self, ctx: &C) {
41+
self.decorated().set_context(ctx)
42+
}
43+
}

0 commit comments

Comments
 (0)