feat: and run and and_then parser.
This commit is contained in:
@@ -261,13 +261,68 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub struct RunParser<P, F> {
|
||||
pub(crate) parser: P,
|
||||
pub(crate) action: F,
|
||||
}
|
||||
|
||||
impl<'a, TToken, T: 'a, TContext, P, F> Parser<'a, TToken, T, TContext> for RunParser<P, F>
|
||||
where
|
||||
TToken: Debug + Clone,
|
||||
P: Parser<'a, TToken, T, TContext>,
|
||||
F: Fn(&T) -> (),
|
||||
{
|
||||
fn parse(
|
||||
&self,
|
||||
context: Rc<RefCell<ParserContext<TToken, TContext>>>,
|
||||
input: &'a [TToken],
|
||||
) -> ParserResult<'a, TToken, T> {
|
||||
match self.parser.parse(context, input) {
|
||||
Ok(r) => {
|
||||
(self.action)(&r.1);
|
||||
|
||||
Ok(r)
|
||||
}
|
||||
r => r,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct AndThenParser<P, F, T> {
|
||||
pub(crate) parser: P,
|
||||
pub(crate) mapper: F,
|
||||
pub(crate) phantom_data: PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<'a, TToken, T: 'a, TResult: 'a, TContext, P, F> Parser<'a, TToken, TResult, TContext>
|
||||
for AndThenParser<P, F, T>
|
||||
where
|
||||
TToken: Debug + Clone,
|
||||
P: Parser<'a, TToken, T, TContext>,
|
||||
F: Fn(T) -> anyhow::Result<TResult>,
|
||||
{
|
||||
fn parse(
|
||||
&self,
|
||||
context: Rc<RefCell<ParserContext<TToken, TContext>>>,
|
||||
input: &'a [TToken],
|
||||
) -> ParserResult<'a, TToken, TResult> {
|
||||
match self.parser.parse(context, input) {
|
||||
Ok((i, r)) => match (self.mapper)(r) {
|
||||
Ok(result) => Ok((i, result)),
|
||||
Err(err) => Err(FailedParserResult::new_with_error(i, err)),
|
||||
},
|
||||
Err(r) => Err(r),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::parser::{
|
||||
failed_parser_test_helper, parser_test_helper, satisfy, take, FailedParserResult,
|
||||
};
|
||||
use crate::text::char_parser;
|
||||
use crate::text::{char_parser, char_satisfy};
|
||||
|
||||
#[test]
|
||||
fn map_test() {
|
||||
@@ -447,4 +502,23 @@ mod test {
|
||||
char_parser('a').optional().parse(c, i)
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn run_test() {
|
||||
parser_test_helper(ParserContext::new_with_str("abc", ()), &'a', |c, i| {
|
||||
char_parser('a').run(|c| assert_eq!(c, &'a')).parse(c, i)
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn and_then_test() {
|
||||
parser_test_helper(ParserContext::new_with_str("123", ()), &1, |c, i| {
|
||||
char_satisfy(char::is_ascii_digit)
|
||||
.and_then(|c| {
|
||||
let word = c.to_string();
|
||||
Ok(i32::from_str_radix(word.as_str(), 10)?)
|
||||
})
|
||||
.parse(c, i)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user