refact: lifetime support in trait level.
This commit is contained in:
parent
8a9c58966b
commit
a282ad8f24
32
Cargo.lock
generated
32
Cargo.lock
generated
|
@ -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",
|
||||||
|
]
|
||||||
|
|
|
@ -4,3 +4,7 @@ version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
anyhow = { version = "1" }
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
nom = { version = "7" }
|
|
@ -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![])),
|
||||||
|
|
|
@ -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)
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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')),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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'))),
|
});
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
mod parser;
|
pub mod combinators;
|
||||||
mod text;
|
pub mod parser;
|
||||||
mod combinators;
|
pub mod text;
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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(()),
|
});
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
30
src/text.rs
30
src/text.rs
|
@ -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),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user