1pub mod at;
17mod group_node;
18mod interp_node;
19mod pipe_node;
20mod tokens_node;
21
22pub use at::*;
23pub use group_node::GroupNode;
24pub use interp_node::InterpNode;
25pub use pipe_node::PipeNode;
26pub use tokens_node::TokensNode;
27
28use proc_macro2::Ident;
29use proc_macro2::Span;
30use proc_macro2::TokenStream;
31use proc_macro2::TokenTree;
32
33use quote::ToTokens;
34
35use syn::Token;
36use syn::parse::ParseStream;
37
38use crate::Expand;
39use crate::ident;
40
41pub enum Node {
45 Tokens(TokensNode),
47 Interp(InterpNode),
49 At(AtNode),
51 Group(GroupNode),
53}
54
55impl Node {
56 pub fn is_tokens(&self) -> bool {
58 matches!(self, Self::Tokens(_))
59 }
60
61 pub fn is_interp(&self) -> bool {
63 matches!(self, Self::Interp(_))
64 }
65
66 pub fn is_at(&self) -> bool {
68 matches!(self, Self::At(_))
69 }
70
71 pub fn is_group(&self) -> bool {
73 matches!(self, Self::Group(_))
74 }
75}
76
77impl Node {
78 pub fn as_tokens(&self) -> &TokensNode {
80 match self {
81 Self::Tokens(v) => v,
82 _ => panic!("called as_tokens on non-Tokens node"),
83 }
84 }
85
86 pub fn as_interp(&self) -> &InterpNode {
88 match self {
89 Self::Interp(v) => v,
90 _ => panic!("called as_interp on non-Interp node"),
91 }
92 }
93
94 pub fn as_at(&self) -> &AtNode {
96 match self {
97 Self::At(v) => v,
98 _ => panic!("called as_at on non-At node"),
99 }
100 }
101
102 pub fn as_group(&self) -> &GroupNode {
104 match self {
105 Self::Group(v) => v,
106 _ => panic!("called as_group on non-Group node"),
107 }
108 }
109}
110
111impl Node {
112 pub fn span(&self) -> Span {
114 match self {
115 Self::Tokens(v) => v.span(),
116 Self::Interp(v) => v.span(),
117 Self::At(v) => v.span(),
118 Self::Group(v) => v.span(),
119 }
120 }
121}
122
123impl From<TokensNode> for Node {
124 fn from(v: TokensNode) -> Self {
125 Self::Tokens(v)
126 }
127}
128
129impl From<InterpNode> for Node {
130 fn from(v: InterpNode) -> Self {
131 Self::Interp(v)
132 }
133}
134
135impl From<AtNode> for Node {
136 fn from(v: AtNode) -> Self {
137 Self::At(v)
138 }
139}
140
141impl From<GroupNode> for Node {
142 fn from(v: GroupNode) -> Self {
143 Self::Group(v)
144 }
145}
146
147impl Node {
148 pub fn parse_brace(input: ParseStream) -> syn::Result<Self> {
149 let content;
150 let brace = syn::braced!(content in input);
151 let span = brace.span.join();
152
153 let fork = content.fork();
154 let is_interp = if fork.peek(syn::token::Brace) {
155 let inner;
156 syn::braced!(inner in fork);
157 fork.is_empty()
158 } else {
159 false
160 };
161
162 if is_interp {
163 let inner;
164 syn::braced!(inner in content);
165
166 let mut expr = TokenStream::new();
167 let mut pipes = Vec::new();
168
169 while !inner.is_empty() {
170 if inner.peek(Token![|]) {
171 inner.parse::<Token![|]>()?;
172 pipes.push(inner.parse::<PipeNode>()?);
173 } else if pipes.is_empty() {
174 let tt: TokenTree = inner.parse()?;
175 tt.to_tokens(&mut expr);
176 } else {
177 break;
178 }
179 }
180
181 if expr.is_empty() {
182 return Err(syn::Error::new(span, "empty interpolation"));
183 }
184
185 Ok(InterpNode { span, expr, pipes }.into())
186 } else {
187 let body = content.parse::<crate::template::Template>()?;
188 Ok(GroupNode {
189 span,
190 delimiter: proc_macro2::Delimiter::Brace,
191 body: Box::new(body),
192 }
193 .into())
194 }
195 }
196}
197
198impl Expand for Node {
199 fn expand(&self, output: &Ident, idents: &mut ident::Iter) -> TokenStream {
200 match self {
201 Self::Tokens(v) => v.expand(output, idents),
202 Self::Interp(v) => v.expand(output, idents),
203 Self::At(v) => v.expand(output, idents),
204 Self::Group(v) => v.expand(output, idents),
205 }
206 }
207}