Branch data Line data Source code
1 : : // This file is part of GCC.
2 : :
3 : : // GCC is free software; you can redistribute it and/or modify it under
4 : : // the terms of the GNU General Public License as published by the Free
5 : : // Software Foundation; either version 3, or (at your option) any later
6 : : // version.
7 : :
8 : : // GCC is distributed in the hope that it will be useful, but WITHOUT ANY
9 : : // WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 : : // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
11 : : // for more details.
12 : :
13 : : // You should have received a copy of the GNU General Public License
14 : : // along with GCC; see the file COPYING3. If not see
15 : : // <http://www.gnu.org/licenses/>.
16 : :
17 : : #include "rust-lex.h"
18 : : #include "rust-token-converter.h"
19 : : #include "bi-map.h"
20 : : #include "line-map.h"
21 : : #include "rust-system.h"
22 : :
23 : : namespace Rust {
24 : :
25 : : static const BiMap<PrimitiveCoreType, std::string> suffixes
26 : : = {{{CORETYPE_F32, "f32"},
27 : : {CORETYPE_F64, "f64"},
28 : : {CORETYPE_U8, "u8"},
29 : : {CORETYPE_U16, "u16"},
30 : : {CORETYPE_U32, "u32"},
31 : : {CORETYPE_U64, "u64"},
32 : : {CORETYPE_U128, "u128"},
33 : : {CORETYPE_I8, "i8"},
34 : : {CORETYPE_I16, "i16"},
35 : : {CORETYPE_I32, "i32"},
36 : : {CORETYPE_I64, "i64"},
37 : : {CORETYPE_I128, "i128"},
38 : : {CORETYPE_ISIZE, "isize"},
39 : : {CORETYPE_USIZE, "usize"}}};
40 : :
41 : : static void
42 : 0 : pop_group (std::vector<ProcMacro::TokenStream> &streams,
43 : : ProcMacro::Delimiter delim)
44 : : {
45 : 0 : auto g = ProcMacro::Group::make_group (streams.back (), delim);
46 : 0 : streams.pop_back ();
47 : 0 : auto tt = ProcMacro::TokenTree::make_tokentree (g);
48 : :
49 : 0 : streams.back ().push (tt);
50 : 0 : }
51 : :
52 : : static ProcMacro::Span
53 : 0 : convert (location_t location)
54 : : {
55 : 0 : return ProcMacro::Span::make_span (location, 0);
56 : : }
57 : :
58 : : static location_t
59 : 0 : convert (ProcMacro::Span span)
60 : : {
61 : 0 : return span.start;
62 : : }
63 : :
64 : : static ProcMacro::Literal
65 : 0 : handle_suffix (const const_TokenPtr &token, ProcMacro::LitKind kind)
66 : : {
67 : 0 : auto str = token->as_string ();
68 : 0 : auto lookup = suffixes.lookup (token->get_type_hint ());
69 : 0 : auto suffix = lookup.value_or ("");
70 : 0 : return ProcMacro::Literal::make_literal (kind, convert (token->get_locus ()),
71 : 0 : str, suffix);
72 : 0 : }
73 : :
74 : : ProcMacro::Literal
75 : 0 : convert_literal (const_TokenPtr lit)
76 : : {
77 : 0 : auto loc = convert (lit->get_locus ());
78 : 0 : switch (lit->get_id ())
79 : : {
80 : 0 : case FLOAT_LITERAL:
81 : 0 : return handle_suffix (lit, ProcMacro::LitKind::make_float ());
82 : 0 : case INT_LITERAL:
83 : 0 : return handle_suffix (lit, ProcMacro::LitKind::make_integer ());
84 : 0 : case CHAR_LITERAL:
85 : 0 : return ProcMacro::Literal::make_literal (ProcMacro::LitKind::make_char (),
86 : 0 : loc, lit->as_string ());
87 : 0 : case STRING_LITERAL:
88 : 0 : return ProcMacro::Literal::make_literal (ProcMacro::LitKind::make_str (),
89 : 0 : loc, lit->as_string ());
90 : 0 : case BYTE_CHAR_LITERAL:
91 : 0 : return ProcMacro::Literal::make_literal (ProcMacro::LitKind::make_byte (),
92 : 0 : loc, lit->as_string ());
93 : 0 : case BYTE_STRING_LITERAL:
94 : 0 : return ProcMacro::Literal::make_literal (
95 : 0 : ProcMacro::LitKind::make_byte_str (), loc, lit->as_string ());
96 : 0 : default:
97 : 0 : rust_unreachable ();
98 : : }
99 : : }
100 : :
101 : : ProcMacro::TokenStream
102 : 0 : convert (const std::vector<const_TokenPtr> &tokens)
103 : : {
104 : 0 : std::vector<ProcMacro::TokenStream> trees;
105 : 0 : trees.push_back (ProcMacro::TokenStream::make_tokenstream ());
106 : 0 : for (auto &token : tokens)
107 : : {
108 : 0 : auto loc = convert (token->get_locus ());
109 : 0 : switch (token->get_id ())
110 : : {
111 : : // Literals
112 : 0 : case FLOAT_LITERAL:
113 : 0 : case INT_LITERAL:
114 : 0 : case CHAR_LITERAL:
115 : 0 : case STRING_LITERAL:
116 : 0 : case BYTE_CHAR_LITERAL:
117 : 0 : case BYTE_STRING_LITERAL:
118 : 0 : trees.back ().push (
119 : 0 : ProcMacro::TokenTree::make_tokentree (convert_literal (token)));
120 : 0 : break;
121 : : // Ident
122 : 0 : case IDENTIFIER:
123 : 0 : case ABSTRACT:
124 : 0 : case AS:
125 : 0 : case ASYNC:
126 : 0 : case AUTO:
127 : 0 : case BECOME:
128 : 0 : case BOX:
129 : 0 : case BREAK:
130 : 0 : case CONST:
131 : 0 : case CONTINUE:
132 : 0 : case CRATE:
133 : 0 : case DO:
134 : 0 : case DYN:
135 : 0 : case ELSE:
136 : 0 : case ENUM_KW:
137 : 0 : case EXTERN_KW:
138 : 0 : case FINAL_KW:
139 : 0 : case FN_KW:
140 : 0 : case FOR:
141 : 0 : case IF:
142 : 0 : case IMPL:
143 : 0 : case IN:
144 : 0 : case LET:
145 : 0 : case LOOP:
146 : 0 : case MACRO:
147 : 0 : case MATCH_KW:
148 : 0 : case MOD:
149 : 0 : case MOVE:
150 : 0 : case MUT:
151 : 0 : case OVERRIDE_KW:
152 : 0 : case PRIV:
153 : 0 : case PUB:
154 : 0 : case REF:
155 : 0 : case RETURN_KW:
156 : 0 : case SELF_ALIAS:
157 : 0 : case SELF:
158 : 0 : case STATIC_KW:
159 : 0 : case STRUCT_KW:
160 : 0 : case SUPER:
161 : 0 : case TRAIT:
162 : 0 : case TRY:
163 : 0 : case TYPE:
164 : 0 : case TYPEOF:
165 : 0 : case UNSAFE:
166 : 0 : case UNSIZED:
167 : 0 : case USE:
168 : 0 : case VIRTUAL:
169 : 0 : case WHERE:
170 : 0 : case WHILE:
171 : 0 : case YIELD:
172 : : // Underscore is not a Punct, considered as an Ident
173 : 0 : case UNDERSCORE:
174 : : // True and false are idents, not literals
175 : : // (https://doc.rust-lang.org/proc_macro/struct.Literal.html)
176 : 0 : case FALSE_LITERAL:
177 : 0 : case TRUE_LITERAL:
178 : 0 : trees.back ().push (ProcMacro::TokenTree::make_tokentree (
179 : 0 : ProcMacro::Ident::make_ident (token->as_string (), loc)));
180 : 0 : break;
181 : : // Joint punct
182 : 0 : case OR:
183 : 0 : case PIPE_EQ:
184 : 0 : case CARET_EQ:
185 : 0 : case RIGHT_SHIFT_EQ:
186 : 0 : case RIGHT_SHIFT:
187 : 0 : case GREATER_OR_EQUAL:
188 : 0 : case MATCH_ARROW:
189 : 0 : case LESS_OR_EQUAL:
190 : 0 : case LEFT_SHIFT_EQ:
191 : 0 : case LEFT_SHIFT:
192 : 0 : case DIV_EQ:
193 : 0 : case ELLIPSIS:
194 : 0 : case DOT_DOT_EQ:
195 : 0 : case DOT_DOT:
196 : 0 : case RETURN_TYPE:
197 : 0 : case MINUS_EQ:
198 : 0 : case PLUS_EQ:
199 : 0 : case ASTERISK_EQ:
200 : 0 : case LOGICAL_AND:
201 : 0 : case AMP_EQ:
202 : 0 : case PERCENT_EQ:
203 : 0 : case SCOPE_RESOLUTION:
204 : 0 : case NOT_EQUAL:
205 : 0 : case EQUAL_EQUAL:
206 : 0 : {
207 : 0 : auto str = token->as_string ();
208 : 0 : auto it = str.cbegin ();
209 : 0 : for (; it != str.cend () - 1; it++)
210 : 0 : trees.back ().push (ProcMacro::TokenTree::make_tokentree (
211 : 0 : ProcMacro::Punct::make_punct (*it, loc, ProcMacro::JOINT)));
212 : 0 : trees.back ().push (ProcMacro::TokenTree::make_tokentree (
213 : 0 : ProcMacro::Punct::make_punct (*it, loc, ProcMacro::ALONE)));
214 : 0 : }
215 : 0 : break;
216 : : // Alone punct tokens
217 : 0 : case EQUAL:
218 : 0 : case RIGHT_ANGLE:
219 : 0 : case LEFT_ANGLE:
220 : 0 : case EXCLAM:
221 : 0 : case TILDE:
222 : 0 : case PLUS:
223 : 0 : case MINUS:
224 : 0 : case ASTERISK:
225 : 0 : case DIV:
226 : 0 : case PERCENT:
227 : 0 : case CARET:
228 : 0 : case AMP:
229 : 0 : case PIPE:
230 : 0 : case PATTERN_BIND:
231 : 0 : case DOT:
232 : 0 : case COMMA:
233 : 0 : case SEMICOLON:
234 : 0 : case COLON:
235 : 0 : case HASH:
236 : 0 : case DOLLAR_SIGN:
237 : 0 : case QUESTION_MARK:
238 : 0 : case SINGLE_QUOTE:
239 : 0 : trees.back ().push (ProcMacro::TokenTree::make_tokentree (
240 : 0 : ProcMacro::Punct::make_punct (token->as_string ()[0], loc,
241 : : ProcMacro::ALONE)));
242 : 0 : break;
243 : 0 : case RIGHT_PAREN:
244 : 0 : pop_group (trees, ProcMacro::PARENTHESIS);
245 : 0 : break;
246 : 0 : case RIGHT_CURLY:
247 : 0 : pop_group (trees, ProcMacro::BRACE);
248 : 0 : break;
249 : 0 : case RIGHT_SQUARE:
250 : 0 : pop_group (trees, ProcMacro::BRACKET);
251 : 0 : break;
252 : 0 : case LEFT_SQUARE:
253 : 0 : case LEFT_CURLY:
254 : 0 : case LEFT_PAREN:
255 : 0 : trees.push_back (ProcMacro::TokenStream::make_tokenstream ());
256 : 0 : break;
257 : 0 : default:
258 : 0 : rust_unreachable ();
259 : : }
260 : : }
261 : 0 : return trees.back ();
262 : 0 : }
263 : :
264 : : static void from_tokenstream (const ProcMacro::TokenStream &ts,
265 : : std::vector<const_TokenPtr> &result);
266 : :
267 : : /**
268 : : * Append the token corresponding to a given Ident to a vector.
269 : : *
270 : : * @param literal Reference to the Ident to convert.
271 : : * @param result Reference to the output vector.
272 : : */
273 : : static void
274 : 0 : from_ident (const ProcMacro::Ident &ident, std::vector<const_TokenPtr> &result)
275 : : {
276 : 0 : std::string value (ident.value.to_string ());
277 : 0 : if (ident.is_raw)
278 : 0 : value = "r#" + value;
279 : :
280 : 0 : Lexer lexer (value, nullptr);
281 : 0 : auto token = lexer.build_token ();
282 : 0 : token->set_locus (convert (ident.span));
283 : 0 : result.push_back (token);
284 : 0 : }
285 : :
286 : : /**
287 : : * Append the token corresponding to a given Literal to a vector.
288 : : *
289 : : * @param literal Reference to the Literal to convert.
290 : : * @param result Reference to the vector tokens should be appended to.
291 : : */
292 : : static void
293 : 0 : from_literal (const ProcMacro::Literal &literal,
294 : : std::vector<const_TokenPtr> &result)
295 : : {
296 : 0 : auto lookup = suffixes.lookup (literal.suffix.to_string ());
297 : 0 : auto loc = convert (literal.span);
298 : 0 : auto suffix = lookup.value_or (CORETYPE_UNKNOWN);
299 : : // FIXME: Add spans instead of empty locations
300 : 0 : switch (literal.kind.tag)
301 : : {
302 : 0 : case ProcMacro::BYTE:
303 : 0 : result.push_back (
304 : 0 : Token::make_byte_char (loc, literal.text.to_string ()[0]));
305 : 0 : break;
306 : 0 : case ProcMacro::CHAR:
307 : 0 : result.push_back (Token::make_char (loc, literal.text.to_string ()[0]));
308 : 0 : break;
309 : 0 : case ProcMacro::INTEGER:
310 : 0 : result.push_back (
311 : 0 : Token::make_int (loc, literal.text.to_string (), suffix));
312 : 0 : break;
313 : 0 : case ProcMacro::FLOAT:
314 : 0 : result.push_back (
315 : 0 : Token::make_float (loc, literal.text.to_string (), suffix));
316 : 0 : break;
317 : 0 : case ProcMacro::STR:
318 : 0 : result.push_back (Token::make_string (loc, literal.text.to_string ()));
319 : 0 : break;
320 : 0 : case ProcMacro::BYTE_STR:
321 : 0 : result.push_back (
322 : 0 : Token::make_byte_string (loc, literal.text.to_string ()));
323 : 0 : break;
324 : : // FIXME: Handle raw string
325 : 0 : case ProcMacro::STR_RAW:
326 : 0 : case ProcMacro::BYTE_STR_RAW:
327 : 0 : default:
328 : 0 : rust_unreachable ();
329 : : }
330 : 0 : }
331 : :
332 : : /**
333 : : * Accumulate through successive calls multiple Punct until one is tagged
334 : : * "Alone", then append the formed token to a given result vector.
335 : : *
336 : : * @param punct Reference to the Punct to convert.
337 : : * @param acc Reference to an accumulator for joined Punct.
338 : : * @param result Reference to the output token vector.
339 : : */
340 : : static void
341 : 0 : from_punct (const ProcMacro::Punct &punct, std::vector<std::uint32_t> &acc,
342 : : std::vector<const_TokenPtr> &result)
343 : : {
344 : 0 : acc.push_back (punct.ch);
345 : 0 : if (ProcMacro::ALONE == punct.spacing) /* Last punct of a chain */
346 : : {
347 : : // TODO: UTF-8 string
348 : 0 : std::string whole (acc.begin (), acc.end ());
349 : 0 : auto lexer = Lexer (whole, nullptr);
350 : 0 : auto token = lexer.build_token ();
351 : 0 : token->set_locus (convert (punct.span));
352 : 0 : result.push_back (token);
353 : 0 : acc.clear ();
354 : 0 : }
355 : 0 : }
356 : :
357 : : /**
358 : : * Iterate over a Group and append all inner tokens to a vector enclosed by its
359 : : * delimiters.
360 : : *
361 : : * @param g Reference to the Group to convert.
362 : : * @param result Reference to the vector tokens should be appended to.
363 : : */
364 : : static void
365 : 0 : from_group (const ProcMacro::Group &g, std::vector<const_TokenPtr> &result)
366 : : {
367 : 0 : auto loc = convert (g.span);
368 : 0 : switch (g.delimiter)
369 : : {
370 : 0 : case ProcMacro::PARENTHESIS:
371 : 0 : result.push_back (Token::make (LEFT_PAREN, loc));
372 : 0 : from_tokenstream (g.stream, result);
373 : 0 : result.push_back (Token::make (RIGHT_PAREN, loc));
374 : 0 : break;
375 : 0 : case ProcMacro::BRACE:
376 : 0 : result.push_back (Token::make (LEFT_CURLY, loc));
377 : 0 : from_tokenstream (g.stream, result);
378 : 0 : result.push_back (Token::make (RIGHT_CURLY, loc));
379 : 0 : break;
380 : 0 : case ProcMacro::BRACKET:
381 : 0 : result.push_back (Token::make (LEFT_SQUARE, loc));
382 : 0 : from_tokenstream (g.stream, result);
383 : 0 : result.push_back (Token::make (RIGHT_SQUARE, loc));
384 : 0 : break;
385 : 0 : case ProcMacro::NONE:
386 : 0 : from_tokenstream (g.stream, result);
387 : 0 : break;
388 : 0 : default:
389 : 0 : rust_unreachable ();
390 : : }
391 : 0 : }
392 : :
393 : : /**
394 : : * Dispatch TokenTree's conversion to its inner type depending on its tag.
395 : : *
396 : : * @param tt Reference to the TokenTree.
397 : : * @param punct_accumulator Reference to an accumulator for joined Punct.
398 : : * @param result Reference to the vector tokens should be appended to.
399 : : */
400 : : static void
401 : 0 : from_tokentree (const ProcMacro::TokenTree &tt,
402 : : std::vector<std::uint32_t> &punct_accumulator,
403 : : std::vector<const_TokenPtr> &result)
404 : : {
405 : 0 : switch (tt.tag)
406 : : {
407 : 0 : case ProcMacro::GROUP:
408 : 0 : from_group (tt.payload.group, result);
409 : 0 : break;
410 : 0 : case ProcMacro::IDENT:
411 : 0 : from_ident (tt.payload.ident, result);
412 : 0 : break;
413 : 0 : case ProcMacro::PUNCT:
414 : 0 : from_punct (tt.payload.punct, punct_accumulator, result);
415 : 0 : break;
416 : 0 : case ProcMacro::LITERAL:
417 : 0 : from_literal (tt.payload.literal, result);
418 : 0 : break;
419 : 0 : default:
420 : 0 : rust_unreachable ();
421 : : }
422 : 0 : }
423 : :
424 : : /**
425 : : * Iterate over a TokenStream and append all inner tokens to a vector.
426 : : *
427 : : * @param ts Reference to the TokenStream.
428 : : * @param result Reference to the vector tokens should be appended to.
429 : : */
430 : : static void
431 : 0 : from_tokenstream (const ProcMacro::TokenStream &ts,
432 : : std::vector<const_TokenPtr> &result)
433 : : {
434 : 0 : std::vector<std::uint32_t> punct_accumulator;
435 : 0 : for (std::uint64_t i = 0; i < ts.size; i++)
436 : : {
437 : 0 : from_tokentree (ts.data[i], punct_accumulator, result);
438 : : }
439 : 0 : }
440 : :
441 : : std::vector<const_TokenPtr>
442 : 0 : convert (const ProcMacro::TokenStream &ts)
443 : : {
444 : 0 : std::vector<const_TokenPtr> result;
445 : 0 : from_tokenstream (ts, result);
446 : 0 : return result;
447 : : }
448 : :
449 : : } // namespace Rust
|