use mon::{DebugTracer, Parser, ParserResult, input::InputIter, mode::Emit, tag, whitespace1}; use crate::{ atom, depend::{Conditional, Expr}, useflag, }; fn expr(it: InputIter<&str>) -> ParserResult<&str, Expr> { let all_of = expr .separated_list1(whitespace1()) .delimited_by(tag("(").followed_by(whitespace1()), tag(")")) .map(|exprs| Expr::AllOf(exprs)); let any_of = expr .separated_list1(whitespace1()) .delimited_by(tag("(").followed_by(whitespace1()), tag(")")) .preceded_by(tag("||").followed_by(whitespace1())) .map(|exprs| Expr::AnyOf(exprs)); let one_of = expr .separated_list1(whitespace1()) .delimited_by(tag("(").followed_by(whitespace1()), tag(")")) .preceded_by(tag("^^").followed_by(whitespace1())) .map(|exprs| Expr::OneOf(exprs)); atom::parsers::atom() .map(|atom| Expr::Atom(atom)) .or(conditional().map(|conditional| Expr::Conditional(conditional))) .or(any_of) .or(all_of) .or(one_of) .parse(it) } fn conditional<'a>() -> impl Parser<&'a str, Output = Conditional> { useflag::parsers::useflag() .preceded_by(tag("!")) .followed_by(tag("?")) .map(|flag| Conditional::Negative(flag)) .or(useflag::parsers::useflag() .followed_by(tag("?")) .map(|flag| Conditional::Positive(flag))) } pub fn exprs<'a>() -> impl Parser<&'a str, Output = Vec> { expr.separated_list1(whitespace1()) } #[cfg(test)] mod test { use super::*; #[test] fn test_expr() { let it = InputIter::new("flag? ( || ( foo/bar foo/bar ) )"); exprs().check_finished(it).unwrap(); } }