logo
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
mod display;
mod methods;
mod parse;
#[cfg(test)]
mod tests;
use nom::{
    branch::alt,
    bytes::complete::{tag, take_till1},
    character::complete::{alphanumeric1, char, multispace1},
    combinator::opt,
    error::Error,
    multi::{many0, separated_list0},
    sequence::{delimited, tuple},
    Err, IResult,
};
use std::{
    fmt::{Display, Formatter},
    ops::{Add, AddAssign},
};

///
pub fn parse_tailwind(input: &str) -> Result<Vec<AstStyle>, Err<Error<&str>>> {
    let rest = many0(tuple((multispace1, AstGroupItem::parse)));
    let (head, groups) = match tuple((AstGroupItem::parse, rest))(input.trim()) {
        Ok(o) => o.1,
        Err(e) => return Err(e),
    };
    let mut out = vec![];
    head.expand(&mut out);
    for (_, g) in groups {
        g.expand(&mut out)
    }
    Ok(out)
}

/// `variant:ast-style(grouped)`
#[derive(Clone, Debug, PartialEq)]
pub struct AstGroup<'a> {
    ///
    pub head: AstStyle<'a>,
    ///
    pub children: Vec<AstGroupItem<'a>>,
}

/// one of [`AstGroup`] and [`AstStyle`]
#[derive(Clone, Debug, PartialEq)]
pub enum AstGroupItem<'a> {
    ///
    Grouped(AstGroup<'a>),
    ///
    Styled(AstStyle<'a>),
    // SelfReference(AstReference),
}

/// `not-variant:pseudo::-ast-element-[arbitrary]`
#[derive(Clone, Debug, PartialEq)]
pub struct AstStyle<'a> {
    ///
    pub negative: bool,
    ///
    pub variants: Vec<ASTVariant<'a>>,
    ///
    pub elements: Vec<&'a str>,
    ///
    pub arbitrary: Option<&'a str>,
}

/// `-[.+]`
#[derive(Clone, Debug, PartialEq)]
pub struct AstArbitrary<'a> {
    /// `[.]`
    pub arbitrary: &'a str,
}

/// `ast-elements`
#[derive(Clone, Debug, PartialEq, Default)]
pub struct AstElements<'a> {
    /// `name-space`
    pub elements: Vec<&'a str>,
}

/// `&`
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct AstReference {}

/// `(not-)?variant:pseudo::`
#[derive(Clone, Debug, PartialEq)]
pub struct ASTVariant<'a> {
    /// `not-`
    pub not: bool,
    /// `::`
    pub pseudo: bool,
    /// `name-space`
    pub names: Vec<&'a str>,
}