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