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 : :
22 : : #include <string>
23 : :
24 : : namespace Rust {
25 : :
26 : : static const BiMap<PrimitiveCoreType, std::string> suffixes
27 : : = {{{CORETYPE_F32, "f32"},
28 : : {CORETYPE_F64, "f64"},
29 : : {CORETYPE_U8, "u8"},
30 : : {CORETYPE_U16, "u16"},
31 : : {CORETYPE_U32, "u32"},
32 : : {CORETYPE_U64, "u64"},
33 : : {CORETYPE_U128, "u128"},
34 : : {CORETYPE_I8, "i8"},
35 : : {CORETYPE_I16, "i16"},
36 : : {CORETYPE_I32, "i32"},
37 : : {CORETYPE_I64, "i64"},
38 : : {CORETYPE_I128, "i128"},
39 : : {CORETYPE_ISIZE, "isize"},
40 : : {CORETYPE_USIZE, "usize"}}};
41 : :
42 : : static void
43 : 0 : pop_group (std::vector<ProcMacro::TokenStream> &streams,
44 : : ProcMacro::Delimiter delim)
45 : : {
46 : 0 : auto g = ProcMacro::Group::make_group (streams.back (), delim);
47 : 0 : streams.pop_back ();
48 : 0 : auto tt = ProcMacro::TokenTree::make_tokentree (g);
49 : :
50 : 0 : streams.back ().push (tt);
51 : 0 : }
52 : :
53 : : static ProcMacro::Span
54 : 0 : convert (location_t location)
55 : : {
56 : 0 : return ProcMacro::Span::make_span (location, 0);
57 : : }
58 : :
59 : : static location_t
60 : 0 : convert (ProcMacro::Span span)
61 : : {
62 : 0 : return span.start;
63 : : }
64 : :
65 : : static ProcMacro::Literal
66 : 0 : handle_suffix (const const_TokenPtr &token, ProcMacro::LitKind kind)
67 : : {
68 : 0 : auto str = token->as_string ();
69 : 0 : auto lookup = suffixes.lookup (token->get_type_hint ());
70 : 0 : auto suffix = lookup.value_or ("");
71 : 0 : return ProcMacro::Literal::make_literal (kind, convert (token->get_locus ()),
72 : 0 : str, suffix);
73 : 0 : }
74 : :
75 : : ProcMacro::Literal
76 : 0 : convert_literal (const_TokenPtr lit)
77 : : {
78 : 0 : auto loc = convert (lit->get_locus ());
79 : 0 : switch (lit->get_id ())
80 : : {
81 : 0 : case FLOAT_LITERAL:
82 : 0 : return handle_suffix (lit, ProcMacro::LitKind::make_float ());
83 : 0 : case INT_LITERAL:
84 : 0 : return handle_suffix (lit, ProcMacro::LitKind::make_integer ());
85 : 0 : case CHAR_LITERAL:
86 : 0 : return ProcMacro::Literal::make_literal (ProcMacro::LitKind::make_char (),
87 : 0 : loc, lit->as_string ());
88 : 0 : case STRING_LITERAL:
89 : 0 : return ProcMacro::Literal::make_literal (ProcMacro::LitKind::make_str (),
90 : 0 : loc, lit->as_string ());
91 : 0 : case BYTE_CHAR_LITERAL:
92 : 0 : return ProcMacro::Literal::make_literal (ProcMacro::LitKind::make_byte (),
93 : 0 : loc, lit->as_string ());
94 : 0 : case BYTE_STRING_LITERAL:
95 : 0 : return ProcMacro::Literal::make_literal (
96 : 0 : ProcMacro::LitKind::make_byte_str (), loc, lit->as_string ());
97 : 0 : default:
98 : 0 : rust_unreachable ();
99 : : }
100 : : }
101 : :
102 : : ProcMacro::TokenStream
103 : 0 : convert (const std::vector<const_TokenPtr> &tokens)
104 : : {
105 : 0 : std::vector<ProcMacro::TokenStream> trees;
106 : 0 : trees.push_back (ProcMacro::TokenStream::make_tokenstream ());
107 : 0 : for (auto &token : tokens)
108 : : {
109 : 0 : auto loc = convert (token->get_locus ());
110 : 0 : switch (token->get_id ())
111 : : {
112 : : // Literals
113 : 0 : case FLOAT_LITERAL:
114 : 0 : case INT_LITERAL:
115 : 0 : case CHAR_LITERAL:
116 : 0 : case STRING_LITERAL:
117 : 0 : case BYTE_CHAR_LITERAL:
118 : 0 : case BYTE_STRING_LITERAL:
119 : 0 : trees.back ().push (
120 : 0 : ProcMacro::TokenTree::make_tokentree (convert_literal (token)));
121 : 0 : break;
122 : : // Ident
123 : 0 : case IDENTIFIER:
124 : 0 : case ABSTRACT:
125 : 0 : case AS:
126 : 0 : case ASYNC:
127 : 0 : case AUTO:
128 : 0 : case BECOME:
129 : 0 : case BOX:
130 : 0 : case BREAK:
131 : 0 : case CONST:
132 : 0 : case CONTINUE:
133 : 0 : case CRATE:
134 : 0 : case DO:
135 : 0 : case DYN:
136 : 0 : case ELSE:
137 : 0 : case ENUM_KW:
138 : 0 : case EXTERN_KW:
139 : 0 : case FINAL_KW:
140 : 0 : case FN_KW:
141 : 0 : case FOR:
142 : 0 : case IF:
143 : 0 : case IMPL:
144 : 0 : case IN:
145 : 0 : case LET:
146 : 0 : case LOOP:
147 : 0 : case MACRO:
148 : 0 : case MATCH_KW:
149 : 0 : case MOD:
150 : 0 : case MOVE:
151 : 0 : case MUT:
152 : 0 : case OVERRIDE_KW:
153 : 0 : case PRIV:
154 : 0 : case PUB:
155 : 0 : case REF:
156 : 0 : case RETURN_KW:
157 : 0 : case SELF_ALIAS:
158 : 0 : case SELF:
159 : 0 : case STATIC_KW:
160 : 0 : case STRUCT_KW:
161 : 0 : case SUPER:
162 : 0 : case TRAIT:
163 : 0 : case TRY:
164 : 0 : case TYPE:
165 : 0 : case TYPEOF:
166 : 0 : case UNSAFE:
167 : 0 : case UNSIZED:
168 : 0 : case USE:
169 : 0 : case VIRTUAL:
170 : 0 : case WHERE:
171 : 0 : case WHILE:
172 : 0 : case YIELD:
173 : : // Underscore is not a Punct, considered as an Ident
174 : 0 : case UNDERSCORE:
175 : : // True and false are idents, not literals
176 : : // (https://doc.rust-lang.org/proc_macro/struct.Literal.html)
177 : 0 : case FALSE_LITERAL:
178 : 0 : case TRUE_LITERAL:
179 : 0 : trees.back ().push (ProcMacro::TokenTree::make_tokentree (
180 : 0 : ProcMacro::Ident::make_ident (token->as_string (), loc)));
181 : 0 : break;
182 : : // Joint punct
183 : 0 : case OR:
184 : 0 : case PIPE_EQ:
185 : 0 : case CARET_EQ:
186 : 0 : case RIGHT_SHIFT_EQ:
187 : 0 : case RIGHT_SHIFT:
188 : 0 : case GREATER_OR_EQUAL:
189 : 0 : case MATCH_ARROW:
190 : 0 : case LESS_OR_EQUAL:
191 : 0 : case LEFT_SHIFT_EQ:
192 : 0 : case LEFT_SHIFT:
193 : 0 : case DIV_EQ:
194 : 0 : case ELLIPSIS:
195 : 0 : case DOT_DOT_EQ:
196 : 0 : case DOT_DOT:
197 : 0 : case RETURN_TYPE:
198 : 0 : case MINUS_EQ:
199 : 0 : case PLUS_EQ:
200 : 0 : case ASTERISK_EQ:
201 : 0 : case LOGICAL_AND:
202 : 0 : case AMP_EQ:
203 : 0 : case PERCENT_EQ:
204 : 0 : case SCOPE_RESOLUTION:
205 : 0 : case NOT_EQUAL:
206 : 0 : case EQUAL_EQUAL: {
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
265 : : from_tokenstream (const ProcMacro::TokenStream &ts,
266 : : std::vector<const_TokenPtr> &result);
267 : :
268 : : /**
269 : : * Append the token corresponding to a given Ident to a vector.
270 : : *
271 : : * @param literal Reference to the Ident to convert.
272 : : * @param result Reference to the output vector.
273 : : */
274 : : static void
275 : 0 : from_ident (const ProcMacro::Ident &ident, std::vector<const_TokenPtr> &result)
276 : : {
277 : 0 : std::string value (ident.value.to_string ());
278 : 0 : if (ident.is_raw)
279 : 0 : value = "r#" + value;
280 : :
281 : 0 : Lexer lexer (value, nullptr);
282 : 0 : auto token = lexer.build_token ();
283 : 0 : token->set_locus (convert (ident.span));
284 : 0 : result.push_back (token);
285 : 0 : }
286 : :
287 : : /**
288 : : * Append the token corresponding to a given Literal to a vector.
289 : : *
290 : : * @param literal Reference to the Literal to convert.
291 : : * @param result Reference to the vector tokens should be appended to.
292 : : */
293 : : static void
294 : 0 : from_literal (const ProcMacro::Literal &literal,
295 : : std::vector<const_TokenPtr> &result)
296 : : {
297 : 0 : auto lookup = suffixes.lookup (literal.suffix.to_string ());
298 : 0 : auto loc = convert (literal.span);
299 : 0 : auto suffix = lookup.value_or (CORETYPE_UNKNOWN);
300 : : // FIXME: Add spans instead of empty locations
301 : 0 : switch (literal.kind.tag)
302 : : {
303 : 0 : case ProcMacro::BYTE:
304 : 0 : result.push_back (
305 : 0 : Token::make_byte_char (loc, literal.text.to_string ()[0]));
306 : 0 : break;
307 : 0 : case ProcMacro::CHAR:
308 : 0 : result.push_back (Token::make_char (loc, literal.text.to_string ()[0]));
309 : 0 : break;
310 : 0 : case ProcMacro::INTEGER:
311 : 0 : result.push_back (
312 : 0 : Token::make_int (loc, literal.text.to_string (), suffix));
313 : 0 : break;
314 : 0 : case ProcMacro::FLOAT:
315 : 0 : result.push_back (
316 : 0 : Token::make_float (loc, literal.text.to_string (), suffix));
317 : 0 : break;
318 : 0 : case ProcMacro::STR:
319 : 0 : result.push_back (Token::make_string (loc, literal.text.to_string ()));
320 : 0 : break;
321 : 0 : case ProcMacro::BYTE_STR:
322 : 0 : result.push_back (
323 : 0 : Token::make_byte_string (loc, literal.text.to_string ()));
324 : 0 : break;
325 : : // FIXME: Handle raw string
326 : 0 : case ProcMacro::STR_RAW:
327 : 0 : case ProcMacro::BYTE_STR_RAW:
328 : 0 : default:
329 : 0 : rust_unreachable ();
330 : : }
331 : 0 : }
332 : :
333 : : /**
334 : : * Accumulate through successive calls multiple Punct until one is tagged
335 : : * "Alone", then append the formed token to a given result vector.
336 : : *
337 : : * @param punct Reference to the Punct to convert.
338 : : * @param acc Reference to an accumulator for joined Punct.
339 : : * @param result Reference to the output token vector.
340 : : */
341 : : static void
342 : 0 : from_punct (const ProcMacro::Punct &punct, std::vector<std::uint32_t> &acc,
343 : : std::vector<const_TokenPtr> &result)
344 : : {
345 : 0 : acc.push_back (punct.ch);
346 : 0 : if (ProcMacro::ALONE == punct.spacing) /* Last punct of a chain */
347 : : {
348 : : // TODO: UTF-8 string
349 : 0 : std::string whole (acc.begin (), acc.end ());
350 : 0 : auto lexer = Lexer (whole, nullptr);
351 : 0 : auto token = lexer.build_token ();
352 : 0 : token->set_locus (convert (punct.span));
353 : 0 : result.push_back (token);
354 : 0 : acc.clear ();
355 : 0 : }
356 : 0 : }
357 : :
358 : : /**
359 : : * Iterate over a Group and append all inner tokens to a vector enclosed by its
360 : : * delimiters.
361 : : *
362 : : * @param g Reference to the Group to convert.
363 : : * @param result Reference to the vector tokens should be appended to.
364 : : */
365 : : static void
366 : 0 : from_group (const ProcMacro::Group &g, std::vector<const_TokenPtr> &result)
367 : : {
368 : 0 : auto loc = convert (g.span);
369 : 0 : switch (g.delimiter)
370 : : {
371 : 0 : case ProcMacro::PARENTHESIS:
372 : 0 : result.push_back (Token::make (LEFT_PAREN, loc));
373 : 0 : from_tokenstream (g.stream, result);
374 : 0 : result.push_back (Token::make (RIGHT_PAREN, loc));
375 : 0 : break;
376 : 0 : case ProcMacro::BRACE:
377 : 0 : result.push_back (Token::make (LEFT_CURLY, loc));
378 : 0 : from_tokenstream (g.stream, result);
379 : 0 : result.push_back (Token::make (RIGHT_CURLY, loc));
380 : 0 : break;
381 : 0 : case ProcMacro::BRACKET:
382 : 0 : result.push_back (Token::make (LEFT_SQUARE, loc));
383 : 0 : from_tokenstream (g.stream, result);
384 : 0 : result.push_back (Token::make (RIGHT_SQUARE, loc));
385 : 0 : break;
386 : 0 : case ProcMacro::NONE:
387 : 0 : from_tokenstream (g.stream, result);
388 : 0 : break;
389 : 0 : default:
390 : 0 : rust_unreachable ();
391 : : }
392 : 0 : }
393 : :
394 : : /**
395 : : * Dispatch TokenTree's conversion to its inner type depending on its tag.
396 : : *
397 : : * @param tt Reference to the TokenTree.
398 : : * @param punct_accumulator Reference to an accumulator for joined Punct.
399 : : * @param result Reference to the vector tokens should be appended to.
400 : : */
401 : : static void
402 : 0 : from_tokentree (const ProcMacro::TokenTree &tt,
403 : : std::vector<std::uint32_t> &punct_accumulator,
404 : : std::vector<const_TokenPtr> &result)
405 : : {
406 : 0 : switch (tt.tag)
407 : : {
408 : 0 : case ProcMacro::GROUP:
409 : 0 : from_group (tt.payload.group, result);
410 : 0 : break;
411 : 0 : case ProcMacro::IDENT:
412 : 0 : from_ident (tt.payload.ident, result);
413 : 0 : break;
414 : 0 : case ProcMacro::PUNCT:
415 : 0 : from_punct (tt.payload.punct, punct_accumulator, result);
416 : 0 : break;
417 : 0 : case ProcMacro::LITERAL:
418 : 0 : from_literal (tt.payload.literal, result);
419 : 0 : break;
420 : 0 : default:
421 : 0 : rust_unreachable ();
422 : : }
423 : 0 : }
424 : :
425 : : /**
426 : : * Iterate over a TokenStream and append all inner tokens to a vector.
427 : : *
428 : : * @param ts Reference to the TokenStream.
429 : : * @param result Reference to the vector tokens should be appended to.
430 : : */
431 : : static void
432 : 0 : from_tokenstream (const ProcMacro::TokenStream &ts,
433 : : std::vector<const_TokenPtr> &result)
434 : : {
435 : 0 : std::vector<std::uint32_t> punct_accumulator;
436 : 0 : for (std::uint64_t i = 0; i < ts.size; i++)
437 : : {
438 : 0 : from_tokentree (ts.data[i], punct_accumulator, result);
439 : : }
440 : 0 : }
441 : :
442 : : std::vector<const_TokenPtr>
443 : 0 : convert (const ProcMacro::TokenStream &ts)
444 : : {
445 : 0 : std::vector<const_TokenPtr> result;
446 : 0 : from_tokenstream (ts, result);
447 : 0 : return result;
448 : : }
449 : :
450 : : } // namespace Rust
|