1 | //! Types for parsing arguments, shared by many of the macros |
2 | |
3 | use crate::{ |
4 | parse_utils::{MyParse, ParseBuffer, ParseStream}, |
5 | spanned::Spans, |
6 | }; |
7 | |
8 | use proc_macro2::TokenStream as TokenStream2; |
9 | |
10 | use quote::ToTokens; |
11 | |
12 | //////////////////////////////////////////////// |
13 | |
14 | // An expression inside `(...)` |
15 | pub(crate) struct ExprArg { |
16 | pub(crate) span: Spans, |
17 | /// Using a TokenStream2 because it is validated to be a valid expression in |
18 | /// the macro_rules! macros that call these proc macros. |
19 | pub(crate) expr: TokenStream2, |
20 | } |
21 | |
22 | impl ToTokens for ExprArg { |
23 | fn to_tokens(&self, ts: &mut TokenStream2) { |
24 | self.expr.to_tokens(ts); |
25 | } |
26 | } |
27 | |
28 | /// A sequence of comma separated expressions wrapped in parentheses (with a trailing comma) |
29 | pub(crate) struct ExprArgs { |
30 | pub(crate) args: Vec<ExprArg>, |
31 | } |
32 | |
33 | //////////////////////////////////////////////// |
34 | |
35 | impl MyParse for ExprArg { |
36 | fn parse(input: ParseStream<'_>) -> Result<Self, crate::Error> { |
37 | let paren: Parentheses = input.parse_paren()?; |
38 | |
39 | let mut content: ParseBuffer = ParseBuffer::new(ts:paren.contents); |
40 | |
41 | content.parse_unwrap_tt(|content: &mut ParseBuffer| { |
42 | let (expr: TokenStream, span: Spans) = content.parse_token_stream_and_span(); |
43 | |
44 | Ok(Self { span, expr }) |
45 | }) |
46 | } |
47 | } |
48 | |
49 | //////////////////////////////////////////////// |
50 | |
51 | impl MyParse for ExprArgs { |
52 | fn parse(input: ParseStream<'_>) -> Result<Self, crate::Error> { |
53 | let mut args: Vec = Vec::new(); |
54 | |
55 | while !input.is_empty() { |
56 | args.push(ExprArg::parse(input)?); |
57 | |
58 | if !input.is_empty() { |
59 | input.parse_punct(',' )?; |
60 | } |
61 | } |
62 | |
63 | Ok(Self { args }) |
64 | } |
65 | } |
66 | |