diff --git a/src/parser.rs b/src/parser.rs index 3a79563..1675d63 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -1,9 +1,14 @@ +use std::marker::PhantomData; + use crate::{map, seq2, surrounded_by}; pub type ParseResult = Result<(O, I), (E, I)>; pub trait Parser { fn parse(&self, input: I) -> ParseResult; + fn name(&self) -> Option { + None + } } impl Parser for F @@ -15,6 +20,28 @@ where } } +pub struct NamedParser +where + P: Parser, +{ + inner: P, + name: String, + phantom: PhantomData<(I, O, E)>, +} + +impl Parser for NamedParser +where + P: Parser, +{ + fn parse(&self, input: I) -> ParseResult { + self.inner.parse(input) + } + + fn name(&self) -> Option { + Some(self.name.clone()) + } +} + pub trait ParserExtension: Parser { fn map(self, map_fn: F) -> impl Parser where @@ -25,6 +52,16 @@ pub trait ParserExtension: Parser { fn then_ignore>(self, next: P) -> impl Parser; fn ignore_then>(self, next: P) -> impl Parser; fn surrounded_by(self, surrounding: impl Parser) -> impl Parser; + fn to_named(self, name: &str) -> NamedParser + where + Self: Sized, + { + NamedParser { + inner: self, + name: name.to_string(), + phantom: PhantomData, + } + } } impl ParserExtension for T diff --git a/src/test/mod.rs b/src/test/mod.rs index e0cdbcc..9d5a67f 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -73,3 +73,9 @@ fn test_repeated() { assert_eq!(output.0.len(), 0); assert_eq!(output.1, "tra la la"); } + +#[test] +fn test_named_parser() { + let parser = literal("yokel").to_named("yokelparser"); + assert_eq!(parser.name(), Some("yokelparser".to_string())); +}