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