add: TryParser and SatifiedMapParser.
This commit is contained in:
parent
dd00a37369
commit
814ab29cb6
|
@ -3,11 +3,11 @@ mod primitive_parsers;
|
|||
|
||||
use crate::parser::modified_parsers::{
|
||||
BindParser, ConvertParser, LitervalCountParser, LitervalParser, LookAheadParser, MapParser,
|
||||
NextParser, ReverseParser,
|
||||
NextParser, ReverseParser, TryParser,
|
||||
};
|
||||
use crate::parser::primitive_parsers::{
|
||||
AnyParser, FailParser, FailWithMessageParser, SatisfyParser, SkipParser, SucceedParser,
|
||||
TakeParser,
|
||||
AnyParser, FailParser, FailWithMessageParser, SatifiedMapParser, SatisfyParser, SkipParser,
|
||||
SucceedParser, TakeParser,
|
||||
};
|
||||
use std::cell::RefCell;
|
||||
use std::error::Error;
|
||||
|
@ -178,6 +178,17 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
fn try_parse(self, result: T) -> TryParser<Self, T>
|
||||
where
|
||||
Self: Sized,
|
||||
T: Clone,
|
||||
{
|
||||
TryParser {
|
||||
parser: self,
|
||||
result,
|
||||
}
|
||||
}
|
||||
|
||||
fn reverse<TResult>(self, result: TResult) -> ReverseParser<Self, T, TResult>
|
||||
where
|
||||
Self: Sized,
|
||||
|
@ -259,6 +270,16 @@ where
|
|||
SatisfyParser { predicate }
|
||||
}
|
||||
|
||||
pub fn satified_map<'a, TToken, TContext, T: 'a, F>(
|
||||
mapper: F,
|
||||
) -> impl Parser<'a, TToken, T, TContext>
|
||||
where
|
||||
TToken: Debug + Clone,
|
||||
F: Fn(&TToken) -> Option<T>,
|
||||
{
|
||||
SatifiedMapParser { mapper }
|
||||
}
|
||||
|
||||
pub fn any<'a, TToken, TContext>() -> impl Parser<'a, TToken, TToken, TContext>
|
||||
where
|
||||
TToken: Debug + Clone + 'a,
|
||||
|
|
|
@ -189,6 +189,29 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
pub struct TryParser<P, T> {
|
||||
pub(crate) parser: P,
|
||||
pub(crate) result: T,
|
||||
}
|
||||
|
||||
impl<'a, TToken, T, TContext, P> Parser<'a, TToken, T, TContext> for TryParser<P, T>
|
||||
where
|
||||
TToken: Debug + Clone,
|
||||
T: Clone + 'a,
|
||||
P: Parser<'a, TToken, T, TContext>,
|
||||
{
|
||||
fn parse(
|
||||
&self,
|
||||
context: Rc<RefCell<ParserContext<TToken, TContext>>>,
|
||||
input: &'a [TToken],
|
||||
) -> ParserResult<'a, TToken, T> {
|
||||
match self.parser.parse(context, input) {
|
||||
Err(r) => Ok((r.input, self.result.clone())),
|
||||
r => r,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ReverseParser<P, T, TResult> {
|
||||
pub(crate) parser: P,
|
||||
pub(crate) result: TResult,
|
||||
|
@ -370,6 +393,17 @@ mod test {
|
|||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn try_parse_test() {
|
||||
parser_test_helper(ParserContext::new_with_str("abc", ()), &'a', |c, i| {
|
||||
char_parser('a').try_parse('a').parse(c, i)
|
||||
});
|
||||
|
||||
parser_test_helper(ParserContext::new_with_str("bc", ()), &'a', |c, i| {
|
||||
char_parser('a').try_parse('a').parse(c, i)
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn reverse_test() {
|
||||
parser_test_helper(ParserContext::new_with_str("abc", ()), &(), |c, i| {
|
||||
|
|
|
@ -86,6 +86,32 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
pub struct SatifiedMapParser<F> {
|
||||
pub(crate) mapper: F,
|
||||
}
|
||||
|
||||
impl<'a, TToken, TContext, T: 'a, F> Parser<'a, TToken, T, TContext> for SatifiedMapParser<F>
|
||||
where
|
||||
TToken: Debug + Clone,
|
||||
F: Fn(&TToken) -> Option<T>,
|
||||
{
|
||||
fn parse(
|
||||
&self,
|
||||
_: Rc<RefCell<ParserContext<TToken, TContext>>>,
|
||||
input: &'a [TToken],
|
||||
) -> ParserResult<'a, TToken, T> {
|
||||
if input.is_empty() {
|
||||
return Err(FailedParserResult::new_with_str(input, "Input is empty"));
|
||||
}
|
||||
|
||||
if let Some(result) = (self.mapper)(&input[0]) {
|
||||
Ok((&input[1..], result))
|
||||
} else {
|
||||
Err(FailedParserResult::new_with_str(input, "Predicate failed."))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct AnyParser {}
|
||||
|
||||
impl<'a, TToken, TContext> Parser<'a, TToken, TToken, TContext> for AnyParser
|
||||
|
@ -166,8 +192,8 @@ where
|
|||
mod test {
|
||||
use super::*;
|
||||
use crate::parser::{
|
||||
any, fail, fail_with_message, failed_parser_test_helper, parser_test_helper, satisfy, skip,
|
||||
succeed, take,
|
||||
any, fail, fail_with_message, failed_parser_test_helper, parser_test_helper, satified_map,
|
||||
satisfy, skip, succeed, take,
|
||||
};
|
||||
|
||||
#[test]
|
||||
|
@ -202,6 +228,21 @@ mod test {
|
|||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn satified_map_test() {
|
||||
parser_test_helper(ParserContext::new_with_str("123", ()), &1, |c, i| {
|
||||
satified_map(|x: &char| x.to_digit(10)).parse(c, i)
|
||||
});
|
||||
|
||||
parser_test_helper(ParserContext::new_with_str("23", ()), &2, |c, i| {
|
||||
satified_map(|x: &char| x.to_digit(10)).parse(c, i)
|
||||
});
|
||||
|
||||
parser_test_helper(ParserContext::new_with_str("3", ()), &3, |c, i| {
|
||||
satified_map(|x: &char| x.to_digit(10)).parse(c, i)
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn any_test() {
|
||||
parser_test_helper(ParserContext::new_with_str("abc", ()), &'a', |c, i| {
|
||||
|
|
Loading…
Reference in New Issue
Block a user