1mod element_node;
14mod for_node;
15mod if_node;
16mod match_node;
17
18pub use element_node::ElementNode;
19pub use for_node::ForNode;
20pub use if_node::IfNode;
21pub use match_node::MatchNode;
22
23use proc_macro2::Ident;
24use proc_macro2::Span;
25use proc_macro2::TokenStream;
26
27use syn::Token;
28use syn::ext::IdentExt;
29use syn::parse::Parse;
30use syn::parse::ParseStream;
31
32use crate::Expand;
33
34pub enum AtNode {
38 If(IfNode),
40 For(ForNode),
42 Match(MatchNode),
44 Element(ElementNode),
46}
47
48impl AtNode {
49 pub fn is_if(&self) -> bool {
51 matches!(self, Self::If(_))
52 }
53
54 pub fn is_for(&self) -> bool {
56 matches!(self, Self::For(_))
57 }
58
59 pub fn is_match(&self) -> bool {
61 matches!(self, Self::Match(_))
62 }
63
64 pub fn is_element(&self) -> bool {
66 matches!(self, Self::Element(_))
67 }
68}
69
70impl AtNode {
71 pub fn as_if(&self) -> &IfNode {
73 match self {
74 Self::If(v) => v,
75 _ => panic!("called as_if on non-If node"),
76 }
77 }
78
79 pub fn as_for(&self) -> &ForNode {
81 match self {
82 Self::For(v) => v,
83 _ => panic!("called as_for on non-For node"),
84 }
85 }
86
87 pub fn as_match(&self) -> &MatchNode {
89 match self {
90 Self::Match(v) => v,
91 _ => panic!("called as_match on non-Match node"),
92 }
93 }
94
95 pub fn as_element(&self) -> &ElementNode {
97 match self {
98 Self::Element(v) => v,
99 _ => panic!("called as_element on non-Element node"),
100 }
101 }
102}
103
104impl AtNode {
105 pub fn span(&self) -> Span {
107 match self {
108 Self::If(v) => v.span(),
109 Self::For(v) => v.span(),
110 Self::Match(v) => v.span(),
111 Self::Element(v) => v.span(),
112 }
113 }
114
115 pub fn to_display_stream(&self, injections: &[(String, TokenStream)]) -> TokenStream {
116 match self {
117 Self::If(v) => v.to_display_stream(injections),
118 Self::For(v) => v.to_display_stream(injections),
119 Self::Match(v) => v.to_display_stream(injections),
120 Self::Element(v) => v.to_display_stream(injections),
121 }
122 }
123}
124
125impl From<IfNode> for AtNode {
126 fn from(v: IfNode) -> Self {
127 Self::If(v)
128 }
129}
130
131impl From<ForNode> for AtNode {
132 fn from(v: ForNode) -> Self {
133 Self::For(v)
134 }
135}
136
137impl From<MatchNode> for AtNode {
138 fn from(v: MatchNode) -> Self {
139 Self::Match(v)
140 }
141}
142
143impl From<ElementNode> for AtNode {
144 fn from(v: ElementNode) -> Self {
145 Self::Element(v)
146 }
147}
148
149impl Expand for AtNode {
150 fn expand(&self, output: &Ident, idents: &mut crate::ident::Iter) -> TokenStream {
151 match self {
152 Self::If(v) => v.expand(output, idents),
153 Self::For(v) => v.expand(output, idents),
154 Self::Match(v) => v.expand(output, idents),
155 Self::Element(v) => v.expand(output, idents),
156 }
157 }
158}
159
160impl Parse for AtNode {
161 fn parse(input: ParseStream) -> syn::Result<Self> {
162 let at_span = input.parse::<Token![@]>()?.span;
163 let ident: syn::Ident = input.call(syn::Ident::parse_any)?;
164 let name = ident.to_string();
165
166 match name.as_str() {
167 "if" => {
168 let mut v = input.parse::<IfNode>()?;
169 v.span = at_span;
170 Ok(v.into())
171 }
172 "for" => {
173 let mut v = input.parse::<ForNode>()?;
174 v.span = at_span;
175 Ok(v.into())
176 }
177 "match" => {
178 let mut v = input.parse::<MatchNode>()?;
179 v.span = at_span;
180 Ok(v.into())
181 }
182 "else" => Err(syn::Error::new(at_span, "unexpected @else without @if")),
183 _ => {
184 let mut v = ElementNode::parse_with_ident(input, ident)?;
185 v.span = at_span;
186 Ok(v.into())
187 }
188 }
189 }
190}