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_display_stream(&self, injections: &[(String, TokenStream)]) -> TokenStream {
67 let mut result = TokenStream::new();
68 for node in &self.nodes {
69 result.extend(node.to_display_stream(injections));
70 }
71 result
72 }
73
74 pub fn to_token_stream(&self) -> TokenStream {
76 let mut idents = ident::Iter::new();
77 let output = idents.next().unwrap();
78 let expanded = self.expand(&output, &mut idents);
79
80 quote! {
81 {
82 let mut #output = ::zyn::proc_macro2::TokenStream::new();
83 let mut __zyn_diagnostic = ::zyn::mark::new();
84 #expanded
85 ::zyn::Output::new()
86 .tokens(#output)
87 .diagnostic(__zyn_diagnostic)
88 .build()
89 }
90 }
91 }
92
93 pub fn render(&self, input: &Input) -> TokenStream {
95 let expanded = self.to_token_stream();
96 quote! {
97 {
98 let input: ::zyn::Input = ::zyn::parse!(#input).unwrap();
99 #expanded
100 }
101 }
102 }
103
104 fn flush(pending: &mut TokenStream, nodes: &mut Vec<Node>) {
105 if pending.is_empty() {
106 return;
107 }
108
109 let stream = std::mem::take(pending);
110 let span = stream
111 .clone()
112 .into_iter()
113 .next()
114 .map(|tt| tt.span())
115 .unwrap_or_else(Span::call_site);
116
117 nodes.push(TokensNode { span, stream }.into());
118 }
119}
120
121impl Expand for Template {
122 fn expand(&self, output: &Ident, idents: &mut ident::Iter) -> TokenStream {
123 let mut result = TokenStream::new();
124
125 for node in &self.nodes {
126 result.extend(node.expand(output, idents));
127 }
128
129 result
130 }
131}
132
133impl Parse for Template {
134 fn parse(input: ParseStream) -> syn::Result<Self> {
135 let mut nodes = Vec::new();
136 let mut pending = TokenStream::new();
137
138 while !input.is_empty() {
139 if input.peek(Token![@]) {
140 Self::flush(&mut pending, &mut nodes);
141 nodes.push(input.parse::<AtNode>()?.into());
142 } else if input.peek(syn::token::Brace) {
143 Self::flush(&mut pending, &mut nodes);
144 nodes.push(Node::parse_brace(input)?);
145 } else if input.peek(syn::token::Paren) || input.peek(syn::token::Bracket) {
146 Self::flush(&mut pending, &mut nodes);
147 nodes.push(input.parse::<GroupNode>()?.into());
148 } else {
149 let tt: TokenTree = input.parse()?;
150 tt.to_tokens(&mut pending);
151 }
152 }
153
154 Self::flush(&mut pending, &mut nodes);
155 Ok(Self { nodes })
156 }
157}