1extern crate proc_macro;
2extern crate proc_macro2;
3extern crate syn;
4
5use proc_macro::TokenStream;
6use proc_macro2::TokenStream as TokenStream2;
7use proc_macro2::{Delimiter, Literal, Punct, Spacing, Span, TokenTree};
8use proc_macro_error::ResultExt;
9use quote::{quote as qquote, quote_spanned as qquote_spanned, TokenStreamExt};
10use std::collections::{HashSet, VecDeque};
11use syn::{parse_quote, Expr, Ident, Path, Token};
12
13struct ParseEnvironment {
19 span: Expr,
20 path_proc_macro2: Path,
21 path_quote: Path,
22 path_core: Path,
23 id_stream: Ident,
24 id_repeat: Ident,
25 id_counter: Ident,
26}
27
28impl syn::parse::Parse for ParseEnvironment {
29 fn parse(input: syn::parse::ParseStream<'_>) -> syn::parse::Result<Self> {
30 let mut fields: Vec<(Ident, Expr)> = Vec::new();
32 while !input.is_empty() {
33 let ident = input.parse()?;
34 input.parse::<Token![:]>()?;
35 let expr = input.parse()?;
36 fields.push((ident, expr));
37 if !input.is_empty() {
38 input.parse::<Token![,]>()?;
39 }
40 }
41 let mut this: ParseEnvironment = Default::default();
42 for (id, expr) in fields {
43 match (id.to_string().as_str(), expr) {
44 ("proc_macro2", Expr::Path(pat)) => {
45 this.path_proc_macro2 = pat.path;
46 }
47 ("quote", Expr::Path(pat)) => {
48 this.path_quote = pat.path;
49 }
50 ("core", Expr::Path(pat)) => {
51 this.path_core = pat.path;
52 }
53 ("span", expr) => {
54 this.span = expr;
55 }
56 (key, _) => {
57 return Err(input.error(&format!("Bad config name: {}", key)));
58 }
59 }
60 }
61 Ok(this)
62 }
63}
64
65impl core::default::Default for ParseEnvironment {
66 fn default() -> Self {
67 Self {
68 span: parse_quote! { ::proc_macro2::Span::call_site() },
69 path_proc_macro2: parse_quote! { ::proc_macro2 },
70 path_quote: parse_quote! { ::template_quote },
71 path_core: parse_quote! { ::core },
72 id_stream: parse_quote! { __template_quote_stream },
73 id_repeat: parse_quote! { __TemplateQuote_Repeat },
74 id_counter: parse_quote! { __template_quote_idcnt },
75 }
76 }
77}
78
79fn eat_terminator(input: &mut VecDeque<TokenTree>) -> bool {
80 match (input.pop_front(), input.pop_front(), input.pop_front()) {
81 (Some(TokenTree::Punct(p1)), Some(TokenTree::Punct(p2)), None)
82 if p1.as_char() == '.'
83 && p2.as_char() == '.'
84 && p1.spacing() == Spacing::Joint
85 && p2.spacing() == Spacing::Alone =>
86 {
87 return true;
88 }
89 (Some(tt1), Some(tt2), Some(tt3)) => {
90 input.push_front(tt3);
91 input.push_front(tt2);
92 input.push_front(tt1);
93 }
94 (Some(tt1), Some(tt2), None) => {
95 input.push_front(tt2);
96 input.push_front(tt1);
97 }
98 (Some(tt1), None, None) => {
99 input.push_front(tt1);
100 }
101 _ => (),
102 }
103 false
104}
105fn eat_comma(input: &mut VecDeque<TokenTree>) -> bool {
106 match input.pop_front() {
107 Some(TokenTree::Punct(p)) if p.as_char() == ',' && p.spacing() == Spacing::Alone => true,
108 Some(tt) => {
109 input.push_front(tt);
110 false
111 }
112 _ => false,
113 }
114}
115fn collect_ident(input: &mut VecDeque<TokenTree>) -> Result<Vec<Ident>, ()> {
116 fn collect_paren_stream(
117 mut input: VecDeque<TokenTree>,
118 ret: &mut Vec<Ident>,
119 ) -> Result<(), ()> {
120 while input.len() > 0 && !eat_terminator(&mut input) {
121 ret.extend(collect_ident(&mut input)?);
122 if input.len() > 0 && !eat_comma(&mut input) {
123 return Err(());
124 }
125 }
126 Ok(())
127 }
128 let mut ret = Vec::new();
129 match input.pop_front() {
130 Some(TokenTree::Group(g))
132 if (g.delimiter() == Delimiter::Parenthesis || g.delimiter() == Delimiter::Bracket) =>
133 {
134 collect_paren_stream(g.stream().into_iter().collect(), &mut ret)?;
135 Ok(ret)
136 }
137 Some(TokenTree::Ident(id)) => {
138 loop {
139 match input.pop_front() {
140 Some(TokenTree::Punct(colon))
141 if colon.as_char() == ':' && colon.spacing() == Spacing::Joint =>
142 {
143 if matches!(
144 input.pop_front(),
145 Some(TokenTree::Punct(colon)) if colon.as_char() == ':' && colon.spacing() == Spacing::Alone
146 ) && matches!(input.pop_front(), Some(TokenTree::Ident(_)))
147 {
148 continue;
149 } else {
150 return Err(());
151 }
152 }
153 Some(o) => input.push_front(o),
154 None => (),
155 }
156 break;
157 }
158 match input.pop_front() {
159 Some(TokenTree::Group(g)) if g.delimiter() == Delimiter::Parenthesis => {
161 collect_paren_stream(g.stream().into_iter().collect(), &mut ret)?;
162 Ok(ret)
163 }
164 Some(TokenTree::Group(g)) if g.delimiter() == Delimiter::Brace => {
166 let mut inner: VecDeque<TokenTree> = g.stream().into_iter().collect();
167 while inner.len() > 0 && !eat_terminator(&mut inner) {
168 match inner.pop_front().unwrap() {
169 TokenTree::Ident(key) => match (inner.pop_front(), inner.pop_front()) {
170 (Some(TokenTree::Punct(colon)), Some(TokenTree::Ident(value)))
171 if colon.as_char() == ':'
172 && colon.spacing() == Spacing::Alone =>
173 {
174 ret.push(value);
175 }
176 (item1, item2) => {
177 if let Some(tt2) = item2 {
178 inner.push_front(tt2);
179 }
180 if let Some(tt1) = item1 {
181 inner.push_front(tt1);
182 }
183 ret.push(key)
184 }
185 },
186 _ => return Err(()),
187 }
188 if inner.len() > 0 && !eat_comma(&mut inner) {
189 return Err(());
190 }
191 }
192 Ok(ret)
193 }
194 Some(o) => {
196 input.push_front(o);
197 ret.push(id);
198 Ok(ret)
199 }
200 None => {
201 ret.push(id);
202 Ok(ret)
203 }
204 }
205 }
206 _ => Err(()),
207 }
208}
209
210fn collect_ident_eq(input: &mut VecDeque<TokenTree>) -> Result<Vec<Ident>, ()> {
211 let v = collect_ident(input)?;
212 match input.pop_front() {
213 Some(TokenTree::Punct(eq)) if eq.as_char() == '=' && eq.spacing() == Spacing::Alone => {
214 Ok(v)
215 }
216 _ => Err(()),
217 }
218}
219
220fn collect_punct_in_expr(mut stream: VecDeque<TokenTree>) -> (Vec<Ident>, VecDeque<TokenTree>) {
221 let mut output = VecDeque::new();
222 let mut ids = Vec::new();
223 while let Some(tt) = stream.pop_front() {
224 match tt {
225 TokenTree::Punct(punct) if punct.as_char() == '#' => match stream.pop_front() {
226 Some(TokenTree::Ident(id)) => {
227 ids.push(id.clone());
228 output.push_back(TokenTree::Ident(id));
229 }
230 Some(o) => {
231 output.push_back(TokenTree::Punct(punct));
232 output.push_back(o);
233 }
234 None => {
235 output.push_back(TokenTree::Punct(punct));
236 }
237 },
238 o => output.push_back(o),
239 }
240 }
241 (ids, output)
242}
243
244fn hash_will_be_processed(next: Option<&TokenTree>, rest: &VecDeque<TokenTree>) -> bool {
245 match next {
246 Some(TokenTree::Ident(_)) => true,
247 Some(TokenTree::Group(group)) if group.delimiter() == Delimiter::Brace => true,
248 Some(TokenTree::Group(group)) if group.delimiter() == Delimiter::Parenthesis => {
249 match (rest.front(), rest.get(1)) {
250 (Some(TokenTree::Group(group2)), _)
251 if group2.delimiter() == Delimiter::Brace =>
252 {
253 true
254 }
255 (Some(TokenTree::Punct(punct)), _) if punct.as_char() == '*' => true,
256 (Some(TokenTree::Punct(_)), Some(TokenTree::Punct(punct2)))
257 if punct2.as_char() == '*' =>
258 {
259 true
260 }
261 (Some(TokenTree::Punct(_)), Some(TokenTree::Group(group2)))
262 if group2.delimiter() == Delimiter::Brace =>
263 {
264 true
265 }
266 _ => false,
267 }
268 }
269 _ => false,
270 }
271}
272
273fn keep_joint_before_processed_hash(punct: char) -> bool {
274 matches!(punct, '+' | '-' | ':' | '<' | '>')
275}
276
277impl ParseEnvironment {
278 fn emit_ident(&self, ident: &Ident) -> TokenStream2 {
279 let Self {
280 span,
281 path_proc_macro2,
282 path_quote,
283 id_stream,
284 ..
285 } = self;
286 let s = ident.to_string();
287 if s.starts_with("r#") {
288 let s = &s[2..];
289 qquote! {
290 <_ as #path_quote::ToTokens>::to_tokens(&#path_proc_macro2::Ident::new_raw(#s, (#span)), &mut #id_stream);
291 }
292 } else {
293 qquote! {
294 <_ as #path_quote::ToTokens>::to_tokens(&#path_proc_macro2::Ident::new(#s, (#span)), &mut #id_stream);
295 }
296 }
297 }
298
299 fn emit_literal(&self, lit: &Literal) -> TokenStream2 {
300 let Self {
301 span,
302 path_proc_macro2,
303 id_stream,
304 ..
305 } = self;
306 let s = lit.to_string();
307 qquote! {
308 {
309 let ts: #path_proc_macro2::TokenStream = #s.parse().expect("Invalid literal str");
310 #id_stream.extend(ts.into_iter().map(|mut t| {
311 t.set_span(#span);
312 t
313 }));
314 }
315 }
316 }
317
318 fn emit_punct(&self, punct: &Punct) -> TokenStream2 {
319 let Self {
320 span,
321 path_proc_macro2,
322 path_quote,
323 id_stream,
324 ..
325 } = self;
326 let p = punct.as_char();
327 let spacing = match punct.spacing() {
328 Spacing::Alone => qquote! {#path_proc_macro2::Spacing::Alone},
329 Spacing::Joint => qquote! {#path_proc_macro2::Spacing::Joint},
330 };
331 qquote! {
332 <_ as #path_quote::ToTokens>::to_tokens(&{
333 let mut p = #path_proc_macro2::Punct::new(#p, #spacing);
334 p.set_span(#span);
335 p
336 }, &mut #id_stream);
337 }
338 }
339
340 fn emit_punct_with_spacing(&self, punct: &Punct, spacing: Spacing) -> TokenStream2 {
341 let mut p = Punct::new(punct.as_char(), spacing);
342 p.set_span(punct.span());
343 self.emit_punct(&p)
344 }
345
346 fn emit_group(&self, delim: &Delimiter, inner: TokenStream2) -> TokenStream2 {
347 let Self {
348 span,
349 path_proc_macro2,
350 path_core,
351 id_stream,
352 ..
353 } = self;
354 let delim = match delim {
355 Delimiter::Parenthesis => qquote! { #path_proc_macro2::Delimiter::Parenthesis },
356 Delimiter::Brace => qquote! { #path_proc_macro2::Delimiter::Brace },
357 Delimiter::Bracket => qquote! { #path_proc_macro2::Delimiter::Bracket },
358 Delimiter::None => qquote! { #path_proc_macro2::Delimiter::None },
359 };
360 qquote! {
361 #id_stream.extend(
362 #path_core::option::Option::Some(
363 #path_proc_macro2::TokenTree::Group(
364 {
365 let mut g = #path_proc_macro2::Group::new(#delim, {
366 let mut #id_stream = #path_proc_macro2::TokenStream::new();
367 { #inner }
368 #id_stream
369 });
370 g.set_span(#span);
371 g
372 }
373 )
374 )
375 );
376 }
377 }
378
379 fn parse_conditional(
380 &self,
381 conditional: TokenStream2,
382 input: VecDeque<TokenTree>,
383 vals: &mut HashSet<Ident>,
384 sep: Option<Punct>,
385 inline_expr_dict: &mut Vec<(Ident, TokenStream2, Span)>,
386 ) -> TokenStream2 {
387 fn parse_if_inner(
388 mut cond: VecDeque<TokenTree>,
389 ) -> (Vec<Ident>, Vec<Ident>, Vec<TokenTree>) {
390 let mut bak: Vec<_> = cond.iter().cloned().collect();
391 match cond.pop_front() {
392 Some(TokenTree::Ident(id_let)) if &id_let.to_string() == "let" => {
393 let removing_ids =
394 collect_ident_eq(&mut cond).expect("Bad format in if-let conditional");
395 bak.truncate(bak.len() - cond.len());
396 let (appending_ids, rem) = collect_punct_in_expr(cond);
397 bak.extend(rem);
398 (removing_ids, appending_ids, bak)
399 }
400 Some(o) => {
401 cond.push_front(o);
402 bak.truncate(bak.len() - cond.len());
403 let (appending_ids, rem) = collect_punct_in_expr(cond);
404 bak.extend(rem);
405 (vec![], appending_ids, bak)
406 }
407 None => panic!("if syntax is empty"),
408 }
409 }
410 let mut cond: VecDeque<TokenTree> = conditional.clone().into_iter().collect();
411 let cond_len = cond.len();
412 let (removing_ids, appending_ids, cond) = match (cond.pop_front(), sep.is_some()) {
413 (Some(TokenTree::Ident(id)), false) if &id.to_string() == "if" => {
414 let (removing_ids, appending_ids, rem) = parse_if_inner(cond);
415 (
416 removing_ids,
417 appending_ids,
418 Some(TokenTree::Ident(id)).into_iter().chain(rem).collect(),
419 )
420 }
421 (Some(TokenTree::Ident(id)), false) if &id.to_string() == "else" => {
422 match cond.pop_front() {
423 Some(TokenTree::Ident(id_if)) if &id_if.to_string() == "if" => {
425 let (removing_ids, appending_ids, rem) = parse_if_inner(cond);
426 (
427 removing_ids,
428 appending_ids,
429 vec![TokenTree::Ident(id), TokenTree::Ident(id_if)]
430 .into_iter()
431 .chain(rem)
432 .collect(),
433 )
434 }
435 Some(_) => panic!("Bad format in else conditional"),
436 None => (vec![], vec![], conditional),
437 }
438 }
439 (Some(TokenTree::Ident(id)), false) if id.to_string() == "let" => {
440 let removing_ids = collect_ident_eq(&mut cond).expect("Bad format in let binding");
441 let n = cond_len - cond.len();
442 let (appending_ids, rem) = collect_punct_in_expr(cond);
443 let conditional: TokenStream2 =
444 conditional.clone().into_iter().take(n).chain(rem).collect();
445 (removing_ids, appending_ids, qquote! {#conditional ;})
446 }
447 (Some(TokenTree::Ident(id)), _) if id.to_string() == "while" => {
448 match cond.pop_front() {
449 Some(TokenTree::Ident(id_let)) if &id_let.to_string() == "let" => {
450 let removing_ids =
451 collect_ident_eq(&mut cond).expect("Bad format in while-let loop");
452 let n = cond_len - cond.len();
453 let (appending_ids, rem) = collect_punct_in_expr(cond);
454 let conditional: TokenStream2 =
455 conditional.clone().into_iter().take(n).chain(rem).collect();
456 (removing_ids, appending_ids, conditional)
457 }
458 Some(o) => {
459 cond.push_front(o);
460 let n = cond_len - cond.len();
461 let (appending_ids, rem) = collect_punct_in_expr(cond);
462 let conditional: TokenStream2 =
463 conditional.clone().into_iter().take(n).chain(rem).collect();
464 (vec![], appending_ids, conditional)
465 }
466 None => panic!("while syntax is empty"),
467 }
468 }
469 (Some(TokenTree::Ident(id)), _) if id.to_string() == "for" => {
470 match (collect_ident(&mut cond), cond.pop_front()) {
471 (Ok(v), Some(TokenTree::Ident(id_in))) if &id_in.to_string() == "in" => {
472 let n = cond_len - cond.len();
473 let (appending_ids, rem) = collect_punct_in_expr(cond);
474 let conditional: TokenStream2 =
475 conditional.clone().into_iter().take(n).chain(rem).collect();
476 (v, appending_ids, conditional)
477 }
478 _ => panic!("Bad format in for loop"),
479 }
480 }
481 _ => panic!("Bad format in conditional"),
482 };
483 let inner = self.parse_inner(input, vals, inline_expr_dict);
484 for id in removing_ids {
485 vals.remove(&id);
486 }
487 for id in appending_ids {
488 vals.insert(id);
489 }
490 if let Some(sep) = sep {
491 let code_sep = self.emit_punct(&sep);
492 let id_counter = &self.id_counter;
493 qquote! {
494 {
495 let mut #id_counter = false;
496 #cond {
497 if #id_counter { #code_sep }
498 #id_counter = true;
499 #inner
500 }
501 }
502 }
503 } else {
504 qquote! {
505 #cond {
506 #inner
507 }
508 }
509 }
510 }
511
512 fn parse_iteration(
513 &self,
514 input: VecDeque<TokenTree>,
515 vals: &mut HashSet<Ident>,
516 sep: Option<Punct>,
517 inline_expr_dict: &mut Vec<(Ident, TokenStream2, Span)>,
518 ) -> TokenStream2 {
519 let Self {
520 path_quote,
521 id_repeat,
522 ..
523 } = self;
524 let debug_str = input
525 .iter()
526 .take(6)
527 .map(|item| match item {
528 TokenTree::Group(g) => match g.delimiter() {
529 Delimiter::Parenthesis => "( .. )".to_owned(),
530 Delimiter::Brace => "{ .. }".to_owned(),
531 Delimiter::Bracket => "[ .. ]".to_owned(),
532 Delimiter::None => "..".to_owned(),
533 },
534 _ => format!("{}", item),
535 })
536 .chain(if input.len() > 6 {
537 Some("..".to_owned())
538 } else {
539 None
540 })
541 .collect::<Vec<_>>()
542 .join(" ");
543 let mut inner_vals = HashSet::new();
544 let inner_output = self.parse_inner(input, &mut inner_vals, inline_expr_dict);
545 let code_sep = sep.map(|sep| self.emit_punct(&Punct::new(sep.as_char(), Spacing::Alone)));
546 let val_nam = code_sep
547 .as_ref()
548 .map(|_| self.id_counter.clone())
549 .into_iter()
550 .collect::<Vec<_>>();
551 vals.extend(inner_vals.iter().cloned());
552 let mut iter = inner_vals.iter();
553 let first = iter.next().expect("Iterative vals not found");
554 let idents_in_tuple = iter.clone().cloned().fold(qquote! {#first}, |prev, next| {
555 qquote! {
556 (#prev, #next)
557 }
558 });
559 let zip_iterators = iter
560 .clone()
561 .map(|ident| {
562 qquote! {
563 .zip(#ident .__template_quote__as_repeat())
564 }
565 })
566 .collect::<Vec<_>>();
567 let zip_iterator_checkers = inner_vals.iter().fold(qquote! {false}, |acc, ident| {
568 qquote! {#acc || (&#ident).__template_quote_is_iterable()}
569 });
570 qquote! {
571 {
572 #(let mut #val_nam = false;)*
573 use #path_quote::Repeat as #id_repeat;
574 if !(#zip_iterator_checkers) {
575 ::core::panic!("Cannot iterate the group: #( {} )*", #debug_str);
576 }
577 for #idents_in_tuple in #first .__template_quote__as_repeat() #(#zip_iterators)* {
578 #(
579 if #val_nam { #code_sep }
580 #val_nam = true;
581 )*
582 #inner_output
583 }
584 }
585 }
586 }
587
588 fn parse(&self, input: TokenStream2) -> TokenStream2 {
589 let Self {
590 path_proc_macro2,
591 id_stream,
592 ..
593 } = self;
594 let mut hs = HashSet::new();
595 let mut dict = Vec::new();
596 let result = self.parse_inner(input.into_iter().collect(), &mut hs, &mut dict);
597 let inline_vals_code =
598 dict.into_iter()
599 .fold(TokenStream2::new(), |acc, (id, inner, span)| {
600 qquote_spanned! { span =>
601 #acc
602 let #id = { #inner };
603 }
604 });
605 qquote! {
606 {
607 let mut #id_stream= #path_proc_macro2::TokenStream::new();
608 #inline_vals_code
609 { #result }
610 #id_stream
611 }
612 }
613 }
614
615 fn parse_inner(
616 &self,
617 mut input: VecDeque<TokenTree>,
618 vals: &mut HashSet<Ident>,
619 inline_expr_dict: &mut Vec<(Ident, TokenStream2, Span)>,
620 ) -> TokenStream2 {
621 let Self {
622 path_quote,
623 id_stream,
624 ..
625 } = self;
626 let mut output = TokenStream2::new();
627 while let Some(token) = input.pop_front() {
628 match token {
629 TokenTree::Group(group) => {
630 let inner = group.stream().into_iter().collect();
631 let result = self.parse_inner(inner, vals, inline_expr_dict);
632 let result = self.emit_group(&group.delimiter(), result);
633 output.append_all(result);
634 }
635 TokenTree::Punct(punct) => match (punct.as_char(), input.pop_front()) {
636 ('#', Some(TokenTree::Ident(ident))) => {
638 vals.insert(ident.clone());
639 output.append_all(
640 qquote! { <_ as #path_quote::ToTokens>::to_tokens(&#ident, &mut #id_stream); },
641 );
642 }
643 ('#', Some(TokenTree::Group(group)))
645 if group.delimiter() == Delimiter::Brace =>
646 {
647 let inner = group.stream().into_iter().collect::<VecDeque<_>>();
648 let is_expr = match inner.get(core::cmp::max(0, inner.len() - 1)) {
650 Some(TokenTree::Punct(p)) if p.as_char() == ';' => false,
651 _ => true,
652 };
653 let (appending_ids, inner) = collect_punct_in_expr(inner);
654 for id in appending_ids {
655 vals.insert(id);
656 }
657 let stream: TokenStream2 = inner.into_iter().collect();
658 if is_expr {
659 output.append_all(qquote! {
660 <_ as #path_quote::ToTokens>::to_tokens(&{
661 #stream
662 }, &mut #id_stream);
663 });
664 } else {
665 output.append_all(qquote! {
666 { #stream }
667 });
668 }
669 }
670 ('#', Some(TokenTree::Group(group)))
671 if group.delimiter() == Delimiter::Parenthesis =>
672 {
673 match input.pop_front() {
674 Some(TokenTree::Group(group2))
676 if group2.delimiter() == Delimiter::Brace =>
677 {
678 output.append_all(self.parse_conditional(
679 group.stream().into(),
680 group2.stream().into_iter().collect(),
681 vals,
682 None,
683 inline_expr_dict,
684 ));
685 }
686 Some(TokenTree::Punct(punct)) if punct.as_char() == '*' => output
688 .append_all(self.parse_iteration(
689 group.stream().into_iter().collect(),
690 vals,
691 None,
692 inline_expr_dict,
693 )),
694 Some(TokenTree::Punct(punct0)) => match input.pop_front() {
695 Some(TokenTree::Punct(punct1)) if punct1.as_char() == '*' => output
697 .append_all(self.parse_iteration(
698 group.stream().into_iter().collect(),
699 vals,
700 Some(punct0),
701 inline_expr_dict,
702 )),
703 Some(TokenTree::Group(group2))
705 if group2.delimiter() == Delimiter::Brace =>
706 {
707 output.append_all(self.parse_conditional(
708 group.stream().into(),
709 group2.stream().into_iter().collect(),
710 vals,
711 Some(punct0),
712 inline_expr_dict,
713 ));
714 }
715 o => {
716 if let Some(o) = o {
717 input.push_front(o);
718 }
719 input.push_front(TokenTree::Punct(punct0));
720 input.push_front(TokenTree::Group(group));
721 output.append_all(self.emit_punct(&punct));
722 }
723 },
724 o => {
725 if let Some(o) = o {
726 input.push_front(o)
727 }
728 input.push_front(TokenTree::Group(group));
729 output.append_all(self.emit_punct(&punct));
730 }
731 }
732 }
733 (_, o) => {
734 let adjust_joint_before_hash = punct.spacing() == Spacing::Joint
735 && matches!(o, Some(TokenTree::Punct(ref p)) if p.as_char() == '#')
736 && !keep_joint_before_processed_hash(punct.as_char())
737 && hash_will_be_processed(input.front(), &input);
738 if let Some(o) = o {
739 input.push_front(o);
740 }
741 if adjust_joint_before_hash {
742 output.append_all(self.emit_punct_with_spacing(&punct, Spacing::Alone));
743 } else {
744 output.append_all(self.emit_punct(&punct));
745 }
746 }
747 },
748 TokenTree::Ident(o) => output.append_all(self.emit_ident(&o)),
749 TokenTree::Literal(o) => output.append_all(self.emit_literal(&o)),
750 }
751 }
752 output
753 }
754}
755
756#[proc_macro]
757pub fn quote(input: TokenStream) -> TokenStream {
758 let env: ParseEnvironment = Default::default();
759 env.parse(input.into()).into()
760}
761
762#[proc_macro]
763pub fn quote_configured(input: TokenStream) -> TokenStream {
764 let input0: TokenStream2 = input.into();
765 let mut input = VecDeque::new();
766 input.extend(input0.into_iter());
767 let env: ParseEnvironment = match input.pop_front() {
768 Some(TokenTree::Group(g)) if g.delimiter() == Delimiter::Brace => {
769 syn::parse2(g.stream()).expect_or_abort("Bad config format")
770 }
771 _ => panic!("Bad config format"),
772 };
773 match input.pop_front() {
774 Some(TokenTree::Punct(p)) if p.as_char() == '=' && p.spacing() == Spacing::Joint => (),
775 _ => panic!("Bad config format"),
776 }
777 match input.pop_front() {
778 Some(TokenTree::Punct(p)) if p.as_char() == '>' && p.spacing() == Spacing::Alone => (),
779 _ => panic!("Bad config format"),
780 }
781 let mut stream = TokenStream2::new();
782 stream.extend(input);
783 env.parse(stream).into()
784}
785
786#[proc_macro]
787pub fn quote_spanned(input: TokenStream) -> TokenStream {
788 let input0: TokenStream2 = input.into();
789 let mut input = VecDeque::new();
790 input.extend(input0.into_iter());
791 let mut span = TokenStream2::new(); loop {
793 match input.pop_front() {
794 Some(TokenTree::Punct(p)) if p.as_char() == '=' && p.spacing() == Spacing::Joint => {
795 match input.pop_front() {
796 Some(TokenTree::Punct(p))
797 if p.as_char() == '>' && p.spacing() == Spacing::Alone =>
798 {
799 break;
801 }
802 Some(o) => {
803 span.extend(Some(TokenTree::Punct(p)));
804 input.push_front(o);
805 }
806 None => {
807 span.extend(Some(TokenTree::Punct(p)));
808 }
809 }
810 }
811 Some(o) => span.extend(Some(o)),
812 None => panic!("wrong quote_spanned format"),
813 }
814 }
815 let mut env: ParseEnvironment = Default::default();
816 env.span = syn::parse2(span).expect_or_abort("Span must be expr");
817 let mut stream = TokenStream2::new();
818 stream.extend(input);
819 env.parse(stream).into()
820}