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
244impl ParseEnvironment {
245 fn emit_ident(&self, ident: &Ident) -> TokenStream2 {
246 let Self {
247 span,
248 path_proc_macro2,
249 path_quote,
250 id_stream,
251 ..
252 } = self;
253 let s = ident.to_string();
254 if s.starts_with("r#") {
255 let s = &s[2..];
256 qquote! {
257 <_ as #path_quote::ToTokens>::to_tokens(&#path_proc_macro2::Ident::new_raw(#s, (#span)), &mut #id_stream);
258 }
259 } else {
260 qquote! {
261 <_ as #path_quote::ToTokens>::to_tokens(&#path_proc_macro2::Ident::new(#s, (#span)), &mut #id_stream);
262 }
263 }
264 }
265
266 fn emit_literal(&self, lit: &Literal) -> TokenStream2 {
267 let Self {
268 span,
269 path_proc_macro2,
270 id_stream,
271 ..
272 } = self;
273 let s = lit.to_string();
274 qquote! {
275 {
276 let ts: #path_proc_macro2::TokenStream = #s.parse().expect("Invalid literal str");
277 #id_stream.extend(ts.into_iter().map(|mut t| {
278 t.set_span(#span);
279 t
280 }));
281 }
282 }
283 }
284
285 fn emit_punct(&self, punct: &Punct) -> TokenStream2 {
286 let Self {
287 span,
288 path_proc_macro2,
289 path_quote,
290 id_stream,
291 ..
292 } = self;
293 let p = punct.as_char();
294 let spacing = match punct.spacing() {
295 Spacing::Alone => qquote! {#path_proc_macro2::Spacing::Alone},
296 Spacing::Joint => qquote! {#path_proc_macro2::Spacing::Joint},
297 };
298 qquote! {
299 <_ as #path_quote::ToTokens>::to_tokens(&{
300 let mut p = #path_proc_macro2::Punct::new(#p, #spacing);
301 p.set_span(#span);
302 p
303 }, &mut #id_stream);
304 }
305 }
306
307 fn emit_group(&self, delim: &Delimiter, inner: TokenStream2) -> TokenStream2 {
308 let Self {
309 span,
310 path_proc_macro2,
311 path_core,
312 id_stream,
313 ..
314 } = self;
315 let delim = match delim {
316 Delimiter::Parenthesis => qquote! { #path_proc_macro2::Delimiter::Parenthesis },
317 Delimiter::Brace => qquote! { #path_proc_macro2::Delimiter::Brace },
318 Delimiter::Bracket => qquote! { #path_proc_macro2::Delimiter::Bracket },
319 Delimiter::None => qquote! { #path_proc_macro2::Delimiter::None },
320 };
321 qquote! {
322 #id_stream.extend(
323 #path_core::option::Option::Some(
324 #path_proc_macro2::TokenTree::Group(
325 {
326 let mut g = #path_proc_macro2::Group::new(#delim, {
327 let mut #id_stream = #path_proc_macro2::TokenStream::new();
328 { #inner }
329 #id_stream
330 });
331 g.set_span(#span);
332 g
333 }
334 )
335 )
336 );
337 }
338 }
339
340 fn parse_conditional(
341 &self,
342 conditional: TokenStream2,
343 input: VecDeque<TokenTree>,
344 vals: &mut HashSet<Ident>,
345 sep: Option<Punct>,
346 inline_expr_dict: &mut Vec<(Ident, TokenStream2, Span)>,
347 ) -> TokenStream2 {
348 fn parse_if_inner(
349 mut cond: VecDeque<TokenTree>,
350 ) -> (Vec<Ident>, Vec<Ident>, Vec<TokenTree>) {
351 let mut bak: Vec<_> = cond.iter().cloned().collect();
352 match cond.pop_front() {
353 Some(TokenTree::Ident(id_let)) if &id_let.to_string() == "let" => {
354 let removing_ids =
355 collect_ident_eq(&mut cond).expect("Bad format in if-let conditional");
356 bak.truncate(bak.len() - cond.len());
357 let (appending_ids, rem) = collect_punct_in_expr(cond);
358 bak.extend(rem);
359 (removing_ids, appending_ids, bak)
360 }
361 Some(o) => {
362 cond.push_front(o);
363 bak.truncate(bak.len() - cond.len());
364 let (appending_ids, rem) = collect_punct_in_expr(cond);
365 bak.extend(rem);
366 (vec![], appending_ids, bak)
367 }
368 None => panic!("if syntax is empty"),
369 }
370 }
371 let mut cond: VecDeque<TokenTree> = conditional.clone().into_iter().collect();
372 let cond_len = cond.len();
373 let (removing_ids, appending_ids, cond) = match (cond.pop_front(), sep.is_some()) {
374 (Some(TokenTree::Ident(id)), false) if &id.to_string() == "if" => {
375 let (removing_ids, appending_ids, rem) = parse_if_inner(cond);
376 (
377 removing_ids,
378 appending_ids,
379 Some(TokenTree::Ident(id)).into_iter().chain(rem).collect(),
380 )
381 }
382 (Some(TokenTree::Ident(id)), false) if &id.to_string() == "else" => {
383 match cond.pop_front() {
384 Some(TokenTree::Ident(id_if)) if &id_if.to_string() == "if" => {
386 let (removing_ids, appending_ids, rem) = parse_if_inner(cond);
387 (
388 removing_ids,
389 appending_ids,
390 vec![TokenTree::Ident(id), TokenTree::Ident(id_if)]
391 .into_iter()
392 .chain(rem)
393 .collect(),
394 )
395 }
396 Some(_) => panic!("Bad format in else conditional"),
397 None => (vec![], vec![], conditional),
398 }
399 }
400 (Some(TokenTree::Ident(id)), false) if id.to_string() == "let" => {
401 let removing_ids = collect_ident_eq(&mut cond).expect("Bad format in let binding");
402 let n = cond_len - cond.len();
403 let (appending_ids, rem) = collect_punct_in_expr(cond);
404 let conditional: TokenStream2 =
405 conditional.clone().into_iter().take(n).chain(rem).collect();
406 (removing_ids, appending_ids, qquote! {#conditional ;})
407 }
408 (Some(TokenTree::Ident(id)), _) if id.to_string() == "while" => {
409 match cond.pop_front() {
410 Some(TokenTree::Ident(id_let)) if &id_let.to_string() == "let" => {
411 let removing_ids =
412 collect_ident_eq(&mut cond).expect("Bad format in while-let loop");
413 let n = cond_len - cond.len();
414 let (appending_ids, rem) = collect_punct_in_expr(cond);
415 let conditional: TokenStream2 =
416 conditional.clone().into_iter().take(n).chain(rem).collect();
417 (removing_ids, appending_ids, conditional)
418 }
419 Some(o) => {
420 cond.push_front(o);
421 let n = cond_len - cond.len();
422 let (appending_ids, rem) = collect_punct_in_expr(cond);
423 let conditional: TokenStream2 =
424 conditional.clone().into_iter().take(n).chain(rem).collect();
425 (vec![], appending_ids, conditional)
426 }
427 None => panic!("while syntax is empty"),
428 }
429 }
430 (Some(TokenTree::Ident(id)), _) if id.to_string() == "for" => {
431 match (collect_ident(&mut cond), cond.pop_front()) {
432 (Ok(v), Some(TokenTree::Ident(id_in))) if &id_in.to_string() == "in" => {
433 let n = cond_len - cond.len();
434 let (appending_ids, rem) = collect_punct_in_expr(cond);
435 let conditional: TokenStream2 =
436 conditional.clone().into_iter().take(n).chain(rem).collect();
437 (v, appending_ids, conditional)
438 }
439 _ => panic!("Bad format in for loop"),
440 }
441 }
442 _ => panic!("Bad format in conditional"),
443 };
444 let inner = self.parse_inner(input, vals, inline_expr_dict);
445 for id in removing_ids {
446 vals.remove(&id);
447 }
448 for id in appending_ids {
449 vals.insert(id);
450 }
451 if let Some(sep) = sep {
452 let code_sep = self.emit_punct(&sep);
453 let id_counter = &self.id_counter;
454 qquote! {
455 {
456 let mut #id_counter = false;
457 #cond {
458 if #id_counter { #code_sep }
459 #id_counter = true;
460 #inner
461 }
462 }
463 }
464 } else {
465 qquote! {
466 #cond {
467 #inner
468 }
469 }
470 }
471 }
472
473 fn parse_iteration(
474 &self,
475 input: VecDeque<TokenTree>,
476 vals: &mut HashSet<Ident>,
477 sep: Option<Punct>,
478 inline_expr_dict: &mut Vec<(Ident, TokenStream2, Span)>,
479 ) -> TokenStream2 {
480 let Self {
481 path_quote,
482 id_repeat,
483 ..
484 } = self;
485 let debug_str = input
486 .iter()
487 .take(5)
488 .map(|item| match item {
489 TokenTree::Group(g) => match g.delimiter() {
490 Delimiter::Parenthesis => "( .. )".to_owned(),
491 Delimiter::Brace => "{ .. }".to_owned(),
492 Delimiter::Bracket => "[ .. ]".to_owned(),
493 Delimiter::None => "..".to_owned(),
494 },
495 _ => format!("{}", item),
496 })
497 .collect::<Vec<_>>()
498 .join(" ");
499 let mut inner_vals = HashSet::new();
500 let inner_output = self.parse_inner(input, &mut inner_vals, inline_expr_dict);
501 let code_sep = sep.map(|sep| self.emit_punct(&Punct::new(sep.as_char(), Spacing::Alone)));
502 let val_nam = code_sep
503 .as_ref()
504 .map(|_| self.id_counter.clone())
505 .into_iter()
506 .collect::<Vec<_>>();
507 vals.extend(inner_vals.iter().cloned());
508 let mut iter = inner_vals.iter();
509 let first = iter.next().expect("Iterative vals not found");
510 let idents_in_tuple = iter.clone().cloned().fold(qquote! {#first}, |prev, next| {
511 qquote! {
512 (#prev, #next)
513 }
514 });
515 let zip_iterators = iter
516 .clone()
517 .map(|ident| {
518 qquote! {
519 .zip(#ident .__template_quote__as_repeat())
520 }
521 })
522 .collect::<Vec<_>>();
523 let zip_iterator_checkers = inner_vals.iter().fold(qquote! {false}, |acc, ident| {
524 qquote! {#acc || (&#ident).__template_quote_is_iterable()}
525 });
526 qquote! {
527 {
528 #(let mut #val_nam = false;)*
529 use #path_quote::Repeat as #id_repeat;
530 if !(#zip_iterator_checkers) {
531 ::core::panic!("Cannot iterate the group: #( {} )*", #debug_str);
532 }
533 for #idents_in_tuple in #first .__template_quote__as_repeat() #(#zip_iterators)* {
534 #(
535 if #val_nam { #code_sep }
536 #val_nam = true;
537 )*
538 #inner_output
539 }
540 }
541 }
542 }
543
544 fn parse(&self, input: TokenStream2) -> TokenStream2 {
545 let Self {
546 path_proc_macro2,
547 id_stream,
548 ..
549 } = self;
550 let mut hs = HashSet::new();
551 let mut dict = Vec::new();
552 let result = self.parse_inner(input.into_iter().collect(), &mut hs, &mut dict);
553 let inline_vals_code =
554 dict.into_iter()
555 .fold(TokenStream2::new(), |acc, (id, inner, span)| {
556 qquote_spanned! { span =>
557 #acc
558 let #id = { #inner };
559 }
560 });
561 qquote! {
562 {
563 let mut #id_stream= #path_proc_macro2::TokenStream::new();
564 #inline_vals_code
565 { #result }
566 #id_stream
567 }
568 }
569 }
570
571 fn parse_inner(
572 &self,
573 mut input: VecDeque<TokenTree>,
574 vals: &mut HashSet<Ident>,
575 inline_expr_dict: &mut Vec<(Ident, TokenStream2, Span)>,
576 ) -> TokenStream2 {
577 let Self {
578 path_quote,
579 id_stream,
580 ..
581 } = self;
582 let mut output = TokenStream2::new();
583 while let Some(token) = input.pop_front() {
584 match token {
585 TokenTree::Group(group) => {
586 let inner = group.stream().into_iter().collect();
587 let result = self.parse_inner(inner, vals, inline_expr_dict);
588 let result = self.emit_group(&group.delimiter(), result);
589 output.append_all(result);
590 }
591 TokenTree::Punct(punct) => match (punct.as_char(), input.pop_front()) {
592 ('#', Some(TokenTree::Ident(ident))) => {
594 vals.insert(ident.clone());
595 output.append_all(
596 qquote! { <_ as #path_quote::ToTokens>::to_tokens(&#ident, &mut #id_stream); },
597 );
598 }
599 ('#', Some(TokenTree::Group(group)))
601 if group.delimiter() == Delimiter::Brace =>
602 {
603 let inner = group.stream().into_iter().collect::<VecDeque<_>>();
604 let is_expr = match inner.get(core::cmp::max(0, inner.len() - 1)) {
606 Some(TokenTree::Punct(p)) if p.as_char() == ';' => false,
607 _ => true,
608 };
609 let (appending_ids, inner) = collect_punct_in_expr(inner);
610 for id in appending_ids {
611 vals.insert(id);
612 }
613 let stream: TokenStream2 = inner.into_iter().collect();
614 if is_expr {
615 output.append_all(qquote! {
616 <_ as #path_quote::ToTokens>::to_tokens(&{
617 #stream
618 }, &mut #id_stream);
619 });
620 } else {
621 output.append_all(qquote! {
622 { #stream }
623 });
624 }
625 }
626 ('#', Some(TokenTree::Group(group)))
627 if group.delimiter() == Delimiter::Parenthesis =>
628 {
629 match input.pop_front() {
630 Some(TokenTree::Group(group2))
632 if group2.delimiter() == Delimiter::Brace =>
633 {
634 output.append_all(self.parse_conditional(
635 group.stream().into(),
636 group2.stream().into_iter().collect(),
637 vals,
638 None,
639 inline_expr_dict,
640 ));
641 }
642 Some(TokenTree::Punct(punct)) if punct.as_char() == '*' => output
644 .append_all(self.parse_iteration(
645 group.stream().into_iter().collect(),
646 vals,
647 None,
648 inline_expr_dict,
649 )),
650 Some(TokenTree::Punct(punct0)) => match input.pop_front() {
651 Some(TokenTree::Punct(punct1)) if punct1.as_char() == '*' => output
653 .append_all(self.parse_iteration(
654 group.stream().into_iter().collect(),
655 vals,
656 Some(punct0),
657 inline_expr_dict,
658 )),
659 Some(TokenTree::Group(group2))
661 if group2.delimiter() == Delimiter::Brace =>
662 {
663 output.append_all(self.parse_conditional(
664 group.stream().into(),
665 group2.stream().into_iter().collect(),
666 vals,
667 Some(punct0),
668 inline_expr_dict,
669 ));
670 }
671 o => {
672 if let Some(o) = o {
673 input.push_front(o);
674 }
675 input.push_front(TokenTree::Punct(punct0));
676 input.push_front(TokenTree::Group(group));
677 output.append_all(self.emit_punct(&punct));
678 }
679 },
680 o => {
681 if let Some(o) = o {
682 input.push_front(o)
683 }
684 input.push_front(TokenTree::Group(group));
685 output.append_all(self.emit_punct(&punct));
686 }
687 }
688 }
689 (_, o) => {
690 if let Some(o) = o {
691 input.push_front(o);
692 }
693 output.append_all(self.emit_punct(&punct));
694 }
695 },
696 TokenTree::Ident(o) => output.append_all(self.emit_ident(&o)),
697 TokenTree::Literal(o) => output.append_all(self.emit_literal(&o)),
698 }
699 }
700 output
701 }
702}
703
704#[proc_macro]
705pub fn quote(input: TokenStream) -> TokenStream {
706 let env: ParseEnvironment = Default::default();
707 env.parse(input.into()).into()
708}
709
710#[proc_macro]
711pub fn quote_configured(input: TokenStream) -> TokenStream {
712 let input0: TokenStream2 = input.into();
713 let mut input = VecDeque::new();
714 input.extend(input0.into_iter());
715 let env: ParseEnvironment = match input.pop_front() {
716 Some(TokenTree::Group(g)) if g.delimiter() == Delimiter::Brace => {
717 syn::parse2(g.stream()).expect_or_abort("Bad config format")
718 }
719 _ => panic!("Bad config format"),
720 };
721 match input.pop_front() {
722 Some(TokenTree::Punct(p)) if p.as_char() == '=' && p.spacing() == Spacing::Joint => (),
723 _ => panic!("Bad config format"),
724 }
725 match input.pop_front() {
726 Some(TokenTree::Punct(p)) if p.as_char() == '>' && p.spacing() == Spacing::Alone => (),
727 _ => panic!("Bad config format"),
728 }
729 let mut stream = TokenStream2::new();
730 stream.extend(input);
731 env.parse(stream).into()
732}
733
734#[proc_macro]
735pub fn quote_spanned(input: TokenStream) -> TokenStream {
736 let input0: TokenStream2 = input.into();
737 let mut input = VecDeque::new();
738 input.extend(input0.into_iter());
739 let mut span = TokenStream2::new(); loop {
741 match input.pop_front() {
742 Some(TokenTree::Punct(p)) if p.as_char() == '=' && p.spacing() == Spacing::Joint => {
743 match input.pop_front() {
744 Some(TokenTree::Punct(p))
745 if p.as_char() == '>' && p.spacing() == Spacing::Alone =>
746 {
747 break;
749 }
750 Some(o) => {
751 span.extend(Some(TokenTree::Punct(p)));
752 input.push_front(o);
753 }
754 None => {
755 span.extend(Some(TokenTree::Punct(p)));
756 }
757 }
758 }
759 Some(o) => span.extend(Some(o)),
760 None => panic!("wrong quote_spanned format"),
761 }
762 }
763 let mut env: ParseEnvironment = Default::default();
764 env.span = syn::parse2(span).expect_or_abort("Span must be expr");
765 let mut stream = TokenStream2::new();
766 stream.extend(input);
767 env.parse(stream).into()
768}