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(self, right_parser: PRight) -> LeftParser where Self: Sized, PRight: Parser<'a, TToken, TRight, TContext>, { LeftParser { left_parser: self, right_parser, phantom_data: PhantomData, } } fn right(self, right_parser: PRight) -> RightParser where Self: Sized, PRight: Parser<'a, TToken, TRight, TContext>, { RightParser { left_parser: self, right_parser, phantom_data: PhantomData, } } fn alternate

(self, second_parser: P) -> AlternateParser where Self: Sized, P: Parser<'a, TToken, T, TContext>, { AlternateParser { first: self, second: second_parser, } } fn many(self) -> ManyParser where Self: Sized, { ManyParser { parser: self } } fn many1(self) -> Many1Parser where Self: Sized, { Many1Parser { parser: self } } fn skip(self) -> SkipParser where Self: Sized, { SkipParser { parser: self, phantom_data: PhantomData, } } fn skip1(self) -> Skip1Parser where Self: Sized, { Skip1Parser { parser: self, phantom_data: PhantomData, } } fn many_till( self, terminator: PTerminator, ) -> ManyTillParser where Self: Sized, PTerminator: Parser<'a, TToken, TTerminator, TContext>, { ManyTillParser { parser: self, terminator, phantom_data: PhantomData, } } fn many1_till( self, terminator: PTerminator, ) -> Many1TillParser 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 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 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, }) }