Mercurial > lbo > hg > rcombinators
changeset 6:7873119002f7
Implement Transform combinator.
author | Lewin Bormann <lewin@lewin-bormann.info> |
---|---|
date | Thu, 30 May 2019 14:27:11 +0200 |
parents | fe1259c95911 |
children | 1f30f2d25d5e |
files | src/combinators.rs src/parser.rs |
diffstat | 2 files changed, 31 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/src/combinators.rs Thu May 30 14:10:26 2019 +0200 +++ b/src/combinators.rs Thu May 30 14:27:11 2019 +0200 @@ -1,6 +1,32 @@ use crate::parser::{ParseError, ParseResult, Parser}; use crate::state::ParseState; +/// Transform applies a function (which may fail) to the result of a parser. Transform only +/// succeeds if the applied function succeeds, too. +pub struct Transform<R, R2, P: Parser<Result = R>, F: Fn(R) -> ParseResult<R2>> { + f: F, + p: P, +} + +impl<R, R2, P: Parser<Result = R>, F: Fn(R) -> ParseResult<R2>> Transform<R, R2, P, F> { + pub fn new(p: P, f: F) -> Transform<R, R2, P, F> { + Transform { f: f, p: p } + } +} + +impl<R, R2, P: Parser<Result = R>, F: Fn(R) -> ParseResult<R2>> Parser for Transform<R, R2, P, F> { + type Result = R2; + fn parse( + &mut self, + st: &mut ParseState<impl Iterator<Item = char>>, + ) -> ParseResult<Self::Result> { + match self.p.parse(st) { + Ok(o) => (self.f)(o), + Err(e) => Err(e), + } + } +} + pub struct Alternative<T>(T); impl<T> Alternative<T> { @@ -189,9 +215,11 @@ StringParser::new("ab"), StringParser::new("de"), StringParser::new(" "), + Transform::new(Int, |i| Ok(i.to_string())), )); let mut ps = ParseState::new("de 34"); assert_eq!(Ok("de".to_string()), p.parse(&mut ps)); assert_eq!(Ok(" ".to_string()), p.parse(&mut ps)); + assert_eq!(Ok("34".to_string()), p.parse(&mut ps)); } }
--- a/src/parser.rs Thu May 30 14:10:26 2019 +0200 +++ b/src/parser.rs Thu May 30 14:27:11 2019 +0200 @@ -6,6 +6,8 @@ pub enum ParseError { EOF, Fail(&'static str, usize), + /// Error during application of Transform. + TransformFail(&'static str, usize), } impl fmt::Display for ParseError { @@ -13,6 +15,7 @@ match self { ParseError::EOF => f.write_str("EOF"), ParseError::Fail(s, pos) => write!(f, "Parse fail: {} at {}", s, pos), + ParseError::TransformFail(s, pos) => write!(f, "Transform fail: {} at {}", s, pos), } } }