forked from gentoo-utils/gentoo-utils
87 lines
2.5 KiB
Rust
87 lines
2.5 KiB
Rust
use mon::{Parser, tag, whitespace1};
|
|
|
|
use crate::{
|
|
Parseable,
|
|
depend::{Conditional, Expr},
|
|
useflag::UseFlag,
|
|
};
|
|
|
|
impl<'a, T> Parseable<'a, &'a str> for Expr<T>
|
|
where
|
|
T: Parseable<'a, &'a str>,
|
|
{
|
|
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 = Conditional::parser()
|
|
.followed_by(whitespace1())
|
|
.and(
|
|
Expr::parser()
|
|
.separated_list(whitespace1(), 1..)
|
|
.delimited_by(tag("(").followed_by(whitespace1()), tag(")")),
|
|
)
|
|
.map(|(conditional, exprs)| Expr::ConditionalGroup(conditional, exprs));
|
|
|
|
T::parser()
|
|
.map(|e| Expr::Element(e))
|
|
.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 crate::atom::Atom;
|
|
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn test_expr() {
|
|
let it = InputIter::new("flag? ( || ( foo/bar foo/bar ) )");
|
|
|
|
Expr::<Atom>::parser()
|
|
.separated_list(whitespace1(), 0..)
|
|
.check_finished(it)
|
|
.unwrap();
|
|
}
|
|
}
|