impl Parseable trait

This commit is contained in:
John Turner
2025-10-28 09:44:32 +00:00
parent 92a8e46082
commit b54616a6dd
6 changed files with 367 additions and 272 deletions

View File

@@ -1,61 +1,73 @@
use mon::{Parser, ParserResult, input::InputIter, tag, whitespace1};
use mon::{Parser, tag, whitespace1};
use crate::{
atom,
Parseable,
atom::Atom,
depend::{Conditional, Expr},
useflag,
useflag::UseFlag,
};
fn expr(it: InputIter<&str>) -> ParserResult<&str, Expr> {
let all_of = expr
.separated_list(whitespace1(), 1..)
.delimited_by(tag("(").followed_by(whitespace1()), tag(")"))
.map(|exprs| Expr::AllOf(exprs));
impl<'a> Parseable<'a, &'a str> for Expr {
type Parser = impl Parser<&'a str, Output = Self>;
let any_of = expr
.separated_list(whitespace1(), 1..)
.delimited_by(tag("(").followed_by(whitespace1()), tag(")"))
.preceded_by(tag("||").followed_by(whitespace1()))
.map(|exprs| Expr::AnyOf(exprs));
fn parser() -> Self::Parser {
|it| {
let all_of = Expr::parser()
.separated_list(whitespace1(), 1..)
.delimited_by(tag("(").followed_by(whitespace1()), tag(")"))
.map(|exprs| Expr::AllOf(exprs));
let one_of = expr
.separated_list(whitespace1(), 1..)
.delimited_by(tag("(").followed_by(whitespace1()), tag(")"))
.preceded_by(tag("^^").followed_by(whitespace1()))
.map(|exprs| Expr::OneOf(exprs));
let any_of = Expr::parser()
.separated_list(whitespace1(), 1..)
.delimited_by(tag("(").followed_by(whitespace1()), tag(")"))
.preceded_by(tag("||").followed_by(whitespace1()))
.map(|exprs| Expr::AnyOf(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)
let one_of = Expr::parser()
.separated_list(whitespace1(), 1..)
.delimited_by(tag("(").followed_by(whitespace1()), tag(")"))
.preceded_by(tag("^^").followed_by(whitespace1()))
.map(|exprs| Expr::OneOf(exprs));
Atom::parser()
.map(|atom| Expr::Atom(atom))
.or(Conditional::parser().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()
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::Positive(flag)))
}
pub fn exprs<'a>() -> impl Parser<&'a str, Output = Vec<Expr>> {
expr.separated_list(whitespace1(), 0..)
.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 ) )");
exprs().check_finished(it).unwrap();
Expr::parser()
.separated_list(whitespace1(), 0..)
.check_finished(it)
.unwrap();
}
}