use crate::parser::{FailedParserResult, Parser, ParserContext, ParserResult}; use std::cell::RefCell; use std::fmt::Debug; use std::marker::PhantomData; use std::rc::Rc; pub struct ManyParser

{ pub(crate) parser: P, } impl<'a, TToken, T: 'a, TContext, P> Parser<'a, TToken, Vec, TContext> for ManyParser

where TToken: Debug + Clone, P: Parser<'a, TToken, T, TContext>, { fn parse( &self, context: Rc>>, input: &'a [TToken], ) -> ParserResult<'a, TToken, Vec> { let mut result = vec![]; let mut input = input; while let Ok((i, r)) = self.parser.parse(context.clone(), input) { result.push(r); input = i; } Ok((input, result)) } } pub struct Many1Parser

{ pub(crate) parser: P, } impl<'a, TToken, T: 'a, TContext, P> Parser<'a, TToken, Vec, TContext> for Many1Parser

where TToken: Debug + Clone, P: Parser<'a, TToken, T, TContext>, { fn parse( &self, context: Rc>>, input: &'a [TToken], ) -> ParserResult<'a, TToken, Vec> { let (mut input, first_result) = self.parser.parse(context.clone(), input)?; let mut result = vec![first_result]; while let Ok((i, r)) = self.parser.parse(context.clone(), input) { result.push(r); input = i; } Ok((input, result)) } } pub struct SkipParser { pub(crate) parser: P, pub(crate) phantom_data: PhantomData, } impl<'a, TToken, T: 'a, TContext, P> Parser<'a, TToken, (), TContext> for SkipParser where TToken: Debug + Clone, P: Parser<'a, TToken, T, TContext>, { fn parse( &self, context: Rc>>, input: &'a [TToken], ) -> ParserResult<'a, TToken, ()> { let mut input = input; while let Ok((i, _)) = self.parser.parse(context.clone(), input) { input = i; } Ok((input, ())) } } pub struct Skip1Parser { pub(crate) parser: P, pub(crate) phantom_data: PhantomData, } impl<'a, TToken, T: 'a, TContext, P> Parser<'a, TToken, (), TContext> for Skip1Parser where TToken: Debug + Clone, P: Parser<'a, TToken, T, TContext>, { fn parse( &self, context: Rc>>, input: &'a [TToken], ) -> ParserResult<'a, TToken, ()> { let (mut input, _) = self.parser.parse(context.clone(), input)?; while let Ok((i, _)) = self.parser.parse(context.clone(), input) { input = i; } Ok((input, ())) } } pub struct ManyTillParser { pub(crate) parser: P, pub(crate) terminator: PTerminator, pub(crate) phantom_data: PhantomData, } impl<'a, TToken, T: 'a, TTerminator: 'a, TContext, P, PTerminator> Parser<'a, TToken, Vec, TContext> for ManyTillParser where TToken: Debug + Clone, P: Parser<'a, TToken, T, TContext>, PTerminator: Parser<'a, TToken, TTerminator, TContext>, { fn parse( &self, context: Rc>>, input: &'a [TToken], ) -> ParserResult<'a, TToken, Vec> { let mut input = input; let mut result = vec![]; loop { if self.terminator.parse(context.clone(), input).is_ok() { return Ok((input, result)); } if let Ok((i, r)) = self.parser.parse(context.clone(), input) { input = i; result.push(r); } else { return Err(( input, FailedParserResult::new("End with other elements.".to_owned()), )); } } } } pub struct Many1TillParser { pub(crate) parser: P, pub(crate) terminator: PTerminator, pub(crate) phantom_data: PhantomData, } impl<'a, TToken, T: 'a, TTerminator: 'a, TContext, P, PTerminator> Parser<'a, TToken, Vec, TContext> for Many1TillParser where TToken: Debug + Clone, P: Parser<'a, TToken, T, TContext>, PTerminator: Parser<'a, TToken, TTerminator, TContext>, { fn parse( &self, context: Rc>>, input: &'a [TToken], ) -> ParserResult<'a, TToken, Vec> { let (mut input, r) = self.parser.parse(context.clone(), input)?; let mut result = vec![r]; loop { if self.terminator.parse(context.clone(), input).is_ok() { return Ok((input, result)); } if let Ok((i, r)) = self.parser.parse(context.clone(), input) { result.push(r); input = i; } else { return Err(( input, FailedParserResult::new("End with other elements.".to_owned()), )); } } } } #[cfg(test)] mod test { use super::*; use crate::combinators::{take1_till, take_till, tuple, ParserExt}; use crate::parser::{failed_parser_test_helper, parser_test_helper}; use crate::text::char_parser; #[test] fn many_test() { parser_test_helper( ParserContext::new_with_str("aaa", ()), &vec!['a', 'a', 'a'], |c, i| char_parser('a').many().parse(c, i), ); parser_test_helper( ParserContext::new_with_str("aaabbaa", ()), &vec!['a', 'a', 'a'], |c, i| char_parser('a').many().parse(c, i), ); parser_test_helper(ParserContext::new_with_str("bbaa", ()), &vec![], |c, i| { char_parser('a').many().parse(c, i) }); parser_test_helper(ParserContext::new_with_str("", ()), &vec![], |c, i| { char_parser('a').many().parse(c, i) }); } #[test] fn many1_test() { parser_test_helper( ParserContext::new_with_str("aaa", ()), &vec!['a', 'a', 'a'], |c, i| char_parser('a').many1().parse(c, i), ); parser_test_helper( ParserContext::new_with_str("aaabbaa", ()), &vec!['a', 'a', 'a'], |c, i| char_parser('a').many1().parse(c, i), ); failed_parser_test_helper(ParserContext::new_with_str("bbaa", ()), |c, i| { char_parser('a').many1().parse(c, i) }); failed_parser_test_helper(ParserContext::new_with_str("", ()), |c, i| { char_parser('a').many1().parse(c, i) }); } #[test] fn skip_test() { parser_test_helper(ParserContext::new_with_str("aaab", ()), &'b', |c, i| { char_parser('a').skip().right(char_parser('b')).parse(c, i) }); parser_test_helper(ParserContext::new_with_str("b", ()), &'b', |c, i| { char_parser('a').skip().right(char_parser('b')).parse(c, i) }); } #[test] fn skip1_test() { parser_test_helper(ParserContext::new_with_str("aaab", ()), &'b', |c, i| { char_parser('a').skip1().right(char_parser('b')).parse(c, i) }); failed_parser_test_helper(ParserContext::new_with_str("b", ()), |c, i| { char_parser('a').skip1().right(char_parser('b')).parse(c, i) }); } #[test] fn many_till_test() { parser_test_helper( ParserContext::new_with_str("aaab", ()), &vec!['a', 'a', 'a'], |c, i| char_parser('a').many_till(char_parser('b')).parse(c, i), ); parser_test_helper(ParserContext::new_with_str("b", ()), &vec![], |c, i| { char_parser('a').many_till(char_parser('b')).parse(c, i) }); failed_parser_test_helper(ParserContext::new_with_str("aaacb", ()), |c, i| { char_parser('a').many_till(char_parser('b')).parse(c, i) }); } #[test] fn many1_till_test() { parser_test_helper( ParserContext::new_with_str("aaab", ()), &vec!['a', 'a', 'a'], |c, i| char_parser('a').many1_till(char_parser('b')).parse(c, i), ); failed_parser_test_helper(ParserContext::new_with_str("b", ()), |c, i| { char_parser('a').many1_till(char_parser('b')).parse(c, i) }); failed_parser_test_helper(ParserContext::new_with_str("aaacb", ()), |c, i| { char_parser('a').many1_till(char_parser('b')).parse(c, i) }); } #[test] fn take_till_test() { parser_test_helper( ParserContext::new_with_str("aaab", ()), &(vec!['a', 'a', 'a'], 'b'), |c, i| tuple((take_till(char_parser('b')), char_parser('b'))).parse(c, i), ); parser_test_helper( ParserContext::new_with_str("b", ()), &(vec![], 'b'), |c, i| tuple((take_till(char_parser('b')), char_parser('b'))).parse(c, i), ); } #[test] fn take1_till_test() { parser_test_helper( ParserContext::new_with_str("aaab", ()), &(vec!['a', 'a', 'a'], 'b'), |c, i| tuple((take1_till(char_parser('b')), char_parser('b'))).parse(c, i), ); failed_parser_test_helper(ParserContext::new_with_str("b", ()), |c, i| { tuple((take1_till(char_parser('b')), char_parser('b'))).parse(c, i) }); } }