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::{
|
use crate::parser::modified_parsers::{
|
||||||
BindParser, ConvertParser, LitervalCountParser, LitervalParser, LookAheadParser, MapParser,
|
BindParser, ConvertParser, LitervalCountParser, LitervalParser, LookAheadParser, MapParser,
|
||||||
NextParser, ReverseParser,
|
NextParser, ReverseParser, TryParser,
|
||||||
};
|
};
|
||||||
use crate::parser::primitive_parsers::{
|
use crate::parser::primitive_parsers::{
|
||||||
AnyParser, FailParser, FailWithMessageParser, SatisfyParser, SkipParser, SucceedParser,
|
AnyParser, FailParser, FailWithMessageParser, SatifiedMapParser, SatisfyParser, SkipParser,
|
||||||
TakeParser,
|
SucceedParser, TakeParser,
|
||||||
};
|
};
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::error::Error;
|
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>
|
fn reverse<TResult>(self, result: TResult) -> ReverseParser<Self, T, TResult>
|
||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
|
@ -259,6 +270,16 @@ where
|
||||||
SatisfyParser { predicate }
|
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>
|
pub fn any<'a, TToken, TContext>() -> impl Parser<'a, TToken, TToken, TContext>
|
||||||
where
|
where
|
||||||
TToken: Debug + Clone + 'a,
|
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 struct ReverseParser<P, T, TResult> {
|
||||||
pub(crate) parser: P,
|
pub(crate) parser: P,
|
||||||
pub(crate) result: TResult,
|
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]
|
#[test]
|
||||||
fn reverse_test() {
|
fn reverse_test() {
|
||||||
parser_test_helper(ParserContext::new_with_str("abc", ()), &(), |c, i| {
|
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 {}
|
pub struct AnyParser {}
|
||||||
|
|
||||||
impl<'a, TToken, TContext> Parser<'a, TToken, TToken, TContext> for AnyParser
|
impl<'a, TToken, TContext> Parser<'a, TToken, TToken, TContext> for AnyParser
|
||||||
|
@ -166,8 +192,8 @@ where
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::parser::{
|
use crate::parser::{
|
||||||
any, fail, fail_with_message, failed_parser_test_helper, parser_test_helper, satisfy, skip,
|
any, fail, fail_with_message, failed_parser_test_helper, parser_test_helper, satified_map,
|
||||||
succeed, take,
|
satisfy, skip, succeed, take,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[test]
|
#[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]
|
#[test]
|
||||||
fn any_test() {
|
fn any_test() {
|
||||||
parser_test_helper(ParserContext::new_with_str("abc", ()), &'a', |c, i| {
|
parser_test_helper(ParserContext::new_with_str("abc", ()), &'a', |c, i| {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user