const_format_proc_macros/
shared_arg_parsing.rs

1//! Types for parsing arguments, shared by many of the macros
2
3use crate::{
4    parse_utils::{MyParse, ParseBuffer, ParseStream},
5    spanned::Spans,
6};
7
8use proc_macro2::TokenStream as TokenStream2;
9
10use quote::ToTokens;
11
12////////////////////////////////////////////////
13
14// An expression inside `(...)`
15pub(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
22impl 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)
29pub(crate) struct ExprArgs {
30    pub(crate) args: Vec<ExprArg>,
31}
32
33////////////////////////////////////////////////
34
35impl MyParse for ExprArg {
36    fn parse(input: ParseStream<'_>) -> Result<Self, crate::Error> {
37        let paren = input.parse_paren()?;
38
39        let mut content = ParseBuffer::new(paren.contents);
40
41        content.parse_unwrap_tt(|content| {
42            let (expr, span) = content.parse_token_stream_and_span();
43
44            Ok(Self { span, expr })
45        })
46    }
47}
48
49////////////////////////////////////////////////
50
51impl MyParse for ExprArgs {
52    fn parse(input: ParseStream<'_>) -> Result<Self, crate::Error> {
53        let mut args = 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}