summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Turner <jturner.usa@gmail.com>2025-10-25 02:02:07 -0400
committerJohn Turner <jturner.usa@gmail.com>2025-10-25 02:02:07 -0400
commitf05c1e92ad51edb4c6971e52f8344fdf8681afee (patch)
tree59da0773fec1ad5a7d3e53987c5bbe042a565848
parentf854e9757704eafaeb9e9847fbadff7d7b23e2a4 (diff)
downloadgentoo-utils-f05c1e92ad51edb4c6971e52f8344fdf8681afee.tar.gz
impl DEPEND parser
-rw-r--r--src/atom/parsers.rs7
-rw-r--r--src/depend/mod.rs18
-rw-r--r--src/depend/parsers.rs61
-rw-r--r--src/lib.rs1
-rw-r--r--tests/depend.rs27
5 files changed, 114 insertions, 0 deletions
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<Expr>),
+ AnyOf(Vec<Expr>),
+ OneOf(Vec<Expr>),
+}
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>> {
+ 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();
+ }
+ }
+ }
+ }
+}