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