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