1 use crate::iter::{self, Iter, IterImpl};
2 use crate::{Define, Error, Export, ExportArgs, FakeCallSite, Input, Macro, Visibility};
3 use proc_macro::Delimiter::{Brace, Bracket, Parenthesis};
4 use proc_macro::{Delimiter, Ident, Span, TokenStream, TokenTree};
5
parse_input(tokens: Iter) -> Result<Input, Error>6 pub(crate) fn parse_input(tokens: Iter) -> Result<Input, Error> {
7 let attrs = parse_attributes(tokens)?;
8 let vis = parse_visibility(tokens)?;
9 let kw = parse_ident(tokens)?;
10 if kw.to_string() == "use" {
11 parse_export(attrs, vis, tokens).map(Input::Export)
12 } else if kw.to_string() == "fn" {
13 parse_define(attrs, vis, kw.span(), tokens).map(Input::Define)
14 } else {
15 Err(Error::new(
16 kw.span(),
17 "unexpected input to #[proc_macro_hack]",
18 ))
19 }
20 }
21
parse_export(attrs: TokenStream, vis: Visibility, tokens: Iter) -> Result<Export, Error>22 fn parse_export(attrs: TokenStream, vis: Visibility, tokens: Iter) -> Result<Export, Error> {
23 let _ = parse_punct(tokens, ':');
24 let _ = parse_punct(tokens, ':');
25 let from = parse_ident(tokens)?;
26 parse_punct(tokens, ':')?;
27 parse_punct(tokens, ':')?;
28
29 let mut macros = Vec::new();
30 match tokens.peek() {
31 Some(TokenTree::Group(group)) if group.delimiter() == Brace => {
32 let ref mut content = iter::new(group.stream());
33 loop {
34 macros.push(parse_macro(content)?);
35 if content.peek().is_none() {
36 break;
37 }
38 parse_punct(content, ',')?;
39 if content.peek().is_none() {
40 break;
41 }
42 }
43 tokens.next().unwrap();
44 }
45 _ => macros.push(parse_macro(tokens)?),
46 }
47
48 parse_punct(tokens, ';')?;
49 Ok(Export {
50 attrs,
51 vis,
52 from,
53 macros,
54 })
55 }
56
parse_punct(tokens: Iter, ch: char) -> Result<(), Error>57 fn parse_punct(tokens: Iter, ch: char) -> Result<(), Error> {
58 match tokens.peek() {
59 Some(TokenTree::Punct(punct)) if punct.as_char() == ch => {
60 tokens.next().unwrap();
61 Ok(())
62 }
63 tt => Err(Error::new(
64 tt.map_or_else(Span::call_site, TokenTree::span),
65 format!("expected `{}`", ch),
66 )),
67 }
68 }
69
parse_define( attrs: TokenStream, vis: Visibility, fn_token: Span, tokens: Iter, ) -> Result<Define, Error>70 fn parse_define(
71 attrs: TokenStream,
72 vis: Visibility,
73 fn_token: Span,
74 tokens: Iter,
75 ) -> Result<Define, Error> {
76 if vis.is_none() {
77 return Err(Error::new(
78 fn_token,
79 "functions tagged with `#[proc_macro_hack]` must be `pub`",
80 ));
81 }
82 let name = parse_ident(tokens)?;
83 let body = tokens.collect();
84 Ok(Define { attrs, name, body })
85 }
86
parse_macro(tokens: Iter) -> Result<Macro, Error>87 fn parse_macro(tokens: Iter) -> Result<Macro, Error> {
88 let name = parse_ident(tokens)?;
89 let export_as = match tokens.peek() {
90 Some(TokenTree::Ident(ident)) if ident.to_string() == "as" => {
91 tokens.next().unwrap();
92 parse_ident(tokens)?
93 }
94 _ => name.clone(),
95 };
96 Ok(Macro { name, export_as })
97 }
98
parse_ident(tokens: Iter) -> Result<Ident, Error>99 fn parse_ident(tokens: Iter) -> Result<Ident, Error> {
100 match tokens.next() {
101 Some(TokenTree::Ident(ident)) => Ok(ident),
102 tt => Err(Error::new(
103 tt.as_ref().map_or_else(Span::call_site, TokenTree::span),
104 "expected identifier",
105 )),
106 }
107 }
108
parse_keyword(tokens: Iter, kw: &'static str) -> Result<(), Error>109 fn parse_keyword(tokens: Iter, kw: &'static str) -> Result<(), Error> {
110 match &tokens.next() {
111 Some(TokenTree::Ident(ident)) if ident.to_string() == kw => Ok(()),
112 tt => Err(Error::new(
113 tt.as_ref().map_or_else(Span::call_site, TokenTree::span),
114 format!("expected `{}`", kw),
115 )),
116 }
117 }
118
parse_int(tokens: Iter) -> Result<u16, Span>119 fn parse_int(tokens: Iter) -> Result<u16, Span> {
120 match tokens.next() {
121 Some(TokenTree::Literal(lit)) => lit.to_string().parse().map_err(|_| lit.span()),
122 Some(tt) => Err(tt.span()),
123 None => Err(Span::call_site()),
124 }
125 }
126
parse_group(tokens: Iter, delimiter: Delimiter) -> Result<IterImpl, Error>127 fn parse_group(tokens: Iter, delimiter: Delimiter) -> Result<IterImpl, Error> {
128 match &tokens.next() {
129 Some(TokenTree::Group(group)) if group.delimiter() == delimiter => {
130 Ok(iter::new(group.stream()))
131 }
132 tt => Err(Error::new(
133 tt.as_ref().map_or_else(Span::call_site, TokenTree::span),
134 "expected delimiter",
135 )),
136 }
137 }
138
parse_visibility(tokens: Iter) -> Result<Visibility, Error>139 fn parse_visibility(tokens: Iter) -> Result<Visibility, Error> {
140 if let Some(TokenTree::Ident(ident)) = tokens.peek() {
141 if ident.to_string() == "pub" {
142 return Ok(Some(tokens.next().unwrap().span()));
143 }
144 }
145 Ok(None)
146 }
147
parse_attributes(tokens: Iter) -> Result<TokenStream, Error>148 fn parse_attributes(tokens: Iter) -> Result<TokenStream, Error> {
149 let mut attrs = TokenStream::new();
150 while let Some(TokenTree::Punct(punct)) = tokens.peek() {
151 if punct.as_char() != '#' {
152 break;
153 }
154 let span = punct.span();
155 attrs.extend(tokens.next());
156 match tokens.peek() {
157 Some(TokenTree::Group(group)) if group.delimiter() == Bracket => {
158 attrs.extend(tokens.next());
159 }
160 _ => return Err(Error::new(span, "unexpected input")),
161 }
162 }
163 Ok(attrs)
164 }
165
parse_export_args(tokens: Iter) -> Result<ExportArgs, Error>166 pub(crate) fn parse_export_args(tokens: Iter) -> Result<ExportArgs, Error> {
167 let mut args = ExportArgs {
168 support_nested: false,
169 internal_macro_calls: 0,
170 fake_call_site: false,
171 };
172
173 while let Some(tt) = tokens.next() {
174 match &tt {
175 TokenTree::Ident(ident) if ident.to_string() == "support_nested" => {
176 args.support_nested = true;
177 }
178 TokenTree::Ident(ident) if ident.to_string() == "internal_macro_calls" => {
179 parse_punct(tokens, '=')?;
180 let calls = parse_int(tokens).map_err(|span| {
181 Error::new(span, "expected integer value for internal_macro_calls")
182 })?;
183 args.internal_macro_calls = calls;
184 }
185 TokenTree::Ident(ident) if ident.to_string() == "fake_call_site" => {
186 args.fake_call_site = true;
187 }
188 _ => {
189 return Err(Error::new(
190 tt.span(),
191 "expected one of: `support_nested`, `internal_macro_calls`, `fake_call_site`",
192 ))
193 }
194 }
195 if tokens.peek().is_none() {
196 break;
197 }
198 parse_punct(tokens, ',')?;
199 }
200
201 Ok(args)
202 }
203
parse_define_args(tokens: Iter) -> Result<(), Error>204 pub(crate) fn parse_define_args(tokens: Iter) -> Result<(), Error> {
205 if tokens.peek().is_none() {
206 Ok(())
207 } else {
208 Err(Error::new(Span::call_site(), "unexpected input"))
209 }
210 }
211
parse_enum_hack(tokens: Iter) -> Result<TokenStream, Error>212 pub(crate) fn parse_enum_hack(tokens: Iter) -> Result<TokenStream, Error> {
213 parse_keyword(tokens, "enum")?;
214 parse_ident(tokens)?;
215
216 let ref mut braces = parse_group(tokens, Brace)?;
217 parse_ident(braces)?;
218 parse_punct(braces, '=')?;
219
220 let ref mut parens = parse_group(braces, Parenthesis)?;
221 parse_ident(parens)?;
222 parse_punct(parens, '!')?;
223
224 let ref mut inner = parse_group(parens, Brace)?;
225 let token_stream = inner.collect();
226
227 parse_punct(parens, ',')?;
228 let _ = parens.next();
229 parse_punct(braces, '.')?;
230 let _ = braces.next();
231 parse_punct(braces, ',')?;
232
233 Ok(token_stream)
234 }
235
parse_fake_call_site(tokens: Iter) -> Result<FakeCallSite, Error>236 pub(crate) fn parse_fake_call_site(tokens: Iter) -> Result<FakeCallSite, Error> {
237 parse_punct(tokens, '#')?;
238 let ref mut attr = parse_group(tokens, Bracket)?;
239 parse_keyword(attr, "derive")?;
240 let ref mut path = parse_group(attr, Parenthesis)?;
241 Ok(FakeCallSite {
242 derive: parse_ident(path)?,
243 rest: tokens.collect(),
244 })
245 }
246