1 use crate::error::{Error, Result};
2 use proc_macro::token_stream::IntoIter as TokenIter;
3 use proc_macro::{Spacing, Span, TokenStream, TokenTree};
4 use std::iter;
5 
6 pub struct Expr(TokenStream);
7 
parse(input: &mut TokenIter) -> Result<Expr>8 pub fn parse(input: &mut TokenIter) -> Result<Expr> {
9     #[derive(PartialEq)]
10     enum Lookbehind {
11         JointColon,
12         DoubleColon,
13         Other,
14     }
15 
16     let mut expr = TokenStream::new();
17     let mut lookbehind = Lookbehind::Other;
18     let mut angle_bracket_depth = 0;
19 
20     loop {
21         match input.next() {
22             Some(TokenTree::Punct(punct)) => {
23                 let ch = punct.as_char();
24                 let spacing = punct.spacing();
25                 expr.extend(iter::once(TokenTree::Punct(punct)));
26                 lookbehind = match ch {
27                     ',' if angle_bracket_depth == 0 => return Ok(Expr(expr)),
28                     ':' if lookbehind == Lookbehind::JointColon => Lookbehind::DoubleColon,
29                     ':' if spacing == Spacing::Joint => Lookbehind::JointColon,
30                     '<' if lookbehind == Lookbehind::DoubleColon => {
31                         angle_bracket_depth += 1;
32                         Lookbehind::Other
33                     }
34                     '>' if angle_bracket_depth > 0 => {
35                         angle_bracket_depth -= 1;
36                         Lookbehind::Other
37                     }
38                     _ => Lookbehind::Other,
39                 };
40             }
41             Some(token) => expr.extend(iter::once(token)),
42             None => {
43                 return Err(Error::new(
44                     Span::call_site(),
45                     "unexpected end of macro input",
46                 ))
47             }
48         }
49     }
50 }
51 
52 impl Expr {
into_tokens(self) -> TokenStream53     pub fn into_tokens(self) -> TokenStream {
54         self.0
55     }
56 }
57