Skip to main content

zyn_core/ast/at/
mod.rs

1mod element_node;
2mod for_node;
3mod if_node;
4mod match_node;
5
6pub use element_node::ElementNode;
7pub use for_node::ForNode;
8pub use if_node::IfNode;
9pub use match_node::MatchNode;
10
11use proc_macro2::Ident;
12use proc_macro2::Span;
13use proc_macro2::TokenStream;
14
15use syn::Token;
16use syn::ext::IdentExt;
17use syn::parse::Parse;
18use syn::parse::ParseStream;
19
20use crate::Expand;
21
22pub enum AtNode {
23    If(IfNode),
24    For(ForNode),
25    Match(MatchNode),
26    Element(ElementNode),
27}
28
29impl AtNode {
30    pub fn is_if(&self) -> bool {
31        matches!(self, Self::If(_))
32    }
33
34    pub fn is_for(&self) -> bool {
35        matches!(self, Self::For(_))
36    }
37
38    pub fn is_match(&self) -> bool {
39        matches!(self, Self::Match(_))
40    }
41
42    pub fn is_element(&self) -> bool {
43        matches!(self, Self::Element(_))
44    }
45}
46
47impl AtNode {
48    pub fn as_if(&self) -> &IfNode {
49        match self {
50            Self::If(v) => v,
51            _ => panic!("called as_if on non-If node"),
52        }
53    }
54
55    pub fn as_for(&self) -> &ForNode {
56        match self {
57            Self::For(v) => v,
58            _ => panic!("called as_for on non-For node"),
59        }
60    }
61
62    pub fn as_match(&self) -> &MatchNode {
63        match self {
64            Self::Match(v) => v,
65            _ => panic!("called as_match on non-Match node"),
66        }
67    }
68
69    pub fn as_element(&self) -> &ElementNode {
70        match self {
71            Self::Element(v) => v,
72            _ => panic!("called as_element on non-Element node"),
73        }
74    }
75}
76
77impl AtNode {
78    pub fn span(&self) -> Span {
79        match self {
80            Self::If(v) => v.span(),
81            Self::For(v) => v.span(),
82            Self::Match(v) => v.span(),
83            Self::Element(v) => v.span(),
84        }
85    }
86}
87
88impl From<IfNode> for AtNode {
89    fn from(v: IfNode) -> Self {
90        Self::If(v)
91    }
92}
93
94impl From<ForNode> for AtNode {
95    fn from(v: ForNode) -> Self {
96        Self::For(v)
97    }
98}
99
100impl From<MatchNode> for AtNode {
101    fn from(v: MatchNode) -> Self {
102        Self::Match(v)
103    }
104}
105
106impl From<ElementNode> for AtNode {
107    fn from(v: ElementNode) -> Self {
108        Self::Element(v)
109    }
110}
111
112impl Expand for AtNode {
113    fn expand(&self, output: &Ident, idents: &mut crate::ident::Iter) -> TokenStream {
114        match self {
115            Self::If(v) => v.expand(output, idents),
116            Self::For(v) => v.expand(output, idents),
117            Self::Match(v) => v.expand(output, idents),
118            Self::Element(v) => v.expand(output, idents),
119        }
120    }
121}
122
123impl Parse for AtNode {
124    fn parse(input: ParseStream) -> syn::Result<Self> {
125        let at_span = input.parse::<Token![@]>()?.span;
126        let ident: syn::Ident = input.call(syn::Ident::parse_any)?;
127        let name = ident.to_string();
128
129        match name.as_str() {
130            "if" => {
131                let mut v = input.parse::<IfNode>()?;
132                v.span = at_span;
133                Ok(v.into())
134            }
135            "for" => {
136                let mut v = input.parse::<ForNode>()?;
137                v.span = at_span;
138                Ok(v.into())
139            }
140            "match" => {
141                let mut v = input.parse::<MatchNode>()?;
142                v.span = at_span;
143                Ok(v.into())
144            }
145            "else" => Err(syn::Error::new(at_span, "unexpected @else without @if")),
146            _ => {
147                let mut v = ElementNode::parse_with_ident(input, ident)?;
148                v.span = at_span;
149                Ok(v.into())
150            }
151        }
152    }
153}