1use proc_macro2::Ident;
25use proc_macro2::Span;
26use proc_macro2::TokenStream;
27use proc_macro2::TokenTree;
28
29use quote::ToTokens;
30use quote::quote;
31
32use syn::Token;
33use syn::parse::Parse;
34use syn::parse::ParseStream;
35
36use crate::Expand;
37use crate::ast::AtNode;
38use crate::ast::GroupNode;
39use crate::ast::Node;
40use crate::ast::TokensNode;
41use crate::ident;
42use crate::types::Input;
43
44pub struct Template {
46 pub nodes: Vec<Node>,
47}
48
49impl Template {
50 pub fn span(&self) -> Span {
52 self.nodes
53 .first()
54 .map(|n| n.span())
55 .unwrap_or_else(Span::call_site)
56 }
57
58 pub fn to_token_stream(&self) -> TokenStream {
60 let mut idents = ident::Iter::new();
61 let output = idents.next().unwrap();
62 let expanded = self.expand(&output, &mut idents);
63
64 quote! {
65 {
66 let mut #output = ::zyn::proc_macro2::TokenStream::new();
67 let mut __zyn_diagnostic = ::zyn::mark::new();
68 #expanded
69 ::zyn::Output::new()
70 .tokens(#output)
71 .diagnostic(__zyn_diagnostic)
72 .build()
73 }
74 }
75 }
76
77 pub fn render(&self, input: &Input) -> TokenStream {
79 let expanded = self.to_token_stream();
80 quote! {
81 {
82 let input: ::zyn::Input = ::zyn::parse!(#input).unwrap();
83 #expanded
84 }
85 }
86 }
87
88 fn flush(pending: &mut TokenStream, nodes: &mut Vec<Node>) {
89 if pending.is_empty() {
90 return;
91 }
92
93 let stream = std::mem::take(pending);
94 let span = stream
95 .clone()
96 .into_iter()
97 .next()
98 .map(|tt| tt.span())
99 .unwrap_or_else(Span::call_site);
100
101 nodes.push(TokensNode { span, stream }.into());
102 }
103}
104
105impl Expand for Template {
106 fn expand(&self, output: &Ident, idents: &mut ident::Iter) -> TokenStream {
107 let mut result = TokenStream::new();
108
109 for node in &self.nodes {
110 result.extend(node.expand(output, idents));
111 }
112
113 result
114 }
115}
116
117impl Parse for Template {
118 fn parse(input: ParseStream) -> syn::Result<Self> {
119 let mut nodes = Vec::new();
120 let mut pending = TokenStream::new();
121
122 while !input.is_empty() {
123 if input.peek(Token![@]) {
124 Self::flush(&mut pending, &mut nodes);
125 nodes.push(input.parse::<AtNode>()?.into());
126 } else if input.peek(syn::token::Brace) {
127 Self::flush(&mut pending, &mut nodes);
128 nodes.push(Node::parse_brace(input)?);
129 } else if input.peek(syn::token::Paren) || input.peek(syn::token::Bracket) {
130 Self::flush(&mut pending, &mut nodes);
131 nodes.push(input.parse::<GroupNode>()?.into());
132 } else {
133 let tt: TokenTree = input.parse()?;
134 tt.to_tokens(&mut pending);
135 }
136 }
137
138 Self::flush(&mut pending, &mut nodes);
139 Ok(Self { nodes })
140 }
141}