core_extensions_proc_macros/
parsing_shared.rs

1#[allow(unused_imports)]
2use crate::used_proc_macro::{
3    token_stream::IntoIter,
4    Delimiter, Ident, Group, Punct, Spacing, Span, TokenStream, TokenTree
5};
6
7use core::iter::{Peekable, once};
8
9
10// Parse the arguments that were passed in parenthesized arguments
11pub(crate) fn parse_paren_args(tt: &TokenTree) -> Peekable<IntoIter> {
12    match tt {
13        TokenTree::Group(group) if group.delimiter() == Delimiter::Parenthesis => {
14            let stream = group.stream();
15            let mut iter = stream.clone().into_iter();
16            match (iter.next(), iter.next()) {
17                (Some(TokenTree::Group(group)), None) if group.delimiter() == Delimiter::None => {
18                    group.stream()
19                }
20                _ => stream,
21            }
22        }
23        x => panic!("Expected a parentheses-delimited group, found:\n{}", x),
24    }.into_iter().peekable()
25}
26
27pub(crate) fn parenthesize_ts(ts: TokenStream, span: Span) -> TokenTree {
28    let mut group = Group::new(Delimiter::Parenthesis, ts);
29    group.set_span(span);
30    TokenTree::Group(group)
31}
32
33pub(crate) fn out_parenthesized(ts: TokenStream, span: Span, out: &mut TokenStream) {
34    out.extend(once(parenthesize_ts(ts, span)));
35}
36
37#[allow(dead_code)]
38pub(crate) fn out_ident(value: &str, span: Span, out: &mut TokenStream) {
39    let ident = Ident::new(value, span);
40    out.extend(once(TokenTree::Ident(ident)));
41}
42
43#[allow(dead_code)]
44pub(crate) fn out_colon2(span: Span, out: &mut TokenStream) {
45    out_punct(':', Spacing::Joint, span, out);
46    out_punct(':', Spacing::Alone, span, out);
47}
48
49#[allow(dead_code)]
50pub(crate) fn out_punct(char: char, spacing: Spacing, span: Span, out: &mut TokenStream) {
51    let mut token = TokenTree::Punct(Punct::new(char, spacing));
52    token.set_span(span);
53    out.extend(once(token));
54}
55
56
57pub(crate) fn parse_path_and_args<F>(
58    macro_name: &str,
59    iter: &mut IntoIter,
60    mut args: TokenStream,
61    f: F,
62) -> TokenStream
63where
64    F: FnOnce(&mut TokenStream)
65{
66    let mut out = TokenStream::new();
67    loop {
68        match iter
69            .next()
70            .unwrap_or_else(|| panic!("{} expected more tokens", macro_name) )
71        {
72            TokenTree::Group(group) if group.delimiter() == Delimiter::None => {
73                out.extend(group.stream());
74            }
75            TokenTree::Group(group) => {
76                let mut pre = group.stream();
77                pre.extend(args);
78                args = pre;
79
80                f(&mut args);
81
82                let mut args = TokenTree::Group(Group::new(group.delimiter(), args));
83                args.set_span(group.span());
84                out.extend(once(args));
85
86                return out;
87            }
88            x => {
89                out.extend(once(x));
90            }
91        }
92    }
93}
94
95
96
97
98
99////////////////////////////////////////////////////////////////////////////////
100
101
102pub(crate) struct MacroInvocation {
103    pub(crate) path_bang: TokenStream,
104    pub(crate) delimiter: Delimiter,
105    pub(crate) delim_span: Span,
106    pub(crate) args: TokenStream,
107}
108
109impl MacroInvocation {
110    pub(crate) fn into_token_stream(mut self) -> TokenStream {
111        let mut args = Group::new(self.delimiter, self.args);
112        args.set_span(self.delim_span);
113        self.path_bang.extend(once(TokenTree::Group(args)));
114        self.path_bang
115    }
116
117    pub(crate) fn expand_with_extra_args<F>(mut self, f: F) -> TokenStream 
118    where
119        F: FnOnce(&mut TokenStream)
120    {
121        f(&mut self.args);
122        let mut args = Group::new(self.delimiter, self.args);
123        args.set_span(self.delim_span);
124        self.path_bang.extend(once(TokenTree::Group(args)));
125        self.path_bang
126    }
127}
128
129const PARSE_MACRO_CALL_ERR: &str = "could not parse last tokens as a macro invocation";
130
131#[cfg(feature = "macro_utils")]
132pub(crate) fn parse_macro_invocation<I>(
133    iter: I
134) -> crate::Result<MacroInvocation> 
135where
136    I: IntoIterator<Item = TokenTree>
137{
138    let mut path_bang = TokenStream::new();
139
140    let mut iter = iter.into_iter();
141
142    loop {
143        match iter.next() {
144            Some(TokenTree::Group(group)) if group.delimiter() == Delimiter::None => {
145                path_bang.extend(group.stream());
146            }
147            Some(TokenTree::Group(group)) => {
148                return Ok(MacroInvocation{
149                    path_bang,
150                    delimiter: group.delimiter(),
151                    delim_span: group.span(),
152                    args: group.stream(),
153                });
154            }
155            Some(x) => {
156                path_bang.extend(once(x));
157            }
158            None => {
159                return Err(crate::Error::end(PARSE_MACRO_CALL_ERR));
160            }
161        }
162    }
163}
164
165pub(crate) fn panicking_parse_macro_invocation<I>(
166    iter: I
167) -> MacroInvocation
168where
169    I: IntoIterator<Item = TokenTree>
170{
171    let mut path_bang = TokenStream::new();
172
173    let mut iter = iter.into_iter();
174
175    loop {
176        match iter.next() {
177            Some(TokenTree::Group(group)) if group.delimiter() == Delimiter::None => {
178                path_bang.extend(group.stream());
179            }
180            Some(TokenTree::Group(group)) => {
181                return MacroInvocation{
182                    path_bang,
183                    delimiter: group.delimiter(),
184                    delim_span: group.span(),
185                    args: group.stream(),
186                };
187            }
188            Some(x) => {
189                path_bang.extend(once(x));
190            }
191            None => panic!("{}", PARSE_MACRO_CALL_ERR),
192        }
193    }
194}
195