summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/depend/mod.rs18
-rw-r--r--src/depend/parsers.rs86
-rw-r--r--src/ebuild/mod.rs57
-rw-r--r--src/ebuild/parsers.rs155
-rw-r--r--src/lib.rs2
-rw-r--r--tests/depend.rs8
6 files changed, 215 insertions, 111 deletions
diff --git a/src/depend/mod.rs b/src/depend/mod.rs
deleted file mode 100644
index 1d85005..0000000
--- a/src/depend/mod.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-use crate::useflag::UseFlag;
-
-pub mod parsers;
-
-#[derive(Clone, Debug)]
-pub enum Conditional {
- Negative(UseFlag),
- Positive(UseFlag),
-}
-
-#[derive(Clone, Debug)]
-pub enum Expr<T> {
- Element(T),
- AllOf(Vec<Self>),
- AnyOf(Vec<Self>),
- OneOf(Vec<Self>),
- ConditionalGroup(Conditional, Vec<Self>),
-}
diff --git a/src/depend/parsers.rs b/src/depend/parsers.rs
deleted file mode 100644
index 975bbe6..0000000
--- a/src/depend/parsers.rs
+++ /dev/null
@@ -1,86 +0,0 @@
-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();
- }
-}
diff --git a/src/ebuild/mod.rs b/src/ebuild/mod.rs
new file mode 100644
index 0000000..2558cf4
--- /dev/null
+++ b/src/ebuild/mod.rs
@@ -0,0 +1,57 @@
+use get::Get;
+use std::path::PathBuf;
+
+use crate::{
+ atom::{Atom, Name, Slot, Version},
+ useflag::{IUseFlag, UseFlag},
+};
+
+pub mod parsers;
+
+#[derive(Clone, Debug)]
+pub enum Conditional {
+ Negative(UseFlag),
+ Positive(UseFlag),
+}
+
+#[derive(Clone, Debug)]
+pub enum Depend<T> {
+ Element(T),
+ AllOf(Vec<Self>),
+ AnyOf(Vec<Self>),
+ OneOf(Vec<Self>),
+ ConditionalGroup(Conditional, Vec<Self>),
+}
+
+#[derive(Debug, Clone, Get)]
+pub struct SrcUri {
+ uri: String,
+ file_name: Option<PathBuf>,
+}
+
+#[derive(Debug, Clone, Get)]
+pub struct License(#[get(method = "get", kind = "deref")] String);
+
+#[derive(Debug, Clone, Get)]
+pub struct Eapi(#[get(method = "get", kind = "deref")] String);
+
+#[derive(Debug, Clone, Get)]
+pub struct Eclass(#[get(method = "get", kind = "deref")] String);
+
+#[derive(Debug, Clone, Get)]
+pub struct Ebuild {
+ name: Name,
+ version: Version,
+ slot: Option<Slot>,
+ homepage: Option<String>,
+ src_uri: Vec<Depend<SrcUri>>,
+ eapi: Option<Eapi>,
+ inherit: Vec<Eclass>,
+ iuse: Vec<IUseFlag>,
+ license: Vec<Depend<License>>,
+ description: Option<String>,
+ depend: Vec<Depend<Atom>>,
+ bdepend: Vec<Depend<Atom>>,
+ rdpened: Vec<Depend<Atom>>,
+ idepend: Vec<Depend<Atom>>,
+}
diff --git a/src/ebuild/parsers.rs b/src/ebuild/parsers.rs
new file mode 100644
index 0000000..d079609
--- /dev/null
+++ b/src/ebuild/parsers.rs
@@ -0,0 +1,155 @@
+use std::path::PathBuf;
+
+use mon::{Parser, alpha1, r#if, tag, whitespace1};
+
+use crate::{
+ Parseable,
+ ebuild::{Conditional, Depend, Eapi, License, SrcUri},
+ useflag::UseFlag,
+};
+
+impl<'a> Parseable<'a, &'a str> for SrcUri {
+ type Parser = impl Parser<&'a str, Output = Self>;
+
+ fn parser() -> Self::Parser {
+ let protocol = alpha1::<&str>().followed_by(tag("://"));
+
+ let uri = r#if(|c: &char| !c.is_ascii_whitespace())
+ .list(1..)
+ .recognize()
+ .map(|output: &str| output.to_string());
+
+ let name = r#if(|c: &char| !c.is_ascii_whitespace())
+ .list(1..)
+ .recognize()
+ .map(|output: &str| PathBuf::from(output));
+
+ uri.preceded_by(protocol)
+ .and(
+ name.preceded_by(tag("->").delimited_by(whitespace1(), whitespace1()))
+ .opt(),
+ )
+ .map(|(uri, file_name)| SrcUri { uri, file_name })
+ }
+}
+
+impl<'a> Parseable<'a, &'a str> for License {
+ type Parser = impl Parser<&'a str, Output = Self>;
+
+ fn parser() -> Self::Parser {
+ let start = r#if(|c: &char| c.is_ascii_alphanumeric() || "_".contains(*c));
+ let rest = r#if(|c: &char| c.is_ascii_alphanumeric() || "+_.-".contains(*c)).list(0..);
+
+ start
+ .and(rest)
+ .recognize()
+ .map(|output: &str| License(output.to_string()))
+ }
+}
+
+impl<'a> Parseable<'a, &'a str> for Eapi {
+ type Parser = impl Parser<&'a str, Output = Self>;
+
+ fn parser() -> Self::Parser {
+ let start = r#if(|c: &char| c.is_ascii_alphanumeric() || "_".contains(*c));
+ let rest = r#if(|c: &char| c.is_ascii_alphanumeric() || "+_.-".contains(*c)).list(0..);
+
+ start
+ .and(rest)
+ .recognize()
+ .map(|output: &str| Eapi(output.to_string()))
+ }
+}
+
+impl<'a, T> Parseable<'a, &'a str> for Depend<T>
+where
+ T: Parseable<'a, &'a str>,
+{
+ type Parser = impl Parser<&'a str, Output = Self>;
+
+ fn parser() -> Self::Parser {
+ |it| {
+ let all_of_group = Depend::parser()
+ .separated_list(whitespace1(), 1..)
+ .delimited_by(tag("(").followed_by(whitespace1()), tag(")"))
+ .map(|exprs| Depend::AllOf(exprs));
+
+ let any_of_group = Depend::parser()
+ .separated_list(whitespace1(), 1..)
+ .delimited_by(tag("(").followed_by(whitespace1()), tag(")"))
+ .preceded_by(tag("||").followed_by(whitespace1()))
+ .map(|exprs| Depend::AnyOf(exprs));
+
+ let one_of_group = Depend::parser()
+ .separated_list(whitespace1(), 1..)
+ .delimited_by(tag("(").followed_by(whitespace1()), tag(")"))
+ .preceded_by(tag("^^").followed_by(whitespace1()))
+ .map(|exprs| Depend::OneOf(exprs));
+
+ let conditional_group = Conditional::parser()
+ .followed_by(whitespace1())
+ .and(
+ Depend::parser()
+ .separated_list(whitespace1(), 1..)
+ .delimited_by(tag("(").followed_by(whitespace1()), tag(")")),
+ )
+ .map(|(conditional, exprs)| Depend::ConditionalGroup(conditional, exprs));
+
+ T::parser()
+ .map(|e| Depend::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, ebuild::Depend};
+
+ use super::*;
+
+ #[test]
+ fn test_src_uri() {
+ let tests = [
+ "https://example.com/foo/bar.tar.gz",
+ "https://example.com/foo/bar.tar.gz -> bar.tar.gz",
+ ];
+
+ for test in tests {
+ SrcUri::parser()
+ .check_finished(InputIter::new(test))
+ .unwrap()
+ }
+ }
+
+ #[test]
+ fn test_expr() {
+ let it = InputIter::new("flag? ( || ( foo/bar foo/bar ) )");
+
+ Depend::<Atom>::parser()
+ .separated_list(whitespace1(), 0..)
+ .check_finished(it)
+ .unwrap();
+ }
+}
diff --git a/src/lib.rs b/src/lib.rs
index ab209e9..fdaf714 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -11,5 +11,5 @@ pub trait Parseable<'a, I: Input + 'a> {
}
pub mod atom;
-pub mod depend;
+pub mod ebuild;
pub mod useflag;
diff --git a/tests/depend.rs b/tests/depend.rs
index 02c59f2..3738854 100644
--- a/tests/depend.rs
+++ b/tests/depend.rs
@@ -1,8 +1,4 @@
-use gentoo_utils::{
- Parseable,
- atom::Atom,
- depend::{self, Expr},
-};
+use gentoo_utils::{Parseable, atom::Atom, ebuild::Depend};
use mon::{Parser, eof, input::InputIter, tag, whitespace1};
use std::fs;
@@ -18,7 +14,7 @@ fn parse_md5_cache() {
if line.starts_with("DEPEND=") {
eprintln!("{line}");
eprintln!();
- Expr::<Atom>::parser()
+ Depend::<Atom>::parser()
.separated_list(whitespace1(), 0..)
.ignore()
.or(eof())