Skip to main content

zyn_core/ast/
mod.rs

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;
19use quote::quote;
20
21use syn::Token;
22use syn::parse::Parse;
23use syn::parse::ParseStream;
24
25use crate::Expand;
26use crate::ident;
27
28pub enum Node {
29    Tokens(TokensNode),
30    Interp(InterpNode),
31    At(AtNode),
32    Group(GroupNode),
33}
34
35impl Node {
36    pub fn is_tokens(&self) -> bool {
37        matches!(self, Self::Tokens(_))
38    }
39
40    pub fn is_interp(&self) -> bool {
41        matches!(self, Self::Interp(_))
42    }
43
44    pub fn is_at(&self) -> bool {
45        matches!(self, Self::At(_))
46    }
47
48    pub fn is_group(&self) -> bool {
49        matches!(self, Self::Group(_))
50    }
51}
52
53impl Node {
54    pub fn as_tokens(&self) -> &TokensNode {
55        match self {
56            Self::Tokens(v) => v,
57            _ => panic!("called as_tokens on non-Tokens node"),
58        }
59    }
60
61    pub fn as_interp(&self) -> &InterpNode {
62        match self {
63            Self::Interp(v) => v,
64            _ => panic!("called as_interp on non-Interp node"),
65        }
66    }
67
68    pub fn as_at(&self) -> &AtNode {
69        match self {
70            Self::At(v) => v,
71            _ => panic!("called as_at on non-At node"),
72        }
73    }
74
75    pub fn as_group(&self) -> &GroupNode {
76        match self {
77            Self::Group(v) => v,
78            _ => panic!("called as_group on non-Group node"),
79        }
80    }
81}
82
83impl Node {
84    pub fn span(&self) -> Span {
85        match self {
86            Self::Tokens(v) => v.span(),
87            Self::Interp(v) => v.span(),
88            Self::At(v) => v.span(),
89            Self::Group(v) => v.span(),
90        }
91    }
92}
93
94impl From<TokensNode> for Node {
95    fn from(v: TokensNode) -> Self {
96        Self::Tokens(v)
97    }
98}
99
100impl From<InterpNode> for Node {
101    fn from(v: InterpNode) -> Self {
102        Self::Interp(v)
103    }
104}
105
106impl From<AtNode> for Node {
107    fn from(v: AtNode) -> Self {
108        Self::At(v)
109    }
110}
111
112impl From<GroupNode> for Node {
113    fn from(v: GroupNode) -> Self {
114        Self::Group(v)
115    }
116}
117
118impl Node {
119    pub fn parse_brace(input: ParseStream) -> syn::Result<Self> {
120        let content;
121        let brace = syn::braced!(content in input);
122        let span = brace.span.join();
123
124        let fork = content.fork();
125        let is_interp = if fork.peek(syn::token::Brace) {
126            let inner;
127            syn::braced!(inner in fork);
128            fork.is_empty()
129        } else {
130            false
131        };
132
133        if is_interp {
134            let inner;
135            syn::braced!(inner in content);
136
137            let mut expr = TokenStream::new();
138            let mut pipes = Vec::new();
139
140            while !inner.is_empty() {
141                if inner.peek(Token![|]) {
142                    inner.parse::<Token![|]>()?;
143                    pipes.push(inner.parse::<PipeNode>()?);
144                } else if pipes.is_empty() {
145                    let tt: TokenTree = inner.parse()?;
146                    tt.to_tokens(&mut expr);
147                } else {
148                    break;
149                }
150            }
151
152            if expr.is_empty() {
153                return Err(syn::Error::new(span, "empty interpolation"));
154            }
155
156            Ok(InterpNode { span, expr, pipes }.into())
157        } else {
158            let body = content.parse::<Element>()?;
159            Ok(GroupNode {
160                span,
161                delimiter: proc_macro2::Delimiter::Brace,
162                body: Box::new(body),
163            }
164            .into())
165        }
166    }
167}
168
169impl Expand for Node {
170    fn expand(&self, output: &Ident, idents: &mut ident::Iter) -> TokenStream {
171        match self {
172            Self::Tokens(v) => v.expand(output, idents),
173            Self::Interp(v) => v.expand(output, idents),
174            Self::At(v) => v.expand(output, idents),
175            Self::Group(v) => v.expand(output, idents),
176        }
177    }
178}
179
180pub struct Element {
181    pub nodes: Vec<Node>,
182}
183
184impl Element {
185    pub fn span(&self) -> Span {
186        self.nodes
187            .first()
188            .map(|n| n.span())
189            .unwrap_or_else(Span::call_site)
190    }
191}
192
193impl Expand for Element {
194    fn expand(&self, output: &Ident, idents: &mut ident::Iter) -> TokenStream {
195        let mut result = TokenStream::new();
196
197        for node in &self.nodes {
198            result.extend(node.expand(output, idents));
199        }
200
201        result
202    }
203}
204
205impl Element {
206    pub fn to_token_stream(&self) -> TokenStream {
207        let mut idents = ident::Iter::new();
208        let output = idents.next().unwrap();
209        let expanded = self.expand(&output, &mut idents);
210
211        quote! {
212            {
213                let mut #output = ::zyn::proc_macro2::TokenStream::new();
214                #expanded
215                #output
216            }
217        }
218    }
219}
220
221impl Parse for Element {
222    fn parse(input: ParseStream) -> syn::Result<Self> {
223        let mut nodes = Vec::new();
224        let mut pending = TokenStream::new();
225
226        while !input.is_empty() {
227            if input.peek(Token![@]) {
228                flush(&mut pending, &mut nodes);
229                nodes.push(input.parse::<AtNode>()?.into());
230            } else if input.peek(syn::token::Brace) {
231                flush(&mut pending, &mut nodes);
232                nodes.push(Node::parse_brace(input)?);
233            } else if input.peek(syn::token::Paren) || input.peek(syn::token::Bracket) {
234                flush(&mut pending, &mut nodes);
235                nodes.push(input.parse::<GroupNode>()?.into());
236            } else {
237                let tt: TokenTree = input.parse()?;
238                tt.to_tokens(&mut pending);
239            }
240        }
241
242        flush(&mut pending, &mut nodes);
243        Ok(Self { nodes })
244    }
245}
246
247fn flush(pending: &mut TokenStream, nodes: &mut Vec<Node>) {
248    if pending.is_empty() {
249        return;
250    }
251
252    let span = pending
253        .clone()
254        .into_iter()
255        .next()
256        .map(|tt| tt.span())
257        .unwrap_or_else(Span::call_site);
258
259    nodes.push(
260        TokensNode {
261            span,
262            stream: pending.clone(),
263        }
264        .into(),
265    );
266
267    *pending = TokenStream::new();
268}