refact: lifetime support in trait level.

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

32
Cargo.lock generated
View File

@ -2,6 +2,38 @@
# It is not intended for manual editing. # It is not intended for manual editing.
version = 4 version = 4
[[package]]
name = "anyhow"
version = "1.0.93"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775"
[[package]]
name = "memchr"
version = "2.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
[[package]]
name = "minimal-lexical"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
[[package]]
name = "nom"
version = "7.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
dependencies = [
"memchr",
"minimal-lexical",
]
[[package]] [[package]]
name = "zero-parser" name = "zero-parser"
version = "0.1.0" version = "0.1.0"
dependencies = [
"anyhow",
"nom",
]

View File

@ -4,3 +4,7 @@ version = "0.1.0"
edition = "2021" edition = "2021"
[dependencies] [dependencies]
anyhow = { version = "1" }
[dev-dependencies]
nom = { version = "7" }

View File

@ -10,21 +10,19 @@ use crate::combinators::many_parsers::{
Many1Parser, Many1TillParser, ManyParser, ManyTillParser, Skip1Parser, SkipParser, Many1Parser, Many1TillParser, ManyParser, ManyTillParser, Skip1Parser, SkipParser,
}; };
use crate::combinators::separated_parsers::{SeparateBy1Parser, SeparateOrEndBy1Parser}; use crate::combinators::separated_parsers::{SeparateBy1Parser, SeparateOrEndBy1Parser};
use crate::combinators::tuple_parser::ParserTuple; use crate::combinators::tuple_parser::{ParserTuple, TupleParser};
use crate::parser::{any, Parser, ParserContext, ParserResult}; use crate::parser::{any, Parser};
use std::cell::RefCell;
use std::fmt::Debug; use std::fmt::Debug;
use std::marker::PhantomData; use std::marker::PhantomData;
use std::rc::Rc;
pub trait ParserExt<TToken, T, TContext>: Parser<TToken, T, TContext> pub trait ParserExt<'a, TToken, T: 'a, TContext>: Parser<'a, TToken, T, TContext>
where where
TToken: Debug + Clone, TToken: Debug + Clone,
{ {
fn left<TRight, PRight>(self, right_parser: PRight) -> LeftParser<Self, PRight, TRight> fn left<TRight: 'a, PRight>(self, right_parser: PRight) -> LeftParser<Self, PRight, TRight>
where where
Self: Sized, Self: Sized,
PRight: Parser<TToken, TRight, TContext>, PRight: Parser<'a, TToken, TRight, TContext>,
{ {
LeftParser { LeftParser {
left_parser: self, left_parser: self,
@ -33,10 +31,10 @@ where
} }
} }
fn right<TRight, PRight>(self, right_parser: PRight) -> RightParser<Self, PRight, T> fn right<TRight: 'a, PRight>(self, right_parser: PRight) -> RightParser<Self, PRight, T>
where where
Self: Sized, Self: Sized,
PRight: Parser<TToken, TRight, TContext>, PRight: Parser<'a, TToken, TRight, TContext>,
{ {
RightParser { RightParser {
left_parser: self, left_parser: self,
@ -48,7 +46,7 @@ where
fn alternate<P>(self, second_parser: P) -> AlternateParser<Self, P> fn alternate<P>(self, second_parser: P) -> AlternateParser<Self, P>
where where
Self: Sized, Self: Sized,
P: Parser<TToken, T, TContext>, P: Parser<'a, TToken, T, TContext>,
{ {
AlternateParser { AlternateParser {
first: self, first: self,
@ -90,13 +88,13 @@ where
} }
} }
fn many_till<TTerminator, PTerminator>( fn many_till<TTerminator: 'a, PTerminator>(
self, self,
terminator: PTerminator, terminator: PTerminator,
) -> ManyTillParser<Self, PTerminator, TTerminator> ) -> ManyTillParser<Self, PTerminator, TTerminator>
where where
Self: Sized, Self: Sized,
PTerminator: Parser<TToken, TTerminator, TContext>, PTerminator: Parser<'a, TToken, TTerminator, TContext>,
{ {
ManyTillParser { ManyTillParser {
parser: self, parser: self,
@ -105,13 +103,13 @@ where
} }
} }
fn many1_till<TTerminator, PTerminator>( fn many1_till<TTerminator: 'a, PTerminator>(
self, self,
terminator: PTerminator, terminator: PTerminator,
) -> Many1TillParser<Self, PTerminator, TTerminator> ) -> Many1TillParser<Self, PTerminator, TTerminator>
where where
Self: Sized, Self: Sized,
PTerminator: Parser<TToken, TTerminator, TContext>, PTerminator: Parser<'a, TToken, TTerminator, TContext>,
{ {
Many1TillParser { Many1TillParser {
parser: self, parser: self,
@ -121,18 +119,21 @@ where
} }
} }
impl<TToken, T, TContext, P> ParserExt<TToken, T, TContext> for P impl<'a, TToken, T: 'a, TContext, P> ParserExt<'a, TToken, T, TContext> for P
where where
TToken: Debug + Clone, TToken: Debug + Clone,
P: Parser<TToken, T, TContext>, P: Parser<'a, TToken, T, TContext>,
{ {
} }
fn alternate_helper<TToken, T, TContext, P1, P2>(first: P1, second: P2) -> AlternateParser<P1, P2> pub fn alternate_helper<'a, TToken, T: 'a, TContext, P1, P2>(
first: P1,
second: P2,
) -> AlternateParser<P1, P2>
where where
TToken: Debug + Clone, TToken: Debug + Clone,
P1: Parser<TToken, T, TContext>, P1: Parser<'a, TToken, T, TContext>,
P2: Parser<TToken, T, TContext>, P2: Parser<'a, TToken, T, TContext>,
{ {
AlternateParser { first, second } AlternateParser { first, second }
} }
@ -143,65 +144,63 @@ macro_rules! alternate {
{ {
let parser = $first; let parser = $first;
$( $(
let parser = crate::combinators::alternate_helper(parser, $second); let parser = $crate::combinators::alternate_helper(parser, $second);
)* )*
parser parser
} }
}; };
} }
pub fn tuple<TToken, T, TContext, TList>( pub fn tuple<'a, TToken, T: 'a, TContext, TList>(list: TList) -> TupleParser<TList>
list: TList,
) -> impl Fn(Rc<RefCell<ParserContext<TToken, TContext>>>, &[TToken]) -> ParserResult<TToken, T>
where where
TToken: Debug + Clone, TToken: Debug + Clone + 'a,
TList: ParserTuple<TToken, T, TContext>, TList: ParserTuple<'a, TToken, T, TContext>,
{ {
move |context, input| list.parse(context, input) TupleParser { parser: list }
} }
pub fn take_till<TToken, TTerminator, TContext, PTerminator>( pub fn take_till<'a, TToken, TTerminator: 'a, TContext, PTerminator>(
termiantor: PTerminator, termiantor: PTerminator,
) -> impl Parser<TToken, Vec<TToken>, TContext> ) -> impl Parser<'a, TToken, Vec<TToken>, TContext>
where where
TToken: Debug + Clone, TToken: Debug + Clone + 'a,
PTerminator: Parser<TToken, TTerminator, TContext>, PTerminator: Parser<'a, TToken, TTerminator, TContext>,
{ {
any().many_till(termiantor) any().many_till(termiantor)
} }
pub fn take1_till<TToken, TTerminator, TContext, PTerminator>( pub fn take1_till<'a, TToken, TTerminator: 'a, TContext, PTerminator>(
terminator: PTerminator, terminator: PTerminator,
) -> impl Parser<TToken, Vec<TToken>, TContext> ) -> impl Parser<'a, TToken, Vec<TToken>, TContext>
where where
TToken: Debug + Clone, TToken: Debug + Clone + 'a,
PTerminator: Parser<TToken, TTerminator, TContext>, PTerminator: Parser<'a, TToken, TTerminator, TContext>,
{ {
any().many1_till(terminator) any().many1_till(terminator)
} }
pub fn quote<TToken, T, TLeft, TRight, TContext, PLeft, P, PRight>( pub fn quote<'a, TToken, T: 'a, TLeft: 'a, TRight: 'a, TContext, PLeft, P, PRight>(
left: PLeft, left: PLeft,
parser: P, parser: P,
right: PRight, right: PRight,
) -> impl Parser<TToken, Vec<T>, TContext> ) -> impl Parser<'a, TToken, Vec<T>, TContext>
where where
TToken: Debug + Clone, TToken: Debug + Clone + 'a,
P: Parser<TToken, T, TContext>, P: Parser<'a, TToken, T, TContext>,
PLeft: Parser<TToken, TLeft, TContext>, PLeft: Parser<'a, TToken, TLeft, TContext>,
PRight: Parser<TToken, TRight, TContext>, PRight: Parser<'a, TToken, TRight, TContext>,
{ {
left.right(parser.many_till(right)) left.right(parser.many_till(right))
} }
pub fn separate_by1<TToken, T, TSeparator, TContext, P, PSeparator>( pub fn separate_by1<'a, TToken, T: 'a, TSeparator: 'a, TContext, P, PSeparator>(
parser: P, parser: P,
separator: PSeparator, separator: PSeparator,
) -> impl Parser<TToken, Vec<T>, TContext> ) -> impl Parser<'a, TToken, Vec<T>, TContext>
where where
TToken: Debug + Clone, TToken: Debug + Clone + 'a,
P: Parser<TToken, T, TContext>, P: Parser<'a, TToken, T, TContext>,
PSeparator: Parser<TToken, TSeparator, TContext>, PSeparator: Parser<'a, TToken, TSeparator, TContext>,
{ {
SeparateBy1Parser { SeparateBy1Parser {
parser, parser,
@ -210,14 +209,14 @@ where
} }
} }
pub fn separate_by<TToken, T, TSeparator, TContext, P, PSeparator>( pub fn separate_by<'a, TToken, T: 'a, TSeparator: 'a, TContext, P, PSeparator>(
parser: P, parser: P,
separator: PSeparator, separator: PSeparator,
) -> impl Parser<TToken, Vec<T>, TContext> ) -> impl Parser<'a, TToken, Vec<T>, TContext>
where where
TToken: Debug + Clone, TToken: Debug + Clone + 'a,
P: Parser<TToken, T, TContext>, P: Parser<'a, TToken, T, TContext>,
PSeparator: Parser<TToken, TSeparator, TContext>, PSeparator: Parser<'a, TToken, TSeparator, TContext>,
{ {
separate_by1(parser, separator).next(|r| match r { separate_by1(parser, separator).next(|r| match r {
Err((input, _)) => Ok((input, vec![])), Err((input, _)) => Ok((input, vec![])),
@ -225,38 +224,38 @@ where
}) })
} }
pub fn end_by1<TToken, T, TSeparator, TContext, P, PSeparator>( pub fn end_by1<'a, TToken, T: 'a, TSeparator: 'a, TContext, P, PSeparator>(
parser: P, parser: P,
separator: PSeparator, separator: PSeparator,
) -> impl Parser<TToken, Vec<T>, TContext> ) -> impl Parser<'a, TToken, Vec<T>, TContext>
where where
TToken: Debug + Clone, TToken: Debug + Clone + 'a,
P: Parser<TToken, T, TContext>, P: Parser<'a, TToken, T, TContext>,
PSeparator: Parser<TToken, TSeparator, TContext>, PSeparator: Parser<'a, TToken, TSeparator, TContext>,
{ {
parser.many1_till(separator) parser.many1_till(separator)
} }
pub fn end_by<TToken, T, TSeparator, TContext, P, PSeparator>( pub fn end_by<'a, TToken, T: 'a, TSeparator: 'a, TContext, P, PSeparator>(
parser: P, parser: P,
separator: PSeparator, separator: PSeparator,
) -> impl Parser<TToken, Vec<T>, TContext> ) -> impl Parser<'a, TToken, Vec<T>, TContext>
where where
TToken: Debug + Clone, TToken: Debug + Clone + 'a,
P: Parser<TToken, T, TContext>, P: Parser<'a, TToken, T, TContext>,
PSeparator: Parser<TToken, TSeparator, TContext>, PSeparator: Parser<'a, TToken, TSeparator, TContext>,
{ {
parser.many_till(separator) parser.many_till(separator)
} }
pub fn separate_or_end_by1<TToken, T, TSeparator, TContext, P, PSeparator>( pub fn separate_or_end_by1<'a, TToken, T: 'a, TSeparator: 'a, TContext, P, PSeparator>(
parser: P, parser: P,
separator: PSeparator, separator: PSeparator,
) -> impl Parser<TToken, Vec<T>, TContext> ) -> impl Parser<'a, TToken, Vec<T>, TContext>
where where
TToken: Debug + Clone, TToken: Debug + Clone + 'a,
P: Parser<TToken, T, TContext>, P: Parser<'a, TToken, T, TContext>,
PSeparator: Parser<TToken, TSeparator, TContext>, PSeparator: Parser<'a, TToken, TSeparator, TContext>,
{ {
SeparateOrEndBy1Parser { SeparateOrEndBy1Parser {
parser, parser,
@ -265,14 +264,14 @@ where
} }
} }
pub fn separate_or_end_by<TToken, T, TSeparator, TContext, P, PSeparator>( pub fn separate_or_end_by<'a, TToken, T: 'a, TSeparator: 'a, TContext, P, PSeparator>(
parser: P, parser: P,
separator: PSeparator, separator: PSeparator,
) -> impl Parser<TToken, Vec<T>, TContext> ) -> impl Parser<'a, TToken, Vec<T>, TContext>
where where
TToken: Debug + Clone, TToken: Debug + Clone + 'a,
P: Parser<TToken, T, TContext>, P: Parser<'a, TToken, T, TContext>,
PSeparator: Parser<TToken, TSeparator, TContext>, PSeparator: Parser<'a, TToken, TSeparator, TContext>,
{ {
separate_or_end_by1(parser, separator).next(|r| match r { separate_or_end_by1(parser, separator).next(|r| match r {
Err((i, _)) => Ok((i, vec![])), Err((i, _)) => Ok((i, vec![])),

View File

@ -8,19 +8,20 @@ pub struct AlternateParser<P1, P2> {
pub(crate) second: P2, pub(crate) second: P2,
} }
impl<TToken, T, TContext, P1, P2> Parser<TToken, T, TContext> for AlternateParser<P1, P2> impl<'a, TToken, T: 'a, TContext, P1, P2> Parser<'a, TToken, T, TContext>
for AlternateParser<P1, P2>
where where
TToken: Debug + Clone, TToken: Debug + Clone,
P1: Parser<TToken, T, TContext>, P1: Parser<'a, TToken, T, TContext>,
P2: Parser<TToken, T, TContext>, P2: Parser<'a, TToken, T, TContext>,
{ {
fn parse<'a>( fn parse(
&self, &self,
context: Rc<RefCell<ParserContext<TToken, TContext>>>, context: Rc<RefCell<ParserContext<TToken, TContext>>>,
input: &'a [TToken], input: &'a [TToken],
) -> ParserResult<'a, TToken, T> { ) -> ParserResult<'a, TToken, T> {
match self.first.parse(context.clone(), input) { match self.first.parse(context.clone(), input) {
Err((input, _)) => self.second.parse(context, input), Err(_) => self.second.parse(context, input),
r => r, r => r,
} }
} }
@ -64,4 +65,47 @@ mod test {
parser_test_helper(ParserContext::new_with_str("b", ()), &'b', parser); parser_test_helper(ParserContext::new_with_str("b", ()), &'b', parser);
parser_test_helper(ParserContext::new_with_str("c", ()), &'c', parser); parser_test_helper(ParserContext::new_with_str("c", ()), &'c', parser);
} }
#[test]
fn alternate_function_test() {
fn parser(
context: Rc<RefCell<ParserContext<char, ()>>>,
input: &[char],
) -> ParserResult<char, char> {
alternate!(char_parser('a'), char_parser('b')).parse(context, input)
}
parser_test_helper(ParserContext::new_with_str("a", ()), &'a', |c, i| {
let parser = alternate!(parser, char_parser('c'));
let parser = alternate!(parser, char_parser('d'));
parser.parse(c, i)
});
}
#[test]
fn alternate_pure_function_test() {
fn parser1(
context: Rc<RefCell<ParserContext<char, ()>>>,
input: &[char],
) -> ParserResult<char, &[char]> {
alternate!(char_parser('a').literal(), char_parser('b').literal()).parse(context, input)
}
fn parser2(
context: Rc<RefCell<ParserContext<char, ()>>>,
input: &[char],
) -> ParserResult<char, &[char]> {
alternate!(char_parser('c').literal(), char_parser('d').literal()).parse(context, input)
}
parser_test_helper(
ParserContext::new_with_str("a", ()),
&"a".to_owned(),
|c, i| {
alternate!(parser1, parser2)
.map(|x| x.iter().map(|x| x.clone()).collect())
.parse(c, i)
},
);
}
} }

View File

@ -1,4 +1,3 @@
use crate::combinators::ParserExt;
use crate::parser::{Parser, ParserContext, ParserResult}; use crate::parser::{Parser, ParserContext, ParserResult};
use std::cell::RefCell; use std::cell::RefCell;
use std::fmt::Debug; use std::fmt::Debug;
@ -11,14 +10,14 @@ pub struct LeftParser<PLeft, PRight, TRight> {
pub(crate) phantom_data: PhantomData<TRight>, pub(crate) phantom_data: PhantomData<TRight>,
} }
impl<TToken, T, TContext, TRight, PLeft, PRight> Parser<TToken, T, TContext> impl<'a, TToken, T: 'a, TContext, TRight: 'a, PLeft, PRight> Parser<'a, TToken, T, TContext>
for LeftParser<PLeft, PRight, TRight> for LeftParser<PLeft, PRight, TRight>
where where
TToken: Debug + Clone, TToken: Debug + Clone,
PLeft: Parser<TToken, T, TContext>, PLeft: Parser<'a, TToken, T, TContext>,
PRight: Parser<TToken, TRight, TContext>, PRight: Parser<'a, TToken, TRight, TContext>,
{ {
fn parse<'a>( fn parse(
&self, &self,
context: Rc<RefCell<ParserContext<TToken, TContext>>>, context: Rc<RefCell<ParserContext<TToken, TContext>>>,
input: &'a [TToken], input: &'a [TToken],
@ -38,14 +37,14 @@ pub struct RightParser<PLeft, PRight, T> {
pub(crate) phantom_data: PhantomData<T>, pub(crate) phantom_data: PhantomData<T>,
} }
impl<TToken, T, TContext, TRight, PLeft, PRight> Parser<TToken, TRight, TContext> impl<'a, TToken, T: 'a, TContext, TRight: 'a, PLeft, PRight> Parser<'a, TToken, TRight, TContext>
for RightParser<PLeft, PRight, T> for RightParser<PLeft, PRight, T>
where where
TToken: Debug + Clone, TToken: Debug + Clone,
PLeft: Parser<TToken, T, TContext>, PLeft: Parser<'a, TToken, T, TContext>,
PRight: Parser<TToken, TRight, TContext>, PRight: Parser<'a, TToken, TRight, TContext>,
{ {
fn parse<'a>( fn parse(
&self, &self,
context: Rc<RefCell<ParserContext<TToken, TContext>>>, context: Rc<RefCell<ParserContext<TToken, TContext>>>,
input: &'a [TToken], input: &'a [TToken],
@ -58,25 +57,21 @@ where
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*; use crate::combinators::ParserExt;
use crate::parser::{parser_test_helper, ParserContext}; use crate::parser::{parser_test_helper, Parser, ParserContext};
use crate::text::char_parser; use crate::text::char_parser;
#[test] #[test]
fn left_test() { fn left_test() {
parser_test_helper( parser_test_helper(ParserContext::new_with_str("abc", ()), &'a', |c, i| {
ParserContext::new_with_str("abc", ()), char_parser('a').left(char_parser('b')).parse(c, i)
&'a', });
char_parser('a').left(char_parser('b')),
);
} }
#[test] #[test]
fn right_test() { fn right_test() {
parser_test_helper( parser_test_helper(ParserContext::new_with_str("abc", ()), &'b', |c, i| {
ParserContext::new_with_str("abc", ()), char_parser('a').right(char_parser('b')).parse(c, i)
&'b', })
char_parser('a').right(char_parser('b')),
)
} }
} }

View File

@ -8,12 +8,12 @@ pub struct ManyParser<P> {
pub(crate) parser: P, pub(crate) parser: P,
} }
impl<TToken, T, TContext, P> Parser<TToken, Vec<T>, TContext> for ManyParser<P> impl<'a, TToken, T: 'a, TContext, P> Parser<'a, TToken, Vec<T>, TContext> for ManyParser<P>
where where
TToken: Debug + Clone, TToken: Debug + Clone,
P: Parser<TToken, T, TContext>, P: Parser<'a, TToken, T, TContext>,
{ {
fn parse<'a>( fn parse(
&self, &self,
context: Rc<RefCell<ParserContext<TToken, TContext>>>, context: Rc<RefCell<ParserContext<TToken, TContext>>>,
input: &'a [TToken], input: &'a [TToken],
@ -34,12 +34,12 @@ pub struct Many1Parser<P> {
pub(crate) parser: P, pub(crate) parser: P,
} }
impl<TToken, T, TContext, P> Parser<TToken, Vec<T>, TContext> for Many1Parser<P> impl<'a, TToken, T: 'a, TContext, P> Parser<'a, TToken, Vec<T>, TContext> for Many1Parser<P>
where where
TToken: Debug + Clone, TToken: Debug + Clone,
P: Parser<TToken, T, TContext>, P: Parser<'a, TToken, T, TContext>,
{ {
fn parse<'a>( fn parse(
&self, &self,
context: Rc<RefCell<ParserContext<TToken, TContext>>>, context: Rc<RefCell<ParserContext<TToken, TContext>>>,
input: &'a [TToken], input: &'a [TToken],
@ -61,12 +61,12 @@ pub struct SkipParser<P, T> {
pub(crate) phantom_data: PhantomData<T>, pub(crate) phantom_data: PhantomData<T>,
} }
impl<TToken, T, TContext, P> Parser<TToken, (), TContext> for SkipParser<P, T> impl<'a, TToken, T: 'a, TContext, P> Parser<'a, TToken, (), TContext> for SkipParser<P, T>
where where
TToken: Debug + Clone, TToken: Debug + Clone,
P: Parser<TToken, T, TContext>, P: Parser<'a, TToken, T, TContext>,
{ {
fn parse<'a>( fn parse(
&self, &self,
context: Rc<RefCell<ParserContext<TToken, TContext>>>, context: Rc<RefCell<ParserContext<TToken, TContext>>>,
input: &'a [TToken], input: &'a [TToken],
@ -86,12 +86,12 @@ pub struct Skip1Parser<P, T> {
pub(crate) phantom_data: PhantomData<T>, pub(crate) phantom_data: PhantomData<T>,
} }
impl<TToken, T, TContext, P> Parser<TToken, (), TContext> for Skip1Parser<P, T> impl<'a, TToken, T: 'a, TContext, P> Parser<'a, TToken, (), TContext> for Skip1Parser<P, T>
where where
TToken: Debug + Clone, TToken: Debug + Clone,
P: Parser<TToken, T, TContext>, P: Parser<'a, TToken, T, TContext>,
{ {
fn parse<'a>( fn parse(
&self, &self,
context: Rc<RefCell<ParserContext<TToken, TContext>>>, context: Rc<RefCell<ParserContext<TToken, TContext>>>,
input: &'a [TToken], input: &'a [TToken],
@ -112,14 +112,14 @@ pub struct ManyTillParser<P, PTerminator, TTerminator> {
pub(crate) phantom_data: PhantomData<TTerminator>, pub(crate) phantom_data: PhantomData<TTerminator>,
} }
impl<TToken, T, TTerminator, TContext, P, PTerminator> Parser<TToken, Vec<T>, TContext> impl<'a, TToken, T: 'a, TTerminator: 'a, TContext, P, PTerminator>
for ManyTillParser<P, PTerminator, TTerminator> Parser<'a, TToken, Vec<T>, TContext> for ManyTillParser<P, PTerminator, TTerminator>
where where
TToken: Debug + Clone, TToken: Debug + Clone,
P: Parser<TToken, T, TContext>, P: Parser<'a, TToken, T, TContext>,
PTerminator: Parser<TToken, TTerminator, TContext>, PTerminator: Parser<'a, TToken, TTerminator, TContext>,
{ {
fn parse<'a>( fn parse(
&self, &self,
context: Rc<RefCell<ParserContext<TToken, TContext>>>, context: Rc<RefCell<ParserContext<TToken, TContext>>>,
input: &'a [TToken], input: &'a [TToken],
@ -150,14 +150,14 @@ pub struct Many1TillParser<P, PTerminator, TTerminator> {
pub(crate) phantom_data: PhantomData<TTerminator>, pub(crate) phantom_data: PhantomData<TTerminator>,
} }
impl<TToken, T, TTerminator, TContext, P, PTerminator> Parser<TToken, Vec<T>, TContext> impl<'a, TToken, T: 'a, TTerminator: 'a, TContext, P, PTerminator>
for Many1TillParser<P, PTerminator, TTerminator> Parser<'a, TToken, Vec<T>, TContext> for Many1TillParser<P, PTerminator, TTerminator>
where where
TToken: Debug + Clone, TToken: Debug + Clone,
P: Parser<TToken, T, TContext>, P: Parser<'a, TToken, T, TContext>,
PTerminator: Parser<TToken, TTerminator, TContext>, PTerminator: Parser<'a, TToken, TTerminator, TContext>,
{ {
fn parse<'a>( fn parse(
&self, &self,
context: Rc<RefCell<ParserContext<TToken, TContext>>>, context: Rc<RefCell<ParserContext<TToken, TContext>>>,
input: &'a [TToken], input: &'a [TToken],
@ -174,7 +174,10 @@ where
result.push(r); result.push(r);
input = i; input = i;
} else { } else {
return Ok((input, result)); return Err((
input,
FailedParserResult::new("End with other elements.".to_owned()),
));
} }
} }
} }
@ -192,26 +195,22 @@ mod test {
parser_test_helper( parser_test_helper(
ParserContext::new_with_str("aaa", ()), ParserContext::new_with_str("aaa", ()),
&vec!['a', 'a', 'a'], &vec!['a', 'a', 'a'],
char_parser('a').many(), |c, i| char_parser('a').many().parse(c, i),
); );
parser_test_helper( parser_test_helper(
ParserContext::new_with_str("aaabbaa", ()), ParserContext::new_with_str("aaabbaa", ()),
&vec!['a', 'a', 'a'], &vec!['a', 'a', 'a'],
char_parser('a').many(), |c, i| char_parser('a').many().parse(c, i),
); );
parser_test_helper( parser_test_helper(ParserContext::new_with_str("bbaa", ()), &vec![], |c, i| {
ParserContext::new_with_str("bbaa", ()), char_parser('a').many().parse(c, i)
&vec![], });
char_parser('a').many(),
);
parser_test_helper( parser_test_helper(ParserContext::new_with_str("", ()), &vec![], |c, i| {
ParserContext::new_with_str("", ()), char_parser('a').many().parse(c, i)
&vec![], });
char_parser('a').many(),
);
} }
#[test] #[test]
@ -219,53 +218,44 @@ mod test {
parser_test_helper( parser_test_helper(
ParserContext::new_with_str("aaa", ()), ParserContext::new_with_str("aaa", ()),
&vec!['a', 'a', 'a'], &vec!['a', 'a', 'a'],
char_parser('a').many1(), |c, i| char_parser('a').many1().parse(c, i),
); );
parser_test_helper( parser_test_helper(
ParserContext::new_with_str("aaabbaa", ()), ParserContext::new_with_str("aaabbaa", ()),
&vec!['a', 'a', 'a'], &vec!['a', 'a', 'a'],
char_parser('a').many1(), |c, i| char_parser('a').many1().parse(c, i),
); );
failed_parser_test_helper( failed_parser_test_helper(ParserContext::new_with_str("bbaa", ()), |c, i| {
ParserContext::new_with_str("bbaa", ()), char_parser('a').many1().parse(c, i)
char_parser('a').many1(), });
);
failed_parser_test_helper( failed_parser_test_helper(ParserContext::new_with_str("", ()), |c, i| {
ParserContext::new_with_str("", ()), char_parser('a').many1().parse(c, i)
char_parser('a').many1(), });
);
} }
#[test] #[test]
fn skip_test() { fn skip_test() {
parser_test_helper( parser_test_helper(ParserContext::new_with_str("aaab", ()), &'b', |c, i| {
ParserContext::new_with_str("aaab", ()), char_parser('a').skip().right(char_parser('b')).parse(c, i)
&'b', });
char_parser('a').skip().right(char_parser('b')),
);
parser_test_helper( parser_test_helper(ParserContext::new_with_str("b", ()), &'b', |c, i| {
ParserContext::new_with_str("b", ()), char_parser('a').skip().right(char_parser('b')).parse(c, i)
&'b', });
char_parser('a').skip().right(char_parser('b')),
);
} }
#[test] #[test]
fn skip1_test() { fn skip1_test() {
parser_test_helper( parser_test_helper(ParserContext::new_with_str("aaab", ()), &'b', |c, i| {
ParserContext::new_with_str("aaab", ()), char_parser('a').skip1().right(char_parser('b')).parse(c, i)
&'b', });
char_parser('a').skip1().right(char_parser('b')),
);
failed_parser_test_helper( failed_parser_test_helper(ParserContext::new_with_str("b", ()), |c, i| {
ParserContext::new_with_str("b", ()), char_parser('a').skip1().right(char_parser('b')).parse(c, i)
char_parser('a').skip1().right(char_parser('b')), });
);
} }
#[test] #[test]
@ -273,19 +263,16 @@ mod test {
parser_test_helper( parser_test_helper(
ParserContext::new_with_str("aaab", ()), ParserContext::new_with_str("aaab", ()),
&vec!['a', 'a', 'a'], &vec!['a', 'a', 'a'],
char_parser('a').many_till(char_parser('b')), |c, i| char_parser('a').many_till(char_parser('b')).parse(c, i),
); );
parser_test_helper( parser_test_helper(ParserContext::new_with_str("b", ()), &vec![], |c, i| {
ParserContext::new_with_str("b", ()), char_parser('a').many_till(char_parser('b')).parse(c, i)
&vec![], });
char_parser('a').many_till(char_parser('b')),
);
failed_parser_test_helper( failed_parser_test_helper(ParserContext::new_with_str("aaacb", ()), |c, i| {
ParserContext::new_with_str("aaacb", ()), char_parser('a').many_till(char_parser('b')).parse(c, i)
char_parser('a').many_till(char_parser('b')), });
);
} }
#[test] #[test]
@ -293,18 +280,16 @@ mod test {
parser_test_helper( parser_test_helper(
ParserContext::new_with_str("aaab", ()), ParserContext::new_with_str("aaab", ()),
&vec!['a', 'a', 'a'], &vec!['a', 'a', 'a'],
char_parser('a').many_till(char_parser('b')), |c, i| char_parser('a').many1_till(char_parser('b')).parse(c, i),
); );
failed_parser_test_helper( failed_parser_test_helper(ParserContext::new_with_str("b", ()), |c, i| {
ParserContext::new_with_str("b", ()), char_parser('a').many1_till(char_parser('b')).parse(c, i)
char_parser('a').many1_till(char_parser('b')), });
);
failed_parser_test_helper( failed_parser_test_helper(ParserContext::new_with_str("aaacb", ()), |c, i| {
ParserContext::new_with_str("aaacb", ()), char_parser('a').many1_till(char_parser('b')).parse(c, i)
char_parser('a').many_till(char_parser('b')), });
);
} }
#[test] #[test]
@ -312,13 +297,13 @@ mod test {
parser_test_helper( parser_test_helper(
ParserContext::new_with_str("aaab", ()), ParserContext::new_with_str("aaab", ()),
&(vec!['a', 'a', 'a'], 'b'), &(vec!['a', 'a', 'a'], 'b'),
tuple((take_till(char_parser('b')), char_parser('b'))), |c, i| tuple((take_till(char_parser('b')), char_parser('b'))).parse(c, i),
); );
parser_test_helper( parser_test_helper(
ParserContext::new_with_str("b", ()), ParserContext::new_with_str("b", ()),
&(vec![], 'b'), &(vec![], 'b'),
tuple((take_till(char_parser('b')), char_parser('b'))), |c, i| tuple((take_till(char_parser('b')), char_parser('b'))).parse(c, i),
); );
} }
@ -327,12 +312,11 @@ mod test {
parser_test_helper( parser_test_helper(
ParserContext::new_with_str("aaab", ()), ParserContext::new_with_str("aaab", ()),
&(vec!['a', 'a', 'a'], 'b'), &(vec!['a', 'a', 'a'], 'b'),
tuple((take1_till(char_parser('b')), char_parser('b'))), |c, i| tuple((take1_till(char_parser('b')), char_parser('b'))).parse(c, i),
); );
failed_parser_test_helper( failed_parser_test_helper(ParserContext::new_with_str("b", ()), |c, i| {
ParserContext::new_with_str("b", ()), tuple((take1_till(char_parser('b')), char_parser('b'))).parse(c, i)
tuple((take1_till(char_parser('b')), char_parser('b'))), });
);
} }
} }

View File

@ -10,14 +10,14 @@ pub struct SeparateBy1Parser<P, PSeparator, TSeparator> {
pub(crate) phantom_data: PhantomData<TSeparator>, pub(crate) phantom_data: PhantomData<TSeparator>,
} }
impl<TToken, T, TSeparator, TContext, P, PSeparator> Parser<TToken, Vec<T>, TContext> impl<'a, TToken, T: 'a, TSeparator: 'a, TContext, P, PSeparator>
for SeparateBy1Parser<P, PSeparator, TSeparator> Parser<'a, TToken, Vec<T>, TContext> for SeparateBy1Parser<P, PSeparator, TSeparator>
where where
TToken: Debug + Clone, TToken: Debug + Clone,
P: Parser<TToken, T, TContext>, P: Parser<'a, TToken, T, TContext>,
PSeparator: Parser<TToken, TSeparator, TContext>, PSeparator: Parser<'a, TToken, TSeparator, TContext>,
{ {
fn parse<'a>( fn parse(
&self, &self,
context: Rc<RefCell<ParserContext<TToken, TContext>>>, context: Rc<RefCell<ParserContext<TToken, TContext>>>,
input: &'a [TToken], input: &'a [TToken],
@ -45,14 +45,14 @@ pub struct SeparateOrEndBy1Parser<P, PSeparator, TSeparator> {
pub(crate) phantom_data: PhantomData<TSeparator>, pub(crate) phantom_data: PhantomData<TSeparator>,
} }
impl<TToken, T, TSeparator, TContext, P, PSeparator> Parser<TToken, Vec<T>, TContext> impl<'a, TToken, T: 'a, TSeparator: 'a, TContext, P, PSeparator>
for SeparateOrEndBy1Parser<P, PSeparator, TSeparator> Parser<'a, TToken, Vec<T>, TContext> for SeparateOrEndBy1Parser<P, PSeparator, TSeparator>
where where
TToken: Debug + Clone, TToken: Debug + Clone,
P: Parser<TToken, T, TContext>, P: Parser<'a, TToken, T, TContext>,
PSeparator: Parser<TToken, TSeparator, TContext>, PSeparator: Parser<'a, TToken, TSeparator, TContext>,
{ {
fn parse<'a>( fn parse(
&self, &self,
context: Rc<RefCell<ParserContext<TToken, TContext>>>, context: Rc<RefCell<ParserContext<TToken, TContext>>>,
input: &'a [TToken], input: &'a [TToken],
@ -114,17 +114,15 @@ mod test {
parser_test_helper( parser_test_helper(
ParserContext::new_with_str("a,b,c", ()), ParserContext::new_with_str("a,b,c", ()),
&vec!['a', 'b', 'c'], &vec!['a', 'b', 'c'],
separate_by1(satisfy(|c: &char| c.is_ascii()), char_parser(',')), |c, i| separate_by1(satisfy(|c: &char| c.is_ascii()), char_parser(',')).parse(c, i),
);
parser_test_helper(
ParserContext::new_with_str("a", ()),
&vec!['a'],
separate_by1(satisfy(|c: &char| c.is_ascii()), char_parser(',')),
); );
parser_test_helper(ParserContext::new_with_str("a", ()), &vec!['a'], |c, i| {
separate_by1(satisfy(|c: &char| c.is_ascii()), char_parser(',')).parse(c, i)
});
parser_test_helper( parser_test_helper(
ParserContext::new_with_str("bbc", ()), ParserContext::new_with_str("bbc", ()),
&vec!['b'], &vec!['b'],
separate_by1(satisfy(|c: &char| c.is_ascii()), char_parser(',')), |c, i| separate_by1(satisfy(|c: &char| c.is_ascii()), char_parser(',')).parse(c, i),
); );
} }
@ -133,22 +131,18 @@ mod test {
parser_test_helper( parser_test_helper(
ParserContext::new_with_str("1,2,3", ()), ParserContext::new_with_str("1,2,3", ()),
&vec!['1', '2', '3'], &vec!['1', '2', '3'],
separate_by(satisfy(|c: &char| c.is_ascii()), char_parser(',')), |c, i| separate_by(satisfy(|c: &char| c.is_ascii()), char_parser(',')).parse(c, i),
);
parser_test_helper(
ParserContext::new_with_str("1", ()),
&vec!['1'],
separate_by(satisfy(|c: &char| c.is_ascii()), char_parser(',')),
);
parser_test_helper(
ParserContext::new_with_str("", ()),
&vec![],
separate_by(satisfy(|c: &char| c.is_ascii()), char_parser(',')),
); );
parser_test_helper(ParserContext::new_with_str("1", ()), &vec!['1'], |c, i| {
separate_by(satisfy(|c: &char| c.is_ascii()), char_parser(',')).parse(c, i)
});
parser_test_helper(ParserContext::new_with_str("", ()), &vec![], |c, i| {
separate_by(satisfy(|c: &char| c.is_ascii()), char_parser(',')).parse(c, i)
});
parser_test_helper( parser_test_helper(
ParserContext::new_with_str("abc", ()), ParserContext::new_with_str("abc", ()),
&vec!['a'], &vec!['a'],
separate_by(satisfy(|c: &char| c.is_ascii()), char_parser(',')), |c, i| separate_by(satisfy(|c: &char| c.is_ascii()), char_parser(',')).parse(c, i),
); );
} }
@ -157,21 +151,17 @@ mod test {
parser_test_helper( parser_test_helper(
ParserContext::new_with_str("aab", ()), ParserContext::new_with_str("aab", ()),
&vec!['a', 'a'], &vec!['a', 'a'],
end_by1(char_parser('a'), char_parser('b')), |c, i| end_by1(char_parser('a'), char_parser('b')).parse(c, i),
);
parser_test_helper(
ParserContext::new_with_str("ab", ()),
&vec!['a'],
end_by1(char_parser('a'), char_parser('b')),
);
failed_parser_test_helper(
ParserContext::new_with_str("b", ()),
end_by1(char_parser('a'), char_parser('b')),
);
failed_parser_test_helper(
ParserContext::new_with_str("cd", ()),
end_by1(char_parser('a'), char_parser('b')),
); );
parser_test_helper(ParserContext::new_with_str("ab", ()), &vec!['a'], |c, i| {
end_by1(char_parser('a'), char_parser('b')).parse(c, i)
});
failed_parser_test_helper(ParserContext::new_with_str("b", ()), |c, i| {
end_by1(char_parser('a'), char_parser('b')).parse(c, i)
});
failed_parser_test_helper(ParserContext::new_with_str("cd", ()), |c, i| {
end_by1(char_parser('a'), char_parser('b')).parse(c, i)
});
} }
#[test] #[test]
@ -179,22 +169,17 @@ mod test {
parser_test_helper( parser_test_helper(
ParserContext::new_with_str("aab", ()), ParserContext::new_with_str("aab", ()),
&vec!['a', 'a'], &vec!['a', 'a'],
end_by(char_parser('a'), char_parser('b')), |c, i| end_by(char_parser('a'), char_parser('b')).parse(c, i),
);
parser_test_helper(
ParserContext::new_with_str("ab", ()),
&vec!['a'],
end_by(char_parser('a'), char_parser('b')),
);
parser_test_helper(
ParserContext::new_with_str("b", ()),
&vec![],
end_by(char_parser('a'), char_parser('b')),
);
failed_parser_test_helper(
ParserContext::new_with_str("cd", ()),
end_by(char_parser('a'), char_parser('b')),
); );
parser_test_helper(ParserContext::new_with_str("ab", ()), &vec!['a'], |c, i| {
end_by(char_parser('a'), char_parser('b')).parse(c, i)
});
parser_test_helper(ParserContext::new_with_str("b", ()), &vec![], |c, i| {
end_by(char_parser('a'), char_parser('b')).parse(c, i)
});
failed_parser_test_helper(ParserContext::new_with_str("cd", ()), |c, i| {
end_by(char_parser('a'), char_parser('b')).parse(c, i)
});
} }
#[test] #[test]
@ -202,27 +187,28 @@ mod test {
parser_test_helper( parser_test_helper(
ParserContext::new_with_str("1,2,3,", ()), ParserContext::new_with_str("1,2,3,", ()),
&vec!['1', '2', '3'], &vec!['1', '2', '3'],
separate_or_end_by1(satisfy(|c: &char| c.is_numeric()), char_parser(',')), |c, i| {
); separate_or_end_by1(satisfy(|c: &char| c.is_numeric()), char_parser(','))
parser_test_helper( .parse(c, i)
ParserContext::new_with_str("1,", ()), },
&vec!['1'],
separate_or_end_by1(satisfy(|c: &char| c.is_numeric()), char_parser(',')),
); );
parser_test_helper(ParserContext::new_with_str("1,", ()), &vec!['1'], |c, i| {
separate_or_end_by1(satisfy(|c: &char| c.is_numeric()), char_parser(',')).parse(c, i)
});
parser_test_helper( parser_test_helper(
ParserContext::new_with_str("1,2,3", ()), ParserContext::new_with_str("1,2,3", ()),
&vec!['1', '2', '3'], &vec!['1', '2', '3'],
separate_or_end_by1(satisfy(|c: &char| c.is_numeric()), char_parser(',')), |c, i| {
); separate_or_end_by1(satisfy(|c: &char| c.is_numeric()), char_parser(','))
parser_test_helper( .parse(c, i)
ParserContext::new_with_str("1", ()), },
&vec!['1'],
separate_or_end_by1(satisfy(|c: &char| c.is_numeric()), char_parser(',')),
);
failed_parser_test_helper(
ParserContext::new_with_str("abc", ()),
separate_or_end_by1(satisfy(|c: &char| c.is_numeric()), char_parser(',')),
); );
parser_test_helper(ParserContext::new_with_str("1", ()), &vec!['1'], |c, i| {
separate_or_end_by1(satisfy(|c: &char| c.is_numeric()), char_parser(',')).parse(c, i)
});
failed_parser_test_helper(ParserContext::new_with_str("abc", ()), |c, i| {
separate_or_end_by1(satisfy(|c: &char| c.is_numeric()), char_parser(',')).parse(c, i)
});
} }
#[test] #[test]
@ -230,27 +216,25 @@ mod test {
parser_test_helper( parser_test_helper(
ParserContext::new_with_str("1,2,3,", ()), ParserContext::new_with_str("1,2,3,", ()),
&vec!['1', '2', '3'], &vec!['1', '2', '3'],
separate_or_end_by(satisfy(|c: &char| c.is_numeric()), char_parser(',')), |c, i| {
); separate_or_end_by(satisfy(|c: &char| c.is_numeric()), char_parser(',')).parse(c, i)
parser_test_helper( },
ParserContext::new_with_str("1,", ()),
&vec!['1'],
separate_or_end_by(satisfy(|c: &char| c.is_numeric()), char_parser(',')),
); );
parser_test_helper(ParserContext::new_with_str("1,", ()), &vec!['1'], |c, i| {
separate_or_end_by(satisfy(|c: &char| c.is_numeric()), char_parser(',')).parse(c, i)
});
parser_test_helper( parser_test_helper(
ParserContext::new_with_str("1,2,3", ()), ParserContext::new_with_str("1,2,3", ()),
&vec!['1', '2', '3'], &vec!['1', '2', '3'],
separate_or_end_by(satisfy(|c: &char| c.is_numeric()), char_parser(',')), |c, i| {
); separate_or_end_by(satisfy(|c: &char| c.is_numeric()), char_parser(',')).parse(c, i)
parser_test_helper( },
ParserContext::new_with_str("1", ()),
&vec!['1'],
separate_or_end_by(satisfy(|c: &char| c.is_numeric()), char_parser(',')),
);
parser_test_helper(
ParserContext::new_with_str("abc", ()),
&vec![],
separate_or_end_by(satisfy(|c: &char| c.is_numeric()), char_parser(',')),
); );
parser_test_helper(ParserContext::new_with_str("1", ()), &vec!['1'], |c, i| {
separate_or_end_by(satisfy(|c: &char| c.is_numeric()), char_parser(',')).parse(c, i)
});
parser_test_helper(ParserContext::new_with_str("abc", ()), &vec![], |c, i| {
separate_or_end_by(satisfy(|c: &char| c.is_numeric()), char_parser(',')).parse(c, i)
});
} }
} }

View File

@ -3,24 +3,43 @@ use std::cell::RefCell;
use std::fmt::Debug; use std::fmt::Debug;
use std::rc::Rc; use std::rc::Rc;
pub trait ParserTuple<TToken, T, TContext> pub trait ParserTuple<'a, TToken, T: 'a, TContext>
where where
TToken: Debug + Clone, TToken: Debug + Clone,
{ {
fn parse<'a>( fn parse(
&self, &self,
context: Rc<RefCell<ParserContext<TToken, TContext>>>, context: Rc<RefCell<ParserContext<TToken, TContext>>>,
input: &'a [TToken], input: &'a [TToken],
) -> ParserResult<'a, TToken, T>; ) -> ParserResult<'a, TToken, T>;
} }
impl<TToken, T1, T2, TContext, P1, P2> ParserTuple<TToken, (T1, T2), TContext> for (P1, P2) pub struct TupleParser<P> {
pub(crate) parser: P,
}
impl<'a, TToken, T: 'a, TContext, P> Parser<'a, TToken, T, TContext> for TupleParser<P>
where where
TToken: Debug + Clone, TToken: Debug + Clone,
P1: Parser<TToken, T1, TContext>, P: ParserTuple<'a, TToken, T, TContext>,
P2: Parser<TToken, T2, TContext>,
{ {
fn parse<'a>( fn parse(
&self,
context: Rc<RefCell<ParserContext<TToken, TContext>>>,
input: &'a [TToken],
) -> ParserResult<'a, TToken, T> {
self.parser.parse(context, input)
}
}
impl<'a, TToken, T1: 'a, T2: 'a, TContext, P1, P2> ParserTuple<'a, TToken, (T1, T2), TContext>
for (P1, P2)
where
TToken: Debug + Clone,
P1: Parser<'a, TToken, T1, TContext>,
P2: Parser<'a, TToken, T2, TContext>,
{
fn parse(
&self, &self,
context: Rc<RefCell<ParserContext<TToken, TContext>>>, context: Rc<RefCell<ParserContext<TToken, TContext>>>,
input: &'a [TToken], input: &'a [TToken],
@ -32,15 +51,15 @@ where
} }
} }
impl<TToken, T1, T2, T3, TContext, P1, P2, P3> ParserTuple<TToken, (T1, T2, T3), TContext> impl<'a, TToken, T1: 'a, T2: 'a, T3: 'a, TContext, P1, P2, P3>
for (P1, P2, P3) ParserTuple<'a, TToken, (T1, T2, T3), TContext> for (P1, P2, P3)
where where
TToken: Debug + Clone, TToken: Debug + Clone,
P1: Parser<TToken, T1, TContext>, P1: Parser<'a, TToken, T1, TContext>,
P2: Parser<TToken, T2, TContext>, P2: Parser<'a, TToken, T2, TContext>,
P3: Parser<TToken, T3, TContext>, P3: Parser<'a, TToken, T3, TContext>,
{ {
fn parse<'a>( fn parse(
&self, &self,
context: Rc<RefCell<ParserContext<TToken, TContext>>>, context: Rc<RefCell<ParserContext<TToken, TContext>>>,
input: &'a [TToken], input: &'a [TToken],
@ -53,16 +72,16 @@ where
} }
} }
impl<TToken, T1, T2, T3, T4, TContext, P1, P2, P3, P4> impl<'a, TToken, T1: 'a, T2: 'a, T3: 'a, T4: 'a, TContext, P1, P2, P3, P4>
ParserTuple<TToken, (T1, T2, T3, T4), TContext> for (P1, P2, P3, P4) ParserTuple<'a, TToken, (T1, T2, T3, T4), TContext> for (P1, P2, P3, P4)
where where
TToken: Debug + Clone, TToken: Debug + Clone,
P1: Parser<TToken, T1, TContext>, P1: Parser<'a, TToken, T1, TContext>,
P2: Parser<TToken, T2, TContext>, P2: Parser<'a, TToken, T2, TContext>,
P3: Parser<TToken, T3, TContext>, P3: Parser<'a, TToken, T3, TContext>,
P4: Parser<TToken, T4, TContext>, P4: Parser<'a, TToken, T4, TContext>,
{ {
fn parse<'a>( fn parse(
&self, &self,
context: Rc<RefCell<ParserContext<TToken, TContext>>>, context: Rc<RefCell<ParserContext<TToken, TContext>>>,
input: &'a [TToken], input: &'a [TToken],
@ -76,17 +95,17 @@ where
} }
} }
impl<TToken, T1, T2, T3, T4, T5, TContext, P1, P2, P3, P4, P5> impl<'a, TToken, T1: 'a, T2: 'a, T3: 'a, T4: 'a, T5: 'a, TContext, P1, P2, P3, P4, P5>
ParserTuple<TToken, (T1, T2, T3, T4, T5), TContext> for (P1, P2, P3, P4, P5) ParserTuple<'a, TToken, (T1, T2, T3, T4, T5), TContext> for (P1, P2, P3, P4, P5)
where where
TToken: Debug + Clone, TToken: Debug + Clone,
P1: Parser<TToken, T1, TContext>, P1: Parser<'a, TToken, T1, TContext>,
P2: Parser<TToken, T2, TContext>, P2: Parser<'a, TToken, T2, TContext>,
P3: Parser<TToken, T3, TContext>, P3: Parser<'a, TToken, T3, TContext>,
P4: Parser<TToken, T4, TContext>, P4: Parser<'a, TToken, T4, TContext>,
P5: Parser<TToken, T5, TContext>, P5: Parser<'a, TToken, T5, TContext>,
{ {
fn parse<'a>( fn parse(
&self, &self,
context: Rc<RefCell<ParserContext<TToken, TContext>>>, context: Rc<RefCell<ParserContext<TToken, TContext>>>,
input: &'a [TToken], input: &'a [TToken],
@ -113,24 +132,27 @@ mod test {
parser_test_helper( parser_test_helper(
ParserContext::new_with_str("ab", ()), ParserContext::new_with_str("ab", ()),
&('a', 'b'), &('a', 'b'),
tuple((char_parser('a'), char_parser('b'))), |c, i| tuple((char_parser('a'), char_parser('b'))).parse(c, i),
); );
parser_test_helper( parser_test_helper(
ParserContext::new_with_str("abc", ()), ParserContext::new_with_str("abc", ()),
&('a', 'b', 'c'), &('a', 'b', 'c'),
tuple((char_parser('a'), char_parser('b'), char_parser('c'))), |c, i| tuple((char_parser('a'), char_parser('b'), char_parser('c'))).parse(c, i),
); );
parser_test_helper( parser_test_helper(
ParserContext::new_with_str("abcd", ()), ParserContext::new_with_str("abcd", ()),
&('a', 'b', 'c', 'd'), &('a', 'b', 'c', 'd'),
|c, i| {
tuple(( tuple((
char_parser('a'), char_parser('a'),
char_parser('b'), char_parser('b'),
char_parser('c'), char_parser('c'),
char_parser('d'), char_parser('d'),
)), ))
.parse(c, i)
},
); );
} }
} }

View File

@ -1,3 +1,3 @@
mod parser; pub mod combinators;
mod text; pub mod parser;
mod combinators; pub mod text;

View File

@ -2,8 +2,8 @@ mod modified_parsers;
mod primitive_parsers; mod primitive_parsers;
use crate::parser::modified_parsers::{ use crate::parser::modified_parsers::{
BindParser, ConvertParser, LitervalParser, LookAheadParser, MapParser, NextParser, BindParser, ConvertParser, LitervalCountParser, LitervalParser, LookAheadParser, MapParser,
ReverseParser, NextParser, ReverseParser,
}; };
use crate::parser::primitive_parsers::{ use crate::parser::primitive_parsers::{
AnyParser, FailParser, FailWithMessageParser, SatisfyParser, SkipParser, SucceedParser, AnyParser, FailParser, FailWithMessageParser, SatisfyParser, SkipParser, SucceedParser,
@ -23,6 +23,10 @@ impl FailedParserResult {
pub fn new(message: String) -> Self { pub fn new(message: String) -> Self {
Self { message } Self { message }
} }
pub fn message(&self) -> &str {
self.message.as_str()
}
} }
impl Display for FailedParserResult { impl Display for FailedParserResult {
@ -67,11 +71,12 @@ impl<TContext> ParserContext<char, TContext> {
} }
} }
pub trait Parser<TToken, T, TContext> pub trait Parser<'a, TToken, T, TContext>
where where
TToken: Debug + Clone, TToken: Debug + Clone,
T: 'a,
{ {
fn parse<'a>( fn parse(
&self, &self,
context: Rc<RefCell<ParserContext<TToken, TContext>>>, context: Rc<RefCell<ParserContext<TToken, TContext>>>,
input: &'a [TToken], input: &'a [TToken],
@ -80,7 +85,7 @@ where
fn map<TResult, F>(self, f: F) -> MapParser<Self, F, T> fn map<TResult, F>(self, f: F) -> MapParser<Self, F, T>
where where
Self: Sized, Self: Sized,
F: Fn(&T) -> TResult, F: Fn(T) -> TResult,
{ {
MapParser { MapParser {
parser: self, parser: self,
@ -89,11 +94,11 @@ where
} }
} }
fn bind<TResult, F, P>(self, f: F) -> BindParser<Self, F, T> fn bind<TResult: 'a, F, P>(self, f: F) -> BindParser<Self, F, T>
where where
Self: Sized, Self: Sized,
F: Fn(T) -> P, F: Fn(T) -> P,
P: Parser<TToken, TResult, TContext>, P: Parser<'a, TToken, TResult, TContext>,
{ {
BindParser { BindParser {
parser: self, parser: self,
@ -125,6 +130,16 @@ where
} }
} }
fn literal_count(self) -> LitervalCountParser<Self, T>
where
Self: Sized,
{
LitervalCountParser {
parser: self,
phantom_data: PhantomData,
}
}
fn literal(self) -> LitervalParser<Self, T> fn literal(self) -> LitervalParser<Self, T>
where where
Self: Sized, Self: Sized,
@ -158,15 +173,15 @@ where
} }
} }
impl<TToken, T, TContext, F> Parser<TToken, T, TContext> for F impl<'a, TToken, T: 'a, TContext, F> Parser<'a, TToken, T, TContext> for F
where where
TToken: Debug + Clone, TToken: Debug + Clone + 'a,
F: for<'f> Fn( F: Fn(
Rc<RefCell<ParserContext<TToken, TContext>>>, Rc<RefCell<ParserContext<TToken, TContext>>>,
&'f [TToken], &'a [TToken],
) -> ParserResult<'f, TToken, T>, ) -> ParserResult<'a, TToken, T>,
{ {
fn parse<'a>( fn parse(
&self, &self,
context: Rc<RefCell<ParserContext<TToken, TContext>>>, context: Rc<RefCell<ParserContext<TToken, TContext>>>,
input: &'a [TToken], input: &'a [TToken],
@ -175,11 +190,12 @@ where
} }
} }
impl<TToken, T, TContext> Parser<TToken, T, TContext> for Box<dyn Parser<TToken, T, TContext>> impl<'a, TToken, T: 'a, TContext> Parser<'a, TToken, T, TContext>
for Box<dyn Parser<'a, TToken, T, TContext>>
where where
TToken: Debug + Clone, TToken: Debug + Clone,
{ {
fn parse<'a>( fn parse(
&self, &self,
context: Rc<RefCell<ParserContext<TToken, TContext>>>, context: Rc<RefCell<ParserContext<TToken, TContext>>>,
input: &'a [TToken], input: &'a [TToken],
@ -188,15 +204,15 @@ where
} }
} }
pub fn succeed<TToken, T, TContext>(value: T) -> impl Parser<TToken, T, TContext> pub fn succeed<'a, TToken, T, TContext>(value: T) -> impl Parser<'a, TToken, T, TContext>
where where
TToken: Debug + Clone, TToken: Debug + Clone,
T: Debug + Clone, T: Debug + Clone + 'a,
{ {
SucceedParser { value } SucceedParser { value }
} }
pub fn fail<TToken, T, TContext>() -> impl Parser<TToken, T, TContext> pub fn fail<'a, TToken, T: 'a, TContext>() -> impl Parser<'a, TToken, T, TContext>
where where
TToken: Debug + Clone, TToken: Debug + Clone,
{ {
@ -205,7 +221,9 @@ where
} }
} }
pub fn fail_with_message<TToken, T, TContext>(message: &str) -> impl Parser<TToken, T, TContext> pub fn fail_with_message<'a, TToken, T: 'a, TContext>(
message: &str,
) -> impl Parser<'a, TToken, T, TContext>
where where
TToken: Debug + Clone, TToken: Debug + Clone,
{ {
@ -215,29 +233,29 @@ where
} }
} }
pub fn satisfy<TToken, TContext, TP>(predicate: TP) -> impl Parser<TToken, TToken, TContext> pub fn satisfy<'a, TToken, TContext, TP>(predicate: TP) -> impl Parser<'a, TToken, TToken, TContext>
where where
TToken: Debug + Clone, TToken: Debug + Clone + 'a,
TP: Fn(&TToken) -> bool, TP: Fn(&TToken) -> bool,
{ {
SatisfyParser { predicate } SatisfyParser { predicate }
} }
pub fn any<TToken, TContext>() -> impl Parser<TToken, TToken, TContext> pub fn any<'a, TToken, TContext>() -> impl Parser<'a, TToken, TToken, TContext>
where where
TToken: Debug + Clone, TToken: Debug + Clone + 'a,
{ {
AnyParser {} AnyParser {}
} }
pub fn take<TToken, TContext>(count: usize) -> impl Parser<TToken, Vec<TToken>, TContext> pub fn take<'a, TToken, TContext>(count: usize) -> impl Parser<'a, TToken, Vec<TToken>, TContext>
where where
TToken: Debug + Clone, TToken: Debug + Clone + 'a,
{ {
TakeParser { count } TakeParser { count }
} }
pub fn skip<TToken, TContext>(count: usize) -> impl Parser<TToken, (), TContext> pub fn skip<'a, TToken, TContext>(count: usize) -> impl Parser<'a, TToken, (), TContext>
where where
TToken: Debug + Clone, TToken: Debug + Clone,
{ {
@ -251,7 +269,7 @@ pub fn parser_test_helper<T, P>(
test_parser: P, test_parser: P,
) where ) where
T: PartialEq + Debug, T: PartialEq + Debug,
P: Parser<char, T, ()>, P: for<'a> Fn(Rc<RefCell<ParserContext<char, ()>>>, &'a [char]) -> ParserResult<'a, char, T>,
{ {
let borrowed_context = context.borrow(); let borrowed_context = context.borrow();
let input = borrowed_context.input_slice(); let input = borrowed_context.input_slice();
@ -266,7 +284,7 @@ pub fn failed_parser_test_helper<T, P>(
test_parser: P, test_parser: P,
) where ) where
T: Debug, T: Debug,
P: Parser<char, T, ()>, P: for<'a> Fn(Rc<RefCell<ParserContext<char, ()>>>, &'a [char]) -> ParserResult<'a, char, T>,
{ {
let borrowed_context = context.borrow(); let borrowed_context = context.borrow();
let input = borrowed_context.input_slice(); let input = borrowed_context.input_slice();

View File

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

View File

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

View File

@ -1,14 +1,13 @@
use crate::parser::{satisfy, take, FailedParserResult, Parser}; use crate::parser::{satisfy, take, FailedParserResult, Parser};
pub fn char_parser<TContext>(c: char) -> impl Parser<char, char, TContext> { pub fn char_parser<'a, TContext>(c: char) -> impl Parser<'a, char, char, TContext> {
satisfy(move |x| *x == c) satisfy(move |x| *x == c)
} }
pub fn string_parser<TContext>(str: String) -> impl Parser<char, String, TContext> { pub fn string_parser<'a, TContext>(str: &'static str) -> impl Parser<'a, char, String, TContext> {
take::<char, TContext>(str.len()).next(move |result| { take::<char, TContext>(str.chars().count()).next(move |result| {
result.and_then(|(input, chars)| { result.and_then(|(input, chars)| {
let chars: String = chars.into_iter().collect(); let chars: String = chars.iter().collect();
if chars == str { if chars == str {
Ok((input, chars)) Ok((input, chars))
} else { } else {
@ -21,6 +20,11 @@ pub fn string_parser<TContext>(str: String) -> impl Parser<char, String, TContex
}) })
} }
pub fn one_of<'a, TContext>(str: &'static str) -> impl Parser<'a, char, char, TContext> {
let str: Vec<char> = str.chars().collect();
satisfy(move |c: &char| str.contains(c))
}
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*; use super::*;
@ -35,10 +39,12 @@ mod test {
parser_test_helper( parser_test_helper(
ParserContext::new_with_str("abc", ()), ParserContext::new_with_str("abc", ()),
&'a', &'a',
char_parser('a'), |context, input| char_parser('a').parse(context, input),
); );
failed_parser_test_helper(ParserContext::new_with_str("bc", ()), char_parser('a')); failed_parser_test_helper(ParserContext::new_with_str("bc", ()), |context, input| {
char_parser('a').parse(context, input)
});
} }
#[test] #[test]
@ -46,17 +52,15 @@ mod test {
parser_test_helper( parser_test_helper(
ParserContext::new_with_str("Hello, world!", ()), ParserContext::new_with_str("Hello, world!", ()),
&"Hello".to_owned(), &"Hello".to_owned(),
string_parser("Hello".to_owned()), |context, input| string_parser("Hello").parse(context, input),
); );
fn test_parser( fn test_parser(
context: Rc<RefCell<ParserContext<char, ()>>>, context: Rc<RefCell<ParserContext<char, ()>>>,
input: &[char], input: &[char],
) -> ParserResult<char, String> { ) -> ParserResult<char, String> {
let (input, first) = let (input, first) = string_parser("hello, ").parse(context.clone(), input)?;
string_parser("hello, ".to_string()).parse(context.clone(), input)?; let (input, second) = string_parser("world!").parse(context.clone(), input)?;
let (input, second) =
string_parser("world!".to_owned()).parse(context.clone(), input)?;
Ok((input, first + second.as_str())) Ok((input, first + second.as_str()))
} }
@ -69,7 +73,7 @@ mod test {
parser_test_helper( parser_test_helper(
ParserContext::new_with_str("hello, world!", ()), ParserContext::new_with_str("hello, world!", ()),
&(), &(),
test_parser.map(|_| ()), |context, input| test_parser.map(|_| ()).parse(context, input),
) )
} }
} }