281 lines
7.1 KiB
Rust
281 lines
7.1 KiB
Rust
mod alternate_parser;
|
|
mod left_right_parsers;
|
|
mod many_parsers;
|
|
mod separated_parsers;
|
|
mod tuple_parser;
|
|
|
|
use crate::combinators::alternate_parser::AlternateParser;
|
|
use crate::combinators::left_right_parsers::{LeftParser, RightParser};
|
|
use crate::combinators::many_parsers::{
|
|
Many1Parser, Many1TillParser, ManyParser, ManyTillParser, Skip1Parser, SkipParser,
|
|
};
|
|
use crate::combinators::separated_parsers::{SeparateBy1Parser, SeparateOrEndBy1Parser};
|
|
use crate::combinators::tuple_parser::{ParserTuple, TupleParser};
|
|
use crate::parser::{any, Parser};
|
|
use std::fmt::Debug;
|
|
use std::marker::PhantomData;
|
|
|
|
pub trait ParserExt<'a, TToken, T: 'a, TContext>: Parser<'a, TToken, T, TContext>
|
|
where
|
|
TToken: Debug + Clone,
|
|
{
|
|
fn left<TRight: 'a, PRight>(self, right_parser: PRight) -> LeftParser<Self, PRight, TRight>
|
|
where
|
|
Self: Sized,
|
|
PRight: Parser<'a, TToken, TRight, TContext>,
|
|
{
|
|
LeftParser {
|
|
left_parser: self,
|
|
right_parser,
|
|
phantom_data: PhantomData,
|
|
}
|
|
}
|
|
|
|
fn right<TRight: 'a, PRight>(self, right_parser: PRight) -> RightParser<Self, PRight, T>
|
|
where
|
|
Self: Sized,
|
|
PRight: Parser<'a, TToken, TRight, TContext>,
|
|
{
|
|
RightParser {
|
|
left_parser: self,
|
|
right_parser,
|
|
phantom_data: PhantomData,
|
|
}
|
|
}
|
|
|
|
fn alternate<P>(self, second_parser: P) -> AlternateParser<Self, P>
|
|
where
|
|
Self: Sized,
|
|
P: Parser<'a, TToken, T, TContext>,
|
|
{
|
|
AlternateParser {
|
|
first: self,
|
|
second: second_parser,
|
|
}
|
|
}
|
|
|
|
fn many(self) -> ManyParser<Self>
|
|
where
|
|
Self: Sized,
|
|
{
|
|
ManyParser { parser: self }
|
|
}
|
|
|
|
fn many1(self) -> Many1Parser<Self>
|
|
where
|
|
Self: Sized,
|
|
{
|
|
Many1Parser { parser: self }
|
|
}
|
|
|
|
fn skip(self) -> SkipParser<Self, T>
|
|
where
|
|
Self: Sized,
|
|
{
|
|
SkipParser {
|
|
parser: self,
|
|
phantom_data: PhantomData,
|
|
}
|
|
}
|
|
|
|
fn skip1(self) -> Skip1Parser<Self, T>
|
|
where
|
|
Self: Sized,
|
|
{
|
|
Skip1Parser {
|
|
parser: self,
|
|
phantom_data: PhantomData,
|
|
}
|
|
}
|
|
|
|
fn many_till<TTerminator: 'a, PTerminator>(
|
|
self,
|
|
terminator: PTerminator,
|
|
) -> ManyTillParser<Self, PTerminator, TTerminator>
|
|
where
|
|
Self: Sized,
|
|
PTerminator: Parser<'a, TToken, TTerminator, TContext>,
|
|
{
|
|
ManyTillParser {
|
|
parser: self,
|
|
terminator,
|
|
phantom_data: PhantomData,
|
|
}
|
|
}
|
|
|
|
fn many1_till<TTerminator: 'a, PTerminator>(
|
|
self,
|
|
terminator: PTerminator,
|
|
) -> Many1TillParser<Self, PTerminator, TTerminator>
|
|
where
|
|
Self: Sized,
|
|
PTerminator: Parser<'a, TToken, TTerminator, TContext>,
|
|
{
|
|
Many1TillParser {
|
|
parser: self,
|
|
terminator,
|
|
phantom_data: PhantomData,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<'a, TToken, T: 'a, TContext, P> ParserExt<'a, TToken, T, TContext> for P
|
|
where
|
|
TToken: Debug + Clone,
|
|
P: Parser<'a, TToken, T, TContext>,
|
|
{
|
|
}
|
|
|
|
pub fn alternate_helper<'a, TToken, T: 'a, TContext, P1, P2>(
|
|
first: P1,
|
|
second: P2,
|
|
) -> AlternateParser<P1, P2>
|
|
where
|
|
TToken: Debug + Clone,
|
|
P1: Parser<'a, TToken, T, TContext>,
|
|
P2: Parser<'a, TToken, T, TContext>,
|
|
{
|
|
AlternateParser { first, second }
|
|
}
|
|
|
|
#[macro_export]
|
|
macro_rules! alternate {
|
|
($first:expr, $( $second:expr ),*) => {
|
|
{
|
|
let parser = $first;
|
|
$(
|
|
let parser = $crate::combinators::alternate_helper(parser, $second);
|
|
)*
|
|
parser
|
|
}
|
|
};
|
|
}
|
|
|
|
pub fn tuple<'a, TToken, T: 'a, TContext, TList>(list: TList) -> TupleParser<TList>
|
|
where
|
|
TToken: Debug + Clone + 'a,
|
|
TList: ParserTuple<'a, TToken, T, TContext>,
|
|
{
|
|
TupleParser { parser: list }
|
|
}
|
|
|
|
pub fn take_till<'a, TToken, TTerminator: 'a, TContext, PTerminator>(
|
|
termiantor: PTerminator,
|
|
) -> impl Parser<'a, TToken, Vec<TToken>, TContext>
|
|
where
|
|
TToken: Debug + Clone + 'a,
|
|
PTerminator: Parser<'a, TToken, TTerminator, TContext>,
|
|
{
|
|
any().many_till(termiantor)
|
|
}
|
|
|
|
pub fn take1_till<'a, TToken, TTerminator: 'a, TContext, PTerminator>(
|
|
terminator: PTerminator,
|
|
) -> impl Parser<'a, TToken, Vec<TToken>, TContext>
|
|
where
|
|
TToken: Debug + Clone + 'a,
|
|
PTerminator: Parser<'a, TToken, TTerminator, TContext>,
|
|
{
|
|
any().many1_till(terminator)
|
|
}
|
|
|
|
pub fn quote<'a, TToken, T: 'a, TLeft: 'a, TRight: 'a, TContext, PLeft, P, PRight>(
|
|
left: PLeft,
|
|
parser: P,
|
|
right: PRight,
|
|
) -> impl Parser<'a, TToken, Vec<T>, TContext>
|
|
where
|
|
TToken: Debug + Clone + 'a,
|
|
P: Parser<'a, TToken, T, TContext>,
|
|
PLeft: Parser<'a, TToken, TLeft, TContext>,
|
|
PRight: Parser<'a, TToken, TRight, TContext>,
|
|
{
|
|
left.right(parser.many_till(right))
|
|
}
|
|
|
|
pub fn separate_by1<'a, TToken, T: 'a, TSeparator: 'a, TContext, P, PSeparator>(
|
|
parser: P,
|
|
separator: PSeparator,
|
|
) -> impl Parser<'a, TToken, Vec<T>, TContext>
|
|
where
|
|
TToken: Debug + Clone + 'a,
|
|
P: Parser<'a, TToken, T, TContext>,
|
|
PSeparator: Parser<'a, TToken, TSeparator, TContext>,
|
|
{
|
|
SeparateBy1Parser {
|
|
parser,
|
|
separator,
|
|
phantom_data: PhantomData,
|
|
}
|
|
}
|
|
|
|
pub fn separate_by<'a, TToken, T: 'a, TSeparator: 'a, TContext, P, PSeparator>(
|
|
parser: P,
|
|
separator: PSeparator,
|
|
) -> impl Parser<'a, TToken, Vec<T>, TContext>
|
|
where
|
|
TToken: Debug + Clone + 'a,
|
|
P: Parser<'a, TToken, T, TContext>,
|
|
PSeparator: Parser<'a, TToken, TSeparator, TContext>,
|
|
{
|
|
separate_by1(parser, separator).next(|r| match r {
|
|
Err((input, _)) => Ok((input, vec![])),
|
|
r => r,
|
|
})
|
|
}
|
|
|
|
pub fn end_by1<'a, TToken, T: 'a, TSeparator: 'a, TContext, P, PSeparator>(
|
|
parser: P,
|
|
separator: PSeparator,
|
|
) -> impl Parser<'a, TToken, Vec<T>, TContext>
|
|
where
|
|
TToken: Debug + Clone + 'a,
|
|
P: Parser<'a, TToken, T, TContext>,
|
|
PSeparator: Parser<'a, TToken, TSeparator, TContext>,
|
|
{
|
|
parser.many1_till(separator)
|
|
}
|
|
|
|
pub fn end_by<'a, TToken, T: 'a, TSeparator: 'a, TContext, P, PSeparator>(
|
|
parser: P,
|
|
separator: PSeparator,
|
|
) -> impl Parser<'a, TToken, Vec<T>, TContext>
|
|
where
|
|
TToken: Debug + Clone + 'a,
|
|
P: Parser<'a, TToken, T, TContext>,
|
|
PSeparator: Parser<'a, TToken, TSeparator, TContext>,
|
|
{
|
|
parser.many_till(separator)
|
|
}
|
|
|
|
pub fn separate_or_end_by1<'a, TToken, T: 'a, TSeparator: 'a, TContext, P, PSeparator>(
|
|
parser: P,
|
|
separator: PSeparator,
|
|
) -> impl Parser<'a, TToken, Vec<T>, TContext>
|
|
where
|
|
TToken: Debug + Clone + 'a,
|
|
P: Parser<'a, TToken, T, TContext>,
|
|
PSeparator: Parser<'a, TToken, TSeparator, TContext>,
|
|
{
|
|
SeparateOrEndBy1Parser {
|
|
parser,
|
|
separator,
|
|
phantom_data: PhantomData,
|
|
}
|
|
}
|
|
|
|
pub fn separate_or_end_by<'a, TToken, T: 'a, TSeparator: 'a, TContext, P, PSeparator>(
|
|
parser: P,
|
|
separator: PSeparator,
|
|
) -> impl Parser<'a, TToken, Vec<T>, TContext>
|
|
where
|
|
TToken: Debug + Clone + 'a,
|
|
P: Parser<'a, TToken, T, TContext>,
|
|
PSeparator: Parser<'a, TToken, TSeparator, TContext>,
|
|
{
|
|
separate_or_end_by1(parser, separator).next(|r| match r {
|
|
Err((i, _)) => Ok((i, vec![])),
|
|
r => r,
|
|
})
|
|
}
|