forked from gentoo-utils/gentoo-utils
create ebuild module
This commit is contained in:
155
src/ebuild/parsers.rs
Normal file
155
src/ebuild/parsers.rs
Normal file
@@ -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();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user