From f05c1e92ad51edb4c6971e52f8344fdf8681afee Mon Sep 17 00:00:00 2001 From: John Turner Date: Sat, 25 Oct 2025 02:02:07 -0400 Subject: [PATCH] impl DEPEND parser --- src/atom/parsers.rs | 7 +++++ src/depend/mod.rs | 18 +++++++++++++ src/depend/parsers.rs | 61 +++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 1 + tests/depend.rs | 27 +++++++++++++++++++ 5 files changed, 114 insertions(+) create mode 100644 src/depend/mod.rs create mode 100644 src/depend/parsers.rs create mode 100644 tests/depend.rs diff --git a/src/atom/parsers.rs b/src/atom/parsers.rs index 16e8fb1..958ecee 100644 --- a/src/atom/parsers.rs +++ b/src/atom/parsers.rs @@ -348,4 +348,11 @@ mod test { assert!(atom().check_finished(it).is_err()); } + + #[test] + fn test_atom_with_trailing_dash_and_letter() { + let it = InputIter::new("dev-db/mysql-connector-c"); + + atom().check_finished(it).unwrap(); + } } diff --git a/src/depend/mod.rs b/src/depend/mod.rs new file mode 100644 index 0000000..ffa7836 --- /dev/null +++ b/src/depend/mod.rs @@ -0,0 +1,18 @@ +use crate::{atom::Atom, useflag::UseFlag}; + +pub mod parsers; + +#[derive(Clone, Debug)] +pub enum Conditional { + Negative(UseFlag), + Positive(UseFlag), +} + +#[derive(Clone, Debug)] +pub enum Expr { + Atom(Atom), + Conditional(Conditional), + AllOf(Vec), + AnyOf(Vec), + OneOf(Vec), +} diff --git a/src/depend/parsers.rs b/src/depend/parsers.rs new file mode 100644 index 0000000..4c23b02 --- /dev/null +++ b/src/depend/parsers.rs @@ -0,0 +1,61 @@ +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(); + } +} diff --git a/src/lib.rs b/src/lib.rs index 1eb0c3f..2dbc8ca 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,4 +2,5 @@ #![allow(dead_code)] pub mod atom; +pub mod depend; pub mod useflag; diff --git a/tests/depend.rs b/tests/depend.rs new file mode 100644 index 0000000..1385862 --- /dev/null +++ b/tests/depend.rs @@ -0,0 +1,27 @@ +use gentoo_utils::depend; +use mon::{Parser, eof, input::InputIter, tag}; +use std::fs; + +#[test] +fn parse_md5_cache() { + let md5_cache = "/var/db/repos/gentoo/metadata/md5-cache"; + + for cat in fs::read_dir(md5_cache).unwrap() { + for pkg in fs::read_dir(cat.unwrap().path()).unwrap() { + let metadata = fs::read_to_string(pkg.unwrap().path()).unwrap(); + + for line in metadata.lines() { + if line.starts_with("DEPEND=") { + eprintln!("{line}"); + + depend::parsers::exprs() + .ignore() + .or(eof()) + .preceded_by(tag("DEPEND=")) + .check_finished(InputIter::new(line)) + .unwrap(); + } + } + } + } +}