refact: lifetime support in trait level.

This commit is contained in:
2024-11-19 19:07:22 +08:00
parent 8a9c58966b
commit a282ad8f24
13 changed files with 621 additions and 480 deletions

View File

@@ -10,20 +10,21 @@ pub struct MapParser<P, F, T1> {
pub(crate) phantom: PhantomData<T1>,
}
impl<TToken, T1, T2, TContext, P, F> Parser<TToken, T2, TContext> for MapParser<P, F, T1>
impl<'a, TToken, T1: 'a, T2: 'a, TContext, P, F> Parser<'a, TToken, T2, TContext>
for MapParser<P, F, T1>
where
TToken: Debug + Clone,
P: Parser<TToken, T1, TContext>,
F: Fn(&T1) -> T2,
P: Parser<'a, TToken, T1, TContext>,
F: Fn(T1) -> T2,
{
fn parse<'a>(
fn parse(
&self,
context: Rc<RefCell<ParserContext<TToken, TContext>>>,
input: &'a [TToken],
) -> ParserResult<'a, TToken, T2> {
self.parser
.parse(context, input)
.map(|(remainder, result)| (remainder, (self.mapper)(&result)))
.map(|(remainder, result)| (remainder, (self.mapper)(result)))
}
}
@@ -33,14 +34,15 @@ pub struct BindParser<P, F, T1> {
pub(crate) phantom_data: PhantomData<T1>,
}
impl<TToken, T1, T2, TContext, P, P2, F> Parser<TToken, T2, TContext> for BindParser<P, F, T1>
impl<'a, TToken, T1: 'a, T2: 'a, TContext, P, P2, F> Parser<'a, TToken, T2, TContext>
for BindParser<P, F, T1>
where
TToken: Debug + Clone,
P: Parser<TToken, T1, TContext>,
P: Parser<'a, TToken, T1, TContext>,
F: Fn(T1) -> P2,
P2: Parser<TToken, T2, TContext>,
P2: Parser<'a, TToken, T2, TContext>,
{
fn parse<'a>(
fn parse(
&self,
context: Rc<RefCell<ParserContext<TToken, TContext>>>,
input: &'a [TToken],
@@ -57,13 +59,14 @@ pub struct ConvertParser<P, T1, T2> {
pub(crate) phantom_data2: PhantomData<T2>,
}
impl<TToken, T1, T2, TContext, P> Parser<TToken, T2, TContext> for ConvertParser<P, T1, T2>
impl<'a, TToken, T1: 'a, T2: 'a, TContext, P> Parser<'a, TToken, T2, TContext>
for ConvertParser<P, T1, T2>
where
TToken: Debug + Clone,
T2: From<T1>,
P: Parser<TToken, T1, TContext>,
P: Parser<'a, TToken, T1, TContext>,
{
fn parse<'a>(
fn parse(
&self,
context: Rc<RefCell<ParserContext<TToken, TContext>>>,
input: &'a [TToken],
@@ -80,13 +83,14 @@ pub struct NextParser<P, H, T> {
pub(crate) phantom_data: PhantomData<T>,
}
impl<TToken, T, TResult, TContext, P, H> Parser<TToken, TResult, TContext> for NextParser<P, H, T>
impl<'a, TToken, T: 'a, TResult: 'a, TContext, P, H> Parser<'a, TToken, TResult, TContext>
for NextParser<P, H, T>
where
TToken: Debug + Clone,
P: Parser<TToken, T, TContext>,
P: Parser<'a, TToken, T, TContext>,
H: for<'f> Fn(ParserResult<'f, TToken, T>) -> ParserResult<'f, TToken, TResult>,
{
fn parse<'a>(
fn parse(
&self,
context: Rc<RefCell<ParserContext<TToken, TContext>>>,
input: &'a [TToken],
@@ -102,16 +106,17 @@ pub struct LitervalParser<P, T> {
pub(crate) phantom_data: PhantomData<T>,
}
impl<TToken, T, TContext, P> Parser<TToken, Vec<TToken>, TContext> for LitervalParser<P, T>
impl<'a, TToken, T: 'a, TContext, P> Parser<'a, TToken, &'a [TToken], TContext>
for LitervalParser<P, T>
where
TToken: Debug + Clone,
P: Parser<TToken, T, TContext>,
TToken: Debug + Clone + 'a,
P: Parser<'a, TToken, T, TContext>,
{
fn parse<'a>(
fn parse(
&self,
context: Rc<RefCell<ParserContext<TToken, TContext>>>,
input: &'a [TToken],
) -> ParserResult<'a, TToken, Vec<TToken>> {
) -> ParserResult<'a, TToken, &'a [TToken]> {
let origin_input = input;
let (input, _) = self.parser.parse(context, input)?;
@@ -119,7 +124,7 @@ where
return Err((
input,
FailedParserResult::new(
"Empty input, the 'literal' parser cann't get length of elememtn.".to_owned(),
"Empty input, the 'literal' parser cann't get length of elememt.".to_owned(),
),
));
}
@@ -127,13 +132,42 @@ where
let length = (&origin_input[1..]).as_ptr() as usize - origin_input.as_ptr() as usize;
let index = (input.as_ptr() as usize - origin_input.as_ptr() as usize) / length;
Ok((
input,
(&origin_input[..index])
.into_iter()
.map(|x| x.clone())
.collect(),
))
Ok((input, &origin_input[..index]))
}
}
pub struct LitervalCountParser<P, T> {
pub(crate) parser: P,
pub(crate) phantom_data: PhantomData<T>,
}
impl<'a, TToken, T: 'a, TContext, P> Parser<'a, TToken, usize, TContext>
for LitervalCountParser<P, T>
where
TToken: Debug + Clone,
P: Parser<'a, TToken, T, TContext>,
{
fn parse(
&self,
context: Rc<RefCell<ParserContext<TToken, TContext>>>,
input: &'a [TToken],
) -> ParserResult<'a, TToken, usize> {
let origin_input = input;
let (input, _) = self.parser.parse(context, input)?;
if origin_input.is_empty() {
return Err((
input,
FailedParserResult::new(
"Empty input, the 'literal' parser cann't get length of elememt.".to_owned(),
),
));
}
let length = (&origin_input[1..]).as_ptr() as usize - origin_input.as_ptr() as usize;
let index = (input.as_ptr() as usize - origin_input.as_ptr() as usize) / length;
Ok((input, index))
}
}
@@ -142,12 +176,12 @@ pub struct LookAheadParser<P, T> {
pub(crate) phantom_data: PhantomData<T>,
}
impl<TToken, T, TContext, P> Parser<TToken, T, TContext> for LookAheadParser<P, T>
impl<'a, TToken, T: 'a, TContext, P> Parser<'a, TToken, T, TContext> for LookAheadParser<P, T>
where
TToken: Debug + Clone,
P: Parser<TToken, T, TContext>,
P: Parser<'a, TToken, T, TContext>,
{
fn parse<'a>(
fn parse(
&self,
context: Rc<RefCell<ParserContext<TToken, TContext>>>,
input: &'a [TToken],
@@ -165,14 +199,14 @@ pub struct ReverseParser<P, T, TResult> {
pub(crate) phantom_data: PhantomData<T>,
}
impl<TToken, T, TResult, TContext, P> Parser<TToken, TResult, TContext>
impl<'a, TToken, T: 'a, TResult: 'a, TContext, P> Parser<'a, TToken, TResult, TContext>
for ReverseParser<P, T, TResult>
where
TToken: Debug + Clone,
TResult: Debug + Clone,
P: Parser<TToken, T, TContext>,
P: Parser<'a, TToken, T, TContext>,
{
fn parse<'a>(
fn parse(
&self,
context: Rc<RefCell<ParserContext<TToken, TContext>>>,
input: &'a [TToken],
@@ -200,25 +234,22 @@ mod test {
parser_test_helper(
ParserContext::new_with_str("hello, world!", ()),
&(),
take(5).map(|_| ()),
|c, i| take(5).map(|_| ()).parse(c, i),
)
}
#[test]
fn bind_test() {
parser_test_helper(
ParserContext::new_with_str("abc", ()),
&'b',
char_parser('a').bind(|_| char_parser('b')),
);
parser_test_helper(ParserContext::new_with_str("abc", ()), &'b', |c, i| {
char_parser('a').bind(|_| char_parser('b')).parse(c, i)
});
parser_test_helper(
ParserContext::new_with_str("abc", ()),
&'c',
parser_test_helper(ParserContext::new_with_str("abc", ()), &'c', |c, i| {
char_parser('a')
.bind(|_| char_parser('b'))
.bind(|_| char_parser('c')),
);
.bind(|_| char_parser('c'))
.parse(c, i)
});
}
struct Number(i32);
@@ -246,49 +277,52 @@ mod test {
parser_test_helper(
ParserContext::new_with_str("9", ()),
&"9".to_owned(),
single_numer_parser.convert(),
|c, i| single_numer_parser.convert().parse(c, i),
);
parser_test_helper(
ParserContext::new_with_str("1", ()),
&"1".to_owned(),
single_numer_parser.convert(),
|c, i| single_numer_parser.convert().parse(c, i),
);
failed_parser_test_helper(
ParserContext::new_with_str("abc", ()),
single_numer_parser.convert::<String>(),
);
failed_parser_test_helper(ParserContext::new_with_str("abc", ()), |c, i| {
single_numer_parser.convert::<String>().parse(c, i)
});
}
#[test]
fn next_test() {
let parser = || {
satisfy(|c: &char| c.is_numeric()).next(|r| match r {
Ok((input, result)) => match result.to_digit(10) {
None => Err((input, FailedParserResult::new("What?".to_string()))),
Some(r) => Ok((input, Number(r as i32))),
},
Err(r) => Err(r),
})
};
fn parser(
context: Rc<RefCell<ParserContext<char, ()>>>,
input: &[char],
) -> ParserResult<char, Number> {
satisfy(|c: &char| c.is_numeric())
.next(|r| match r {
Ok((input, result)) => match result.to_digit(10) {
None => Err((input, FailedParserResult::new("What?".to_string()))),
Some(r) => Ok((input, Number(r as i32))),
},
Err(r) => Err(r),
})
.parse(context, input)
}
parser_test_helper(
ParserContext::new_with_str("9", ()),
&"9".to_owned(),
parser().convert(),
|c, i| parser.convert().parse(c, i),
);
parser_test_helper(
ParserContext::new_with_str("1", ()),
&"1".to_owned(),
parser().convert(),
|c, i| parser.convert().parse(c, i),
);
failed_parser_test_helper(
ParserContext::new_with_str("abc", ()),
parser().convert::<String>(),
);
failed_parser_test_helper(ParserContext::new_with_str("abc", ()), |c, i| {
parser.convert::<String>().parse(c, i)
});
}
#[test]
@@ -296,45 +330,58 @@ mod test {
parser_test_helper(
ParserContext::new_with_str("abc", ()),
&vec!['a'],
char_parser('a').literal(),
|c, i| {
char_parser('a')
.literal()
.map(|x| x.iter().map(|x| x.clone()).collect())
.parse(c, i)
},
);
parser_test_helper(
ParserContext::new_with_str("abc", ()),
&vec!['a', 'b'],
char_parser('a').bind(|_| char_parser('b')).literal(),
|c, i| {
char_parser('a')
.bind(|_| char_parser('b'))
.literal()
.map(|x| x.iter().map(|x| x.clone()).collect())
.parse(c, i)
},
);
parser_test_helper(
ParserContext::new_with_str("abc", ()),
&vec!['a', 'b', 'c'],
char_parser('a')
.bind(|_| char_parser('b'))
.bind(|_| char_parser('c'))
.literal(),
|c, i| {
char_parser('a')
.bind(|_| char_parser('b'))
.bind(|_| char_parser('c'))
.literal()
.map(|x| x.iter().map(|x| x.clone()).collect())
.parse(c, i)
},
);
}
#[test]
fn look_ahead_test() {
parser_test_helper(
ParserContext::new_with_str("abc", ()),
&'a',
char_parser('a').look_ahead().bind(|_| char_parser('a')),
);
parser_test_helper(ParserContext::new_with_str("abc", ()), &'a', |c, i| {
char_parser('a')
.look_ahead()
.bind(|_| char_parser('a'))
.parse(c, i)
});
}
#[test]
fn reverse_test() {
parser_test_helper(
ParserContext::new_with_str("abc", ()),
&(),
char_parser('b').reverse(()),
);
parser_test_helper(ParserContext::new_with_str("abc", ()), &(), |c, i| {
char_parser('b').reverse(()).parse(c, i)
});
failed_parser_test_helper(
ParserContext::new_with_str("abc", ()),
char_parser('a').reverse(()),
);
failed_parser_test_helper(ParserContext::new_with_str("abc", ()), |c, i| {
char_parser('a').reverse(()).parse(c, i)
});
}
}

View File

@@ -8,12 +8,12 @@ pub struct SucceedParser<T> {
pub(crate) value: T,
}
impl<TToken, T, TContext> Parser<TToken, T, TContext> for SucceedParser<T>
impl<'a, TToken, T: 'a, TContext> Parser<'a, TToken, T, TContext> for SucceedParser<T>
where
TToken: Debug + Clone,
T: Debug + Clone,
{
fn parse<'a>(
fn parse(
&self,
_: Rc<RefCell<ParserContext<TToken, TContext>>>,
input: &'a [TToken],
@@ -26,11 +26,11 @@ pub struct FailParser<T> {
pub(crate) phantom_data: PhantomData<T>,
}
impl<TToken, T, TContext> Parser<TToken, T, TContext> for FailParser<T>
impl<'a, TToken, T: 'a, TContext> Parser<'a, TToken, T, TContext> for FailParser<T>
where
TToken: Debug + Clone,
{
fn parse<'a>(
fn parse(
&self,
_: Rc<RefCell<ParserContext<TToken, TContext>>>,
input: &'a [TToken],
@@ -47,11 +47,11 @@ pub struct FailWithMessageParser<T> {
pub(crate) phantom_data: PhantomData<T>,
}
impl<TToken, T, TContext> Parser<TToken, T, TContext> for FailWithMessageParser<T>
impl<'a, TToken, T: 'a, TContext> Parser<'a, TToken, T, TContext> for FailWithMessageParser<T>
where
TToken: Debug + Clone,
{
fn parse<'a>(
fn parse(
&self,
_: Rc<RefCell<ParserContext<TToken, TContext>>>,
input: &'a [TToken],
@@ -64,12 +64,12 @@ pub struct SatisfyParser<F> {
pub(crate) predicate: F,
}
impl<TToken, TContext, F> Parser<TToken, TToken, TContext> for SatisfyParser<F>
impl<'a, TToken, TContext, F> Parser<'a, TToken, TToken, TContext> for SatisfyParser<F>
where
TToken: Debug + Clone,
TToken: Debug + Clone + 'a,
F: Fn(&TToken) -> bool,
{
fn parse<'a>(
fn parse(
&self,
_: Rc<RefCell<ParserContext<TToken, TContext>>>,
input: &'a [TToken],
@@ -91,11 +91,11 @@ where
pub struct AnyParser {}
impl<TToken, TContext> Parser<TToken, TToken, TContext> for AnyParser
impl<'a, TToken, TContext> Parser<'a, TToken, TToken, TContext> for AnyParser
where
TToken: Debug + Clone,
TToken: Debug + Clone + 'a,
{
fn parse<'a>(
fn parse(
&self,
_: Rc<RefCell<ParserContext<TToken, TContext>>>,
input: &'a [TToken],
@@ -112,11 +112,11 @@ pub struct TakeParser {
pub(crate) count: usize,
}
impl<TToken, TContext> Parser<TToken, Vec<TToken>, TContext> for TakeParser
impl<'a, TToken, TContext> Parser<'a, TToken, Vec<TToken>, TContext> for TakeParser
where
TToken: Debug + Clone,
TToken: Debug + Clone + 'a,
{
fn parse<'a>(
fn parse(
&self,
_: Rc<RefCell<ParserContext<TToken, TContext>>>,
input: &'a [TToken],
@@ -142,11 +142,11 @@ pub struct SkipParser {
pub(crate) count: usize,
}
impl<TToken, TContext> Parser<TToken, (), TContext> for SkipParser
impl<'a, TToken, TContext> Parser<'a, TToken, (), TContext> for SkipParser
where
TToken: Debug + Clone,
{
fn parse<'a>(
fn parse(
&self,
_: Rc<RefCell<ParserContext<TToken, TContext>>>,
input: &'a [TToken],
@@ -175,41 +175,45 @@ mod test {
#[test]
fn succeed_test() {
parser_test_helper(ParserContext::new_with_str("abc", ()), &(), succeed(()));
parser_test_helper(ParserContext::new_with_str("abc", ()), &(), |c, i| {
succeed(()).parse(c, i)
});
}
#[test]
fn fail_test() {
failed_parser_test_helper::<(), _>(ParserContext::new_with_str("abc", ()), fail());
failed_parser_test_helper(ParserContext::new_with_str("abc", ()), |c, i| {
fail::<char, (), ()>().parse(c, i)
});
}
#[test]
fn fail_with_message_test() {
failed_parser_test_helper::<(), _>(
ParserContext::new_with_str("abc", ()),
fail_with_message("Failed!"),
);
failed_parser_test_helper(ParserContext::new_with_str("abc", ()), |c, i| {
fail_with_message::<char, (), ()>("Failed!").parse(c, i)
});
}
#[test]
fn satisfy_test() {
parser_test_helper(
ParserContext::new_with_str("abc", ()),
&'a',
satisfy(|x| x == &'a'),
);
parser_test_helper(ParserContext::new_with_str("abc", ()), &'a', |c, i| {
satisfy(|x| x == &'a').parse(c, i)
});
failed_parser_test_helper(
ParserContext::new_with_str("abc", ()),
satisfy(|x| x == &'b'),
);
failed_parser_test_helper(ParserContext::new_with_str("abc", ()), |c, i| {
satisfy(|x| x == &'b').parse(c, i)
});
}
#[test]
fn any_test() {
parser_test_helper(ParserContext::new_with_str("abc", ()), &'a', any());
parser_test_helper(ParserContext::new_with_str("abc", ()), &'a', |c, i| {
any().parse(c, i)
});
parser_test_helper(ParserContext::new_with_str("cde", ()), &'c', any());
parser_test_helper(ParserContext::new_with_str("cde", ()), &'c', |c, i| {
any().parse(c, i)
});
}
#[test]
@@ -217,10 +221,12 @@ mod test {
parser_test_helper(
ParserContext::new_with_str("hello, world!", ()),
&("hello".chars().collect()),
take(5),
|c, i| take(5).parse(c, i),
);
failed_parser_test_helper(ParserContext::new_with_str("abcd", ()), take(5));
failed_parser_test_helper(ParserContext::new_with_str("abcd", ()), |c, i| {
take(5).parse(c, i)
});
}
#[test]
@@ -228,9 +234,11 @@ mod test {
parser_test_helper(
ParserContext::new_with_str("hello, world!", ()),
&(),
skip(5),
|c, i| skip(5).parse(c, i),
);
failed_parser_test_helper(ParserContext::new_with_str("abcd", ()), skip(5));
failed_parser_test_helper(ParserContext::new_with_str("abcd", ()), |c, i| {
skip(5).parse(c, i)
});
}
}