use mon::{Parser, tag, whitespace1}; use crate::{ Parseable, atom::Atom, depend::{Conditional, Expr}, useflag::UseFlag, }; impl<'a> Parseable<'a, &'a str> for Expr { type Parser = impl Parser<&'a str, Output = Self>; fn parser() -> Self::Parser { |it| { let all_of_group = Expr::parser() .separated_list(whitespace1(), 1..) .delimited_by(tag("(").followed_by(whitespace1()), tag(")")) .map(|exprs| Expr::AllOf(exprs)); let any_of_group = Expr::parser() .separated_list(whitespace1(), 1..) .delimited_by(tag("(").followed_by(whitespace1()), tag(")")) .preceded_by(tag("||").followed_by(whitespace1())) .map(|exprs| Expr::AnyOf(exprs)); let one_of_group = Expr::parser() .separated_list(whitespace1(), 1..) .delimited_by(tag("(").followed_by(whitespace1()), tag(")")) .preceded_by(tag("^^").followed_by(whitespace1())) .map(|exprs| Expr::OneOf(exprs)); let conditional_group = Expr::parser() .separated_list(whitespace1(), 1..) .delimited_by(tag("(").followed_by(whitespace1()), tag(")")) .preceded_by(Conditional::parser().followed_by(whitespace1())) .map(|exprs| Expr::OneOf(exprs)); Atom::parser() .map(|atom| Expr::Atom(atom)) .or(conditional_group) .or(any_of_group) .or(all_of_group) .or(one_of_group) .parse(it) } } } impl<'a> Parseable<'a, &'a str> for Conditional { type Parser = impl Parser<&'a str, Output = Self>; fn parser() -> Self::Parser { UseFlag::parser() .preceded_by(tag("!")) .followed_by(tag("?")) .map(|flag| Conditional::Negative(flag)) .or(UseFlag::parser() .followed_by(tag("?")) .map(|flag| Conditional::Positive(flag))) } } #[cfg(test)] mod test { use mon::input::InputIter; use super::*; #[test] fn test_expr() { let it = InputIter::new("flag? ( || ( foo/bar foo/bar ) )"); Expr::parser() .separated_list(whitespace1(), 0..) .check_finished(it) .unwrap(); } }