Line data Source code
1 : // Copyright (C) 2025-2026 Free Software Foundation, Inc.
2 :
3 : // This file is part of GCC.
4 :
5 : // GCC is free software; you can redistribute it and/or modify it under
6 : // the terms of the GNU General Public License as published by the Free
7 : // Software Foundation; either version 3, or (at your option) any later
8 : // version.
9 :
10 : // GCC is distributed in the hope that it will be useful, but WITHOUT ANY
11 : // WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 : // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 : // for more details.
14 :
15 : // You should have received a copy of the GNU General Public License
16 : // along with GCC; see the file COPYING3. If not see
17 : // <http://www.gnu.org/licenses/>.
18 :
19 : /* DO NOT INCLUDE ANYWHERE - this is automatically included
20 : * by rust-parse-impl.h
21 : * This is also the reason why there are no include guards. */
22 :
23 : #include "rust-parse.h"
24 :
25 : namespace Rust {
26 :
27 : // Parses a SimplePath AST node, if it exists. Does nothing otherwise.
28 : template <typename ManagedTokenSource>
29 : tl::expected<AST::SimplePath, Parse::Error::Node>
30 22644 : Parser<ManagedTokenSource>::parse_simple_path ()
31 : {
32 22644 : bool has_opening_scope_resolution = false;
33 22644 : location_t locus = UNKNOWN_LOCATION;
34 :
35 : using Parse::Utils::is_simple_path_segment;
36 :
37 : // don't parse anything if not a path upfront
38 45288 : if (!is_simple_path_segment (lexer.peek_token ()->get_id ())
39 22918 : && !is_simple_path_segment (lexer.peek_token (1)->get_id ()))
40 220 : return tl::unexpected<Parse::Error::Node> (Parse::Error::Node::MALFORMED);
41 :
42 : /* Checks for opening scope resolution (i.e. global scope fully-qualified
43 : * path) */
44 44848 : if (lexer.peek_token ()->get_id () == SCOPE_RESOLUTION)
45 : {
46 0 : has_opening_scope_resolution = true;
47 :
48 0 : locus = lexer.peek_token ()->get_locus ();
49 :
50 0 : lexer.skip_token ();
51 : }
52 :
53 : // Parse single required simple path segment
54 22424 : auto segment = parse_simple_path_segment ();
55 :
56 22424 : if (!segment)
57 54 : return tl::unexpected<Parse::Error::Node> (Parse::Error::Node::CHILD_ERROR);
58 :
59 : // get location if not gotten already
60 22370 : if (locus == UNKNOWN_LOCATION)
61 22370 : locus = segment->get_locus ();
62 :
63 22370 : std::vector<AST::SimplePathSegment> segments;
64 22370 : segments.push_back (std::move (segment.value ()));
65 :
66 : // Parse all other simple path segments
67 46934 : while (lexer.peek_token ()->get_id () == SCOPE_RESOLUTION)
68 : {
69 1180 : auto new_segment = parse_simple_path_segment (1);
70 :
71 : using Error = Parse::Error::SimplePathSegment::Kind;
72 : // Return path as currently constructed if segment in error state.
73 1180 : if (!new_segment)
74 : {
75 166 : if (new_segment.error ().kind == Error::INVALID_SIMPLE_PATH_TOKEN)
76 : break; /* Could be end of path */
77 : else /* Any other error is an hard error */
78 : return tl::unexpected<Parse::Error::Node> (
79 0 : Parse::Error::Node::CHILD_ERROR);
80 : }
81 :
82 1014 : segments.push_back (std::move (new_segment.value ()));
83 : }
84 :
85 22370 : return AST::SimplePath (std::move (segments), has_opening_scope_resolution,
86 22370 : locus);
87 : /* TODO: now that is_simple_path_segment exists, could probably start
88 : * actually making errors upon parse failure of segments and whatever */
89 44794 : }
90 :
91 : /* Parses a single SimplePathSegment (does not handle the scope resolution
92 : * operators)
93 : * Starts parsing at an offset of base_peek */
94 : template <typename ManagedTokenSource>
95 : tl::expected<AST::SimplePathSegment, Parse::Error::SimplePathSegment>
96 23604 : Parser<ManagedTokenSource>::parse_simple_path_segment (int base_peek)
97 : {
98 : using namespace Values;
99 23604 : const_TokenPtr t = lexer.peek_token (base_peek);
100 23604 : switch (t->get_id ())
101 : {
102 23001 : case IDENTIFIER:
103 23001 : lexer.skip_token (base_peek);
104 :
105 46002 : return AST::SimplePathSegment (t->get_str (), t->get_locus ());
106 301 : case SUPER:
107 301 : lexer.skip_token (base_peek);
108 :
109 301 : return AST::SimplePathSegment (Keywords::SUPER, t->get_locus ());
110 60 : case SELF:
111 60 : lexer.skip_token (base_peek);
112 :
113 60 : return AST::SimplePathSegment (Keywords::SELF, t->get_locus ());
114 22 : case CRATE:
115 22 : lexer.skip_token (base_peek);
116 :
117 22 : return AST::SimplePathSegment (Keywords::CRATE, t->get_locus ());
118 0 : case DOLLAR_SIGN:
119 0 : if (lexer.peek_token (base_peek + 1)->get_id () == CRATE)
120 : {
121 0 : lexer.skip_token (base_peek + 1);
122 :
123 0 : return AST::SimplePathSegment ("$crate", t->get_locus ());
124 : }
125 : gcc_fallthrough ();
126 : default:
127 : // do nothing but inactivates warning from gcc when compiling
128 : /* could put the rust_error_at thing here but fallthrough (from failing
129 : * $crate condition) isn't completely obvious if it is. */
130 :
131 : return Parse::Error::SimplePathSegment::make_invalid_token_or_path_end ();
132 : }
133 : rust_unreachable ();
134 23604 : }
135 :
136 : // Parses a PathIdentSegment - an identifier segment of a non-SimplePath path.
137 : template <typename ManagedTokenSource>
138 : tl::expected<AST::PathIdentSegment, Parse::Error::PathIdentSegment>
139 139238 : Parser<ManagedTokenSource>::parse_path_ident_segment ()
140 : {
141 139238 : const_TokenPtr t = lexer.peek_token ();
142 139238 : switch (t->get_id ())
143 : {
144 123017 : case IDENTIFIER:
145 123017 : lexer.skip_token ();
146 :
147 246034 : return AST::PathIdentSegment (t->get_str (), t->get_locus ());
148 8 : case SUPER:
149 8 : lexer.skip_token ();
150 :
151 8 : return AST::PathIdentSegment (Values::Keywords::SUPER, t->get_locus ());
152 6904 : case SELF:
153 6904 : lexer.skip_token ();
154 :
155 6904 : return AST::PathIdentSegment (Values::Keywords::SELF, t->get_locus ());
156 8431 : case SELF_ALIAS:
157 8431 : lexer.skip_token ();
158 :
159 16862 : return AST::PathIdentSegment (Values::Keywords::SELF_ALIAS,
160 8431 : t->get_locus ());
161 667 : case CRATE:
162 667 : lexer.skip_token ();
163 :
164 667 : return AST::PathIdentSegment (Values::Keywords::CRATE, t->get_locus ());
165 4 : case DOLLAR_SIGN:
166 8 : if (lexer.peek_token (1)->get_id () == CRATE)
167 : {
168 0 : lexer.skip_token (1);
169 :
170 0 : return AST::PathIdentSegment ("$crate", t->get_locus ());
171 : }
172 : gcc_fallthrough ();
173 : default:
174 : /* do nothing but inactivates warning from gcc when compiling
175 : * could put the error_at thing here but fallthrough (from failing $crate
176 : * condition) isn't completely obvious if it is. */
177 :
178 : // test prevent error
179 : return Parse::Error::PathIdentSegment::make_invalid_token ();
180 : }
181 : rust_unreachable ();
182 139238 : }
183 :
184 : // Parses a type path.
185 : template <typename ManagedTokenSource>
186 : AST::TypePath
187 53355 : Parser<ManagedTokenSource>::parse_type_path ()
188 : {
189 53355 : bool has_opening_scope_resolution = false;
190 53355 : location_t locus = lexer.peek_token ()->get_locus ();
191 106710 : if (lexer.peek_token ()->get_id () == SCOPE_RESOLUTION)
192 : {
193 28 : has_opening_scope_resolution = true;
194 28 : lexer.skip_token ();
195 : }
196 :
197 : // create segment vector
198 53355 : std::vector<std::unique_ptr<AST::TypePathSegment>> segments;
199 :
200 : // parse required initial segment
201 53355 : std::unique_ptr<AST::TypePathSegment> initial_segment
202 : = parse_type_path_segment ();
203 53355 : if (initial_segment == nullptr)
204 : {
205 : // skip after somewhere?
206 : // don't necessarily throw error but yeah
207 203 : return AST::TypePath::create_error ();
208 : }
209 53152 : segments.push_back (std::move (initial_segment));
210 :
211 : // parse optional segments (as long as scope resolution operator exists)
212 53152 : const_TokenPtr t = lexer.peek_token ();
213 54346 : while (t->get_id () == SCOPE_RESOLUTION)
214 : {
215 : // skip scope resolution operator
216 1194 : lexer.skip_token ();
217 :
218 : // parse the actual segment - it is an error if it doesn't exist now
219 1194 : std::unique_ptr<AST::TypePathSegment> segment
220 : = parse_type_path_segment ();
221 1194 : if (segment == nullptr)
222 : {
223 : // skip after somewhere?
224 0 : Error error (t->get_locus (), "could not parse type path segment");
225 0 : add_error (std::move (error));
226 :
227 0 : return AST::TypePath::create_error ();
228 0 : }
229 :
230 1194 : segments.push_back (std::move (segment));
231 :
232 1194 : t = lexer.peek_token ();
233 : }
234 :
235 53152 : segments.shrink_to_fit ();
236 :
237 106304 : return AST::TypePath (std::move (segments), locus,
238 53152 : has_opening_scope_resolution);
239 53355 : }
240 :
241 : /* Parses a single type path segment (not including opening scope resolution,
242 : * but includes any internal ones). Includes generic args or type path
243 : * functions too. */
244 : template <typename ManagedTokenSource>
245 : std::unique_ptr<AST::TypePathSegment>
246 54880 : Parser<ManagedTokenSource>::parse_type_path_segment ()
247 : {
248 54880 : location_t locus = lexer.peek_token ()->get_locus ();
249 : // parse ident segment part
250 54880 : auto ident_segment_res = parse_path_ident_segment ();
251 54880 : if (!ident_segment_res)
252 : {
253 : // not necessarily an error
254 203 : return nullptr;
255 : }
256 54677 : auto ident_segment = ident_segment_res.value ();
257 :
258 : /* lookahead to determine if variants exist - only consume scope resolution
259 : * then */
260 54677 : bool has_separating_scope_resolution = false;
261 54677 : const_TokenPtr next = lexer.peek_token (1);
262 109354 : if (lexer.peek_token ()->get_id () == SCOPE_RESOLUTION
263 54677 : && (next->get_id () == LEFT_ANGLE || next->get_id () == LEFT_PAREN))
264 : {
265 0 : has_separating_scope_resolution = true;
266 0 : lexer.skip_token ();
267 : }
268 :
269 : // branch into variants on next token
270 54677 : const_TokenPtr t = lexer.peek_token ();
271 54677 : switch (t->get_id ())
272 : {
273 2737 : case LEFT_SHIFT:
274 : case LEFT_ANGLE:
275 : {
276 : // parse generic args
277 2737 : AST::GenericArgs generic_args = parse_path_generic_args ();
278 :
279 2737 : return std::unique_ptr<AST::TypePathSegmentGeneric> (
280 5474 : new AST::TypePathSegmentGeneric (std::move (ident_segment),
281 : has_separating_scope_resolution,
282 2737 : std::move (generic_args), locus));
283 2737 : }
284 30 : case LEFT_PAREN:
285 : {
286 : // parse type path function
287 30 : AST::TypePathFunction type_path_function
288 : = parse_type_path_function (locus);
289 :
290 30 : if (type_path_function.is_error ())
291 : {
292 : // skip after somewhere?
293 0 : return nullptr;
294 : }
295 :
296 30 : return std::unique_ptr<AST::TypePathSegmentFunction> (
297 90 : new AST::TypePathSegmentFunction (std::move (ident_segment),
298 : has_separating_scope_resolution,
299 : std::move (type_path_function),
300 30 : locus));
301 30 : }
302 51910 : default:
303 : // neither of them
304 : return std::unique_ptr<AST::TypePathSegment> (
305 51910 : new AST::TypePathSegment (std::move (ident_segment),
306 51910 : has_separating_scope_resolution, locus));
307 : }
308 : rust_unreachable ();
309 109354 : }
310 :
311 : // Parses a function call representation inside a type path.
312 : template <typename ManagedTokenSource>
313 : AST::TypePathFunction
314 30 : Parser<ManagedTokenSource>::parse_type_path_function (location_t id_location)
315 : {
316 30 : if (!skip_token (LEFT_PAREN))
317 : {
318 : // skip somewhere?
319 : return AST::TypePathFunction::create_error ();
320 : }
321 :
322 : // parse function inputs
323 30 : std::vector<std::unique_ptr<AST::Type>> inputs;
324 :
325 94 : while (lexer.peek_token ()->get_id () != RIGHT_PAREN)
326 : {
327 32 : std::unique_ptr<AST::Type> type = parse_type ();
328 32 : if (type == nullptr)
329 : {
330 : /* this is an error as there should've been a ')' there if there
331 : * wasn't a type */
332 0 : Error error (
333 0 : lexer.peek_token ()->get_locus (),
334 : "failed to parse type in parameters of type path function");
335 0 : add_error (std::move (error));
336 :
337 : // skip somewhere?
338 0 : return AST::TypePathFunction::create_error ();
339 0 : }
340 :
341 32 : inputs.push_back (std::move (type));
342 :
343 : // skip commas, including trailing commas
344 64 : if (lexer.peek_token ()->get_id () != COMMA)
345 : break;
346 :
347 2 : lexer.skip_token ();
348 : }
349 :
350 30 : if (!skip_token (RIGHT_PAREN))
351 : {
352 : // skip somewhere?
353 : return AST::TypePathFunction::create_error ();
354 : }
355 :
356 : // parse optional return type
357 30 : std::unique_ptr<AST::Type> return_type = parse_function_return_type ();
358 :
359 30 : inputs.shrink_to_fit ();
360 30 : return AST::TypePathFunction (std::move (inputs), id_location,
361 30 : std::move (return_type));
362 30 : }
363 :
364 : // Parses a path inside an expression that allows generic arguments.
365 : template <typename ManagedTokenSource>
366 : AST::PathInExpression
367 73330 : Parser<ManagedTokenSource>::parse_path_in_expression ()
368 : {
369 73330 : location_t locus = UNKNOWN_LOCATION;
370 73330 : bool has_opening_scope_resolution = false;
371 146660 : if (lexer.peek_token ()->get_id () == SCOPE_RESOLUTION)
372 : {
373 9 : has_opening_scope_resolution = true;
374 :
375 9 : locus = lexer.peek_token ()->get_locus ();
376 :
377 9 : lexer.skip_token ();
378 : }
379 :
380 : // create segment vector
381 73330 : std::vector<AST::PathExprSegment> segments;
382 :
383 73330 : if (locus == UNKNOWN_LOCATION)
384 : {
385 146642 : locus = lexer.peek_token ()->get_locus ();
386 : }
387 :
388 : // parse required initial segment
389 73330 : AST::PathExprSegment initial_segment = parse_path_expr_segment ();
390 73330 : if (initial_segment.is_error ())
391 : {
392 : // skip after somewhere?
393 : // don't necessarily throw error but yeah
394 4 : return AST::PathInExpression::create_error ();
395 : }
396 73326 : segments.push_back (std::move (initial_segment));
397 :
398 : // parse optional segments (as long as scope resolution operator exists)
399 73326 : const_TokenPtr t = lexer.peek_token ();
400 81237 : while (t->get_id () == SCOPE_RESOLUTION)
401 : {
402 : // skip scope resolution operator
403 7911 : lexer.skip_token ();
404 :
405 : // parse the actual segment - it is an error if it doesn't exist now
406 7911 : AST::PathExprSegment segment = parse_path_expr_segment ();
407 7911 : if (segment.is_error ())
408 : {
409 : // skip after somewhere?
410 4 : Error error (t->get_locus (),
411 : "could not parse path expression segment");
412 4 : add_error (std::move (error));
413 :
414 4 : return AST::PathInExpression::create_error ();
415 4 : }
416 :
417 7907 : segments.push_back (std::move (segment));
418 :
419 7907 : t = lexer.peek_token ();
420 : }
421 :
422 73322 : segments.shrink_to_fit ();
423 :
424 73322 : return AST::PathInExpression (std::move (segments), {}, locus,
425 73322 : has_opening_scope_resolution);
426 146656 : }
427 :
428 : /* Parses a single path in expression path segment (including generic
429 : * arguments). */
430 : template <typename ManagedTokenSource>
431 : AST::PathExprSegment
432 84358 : Parser<ManagedTokenSource>::parse_path_expr_segment ()
433 : {
434 84358 : location_t locus = lexer.peek_token ()->get_locus ();
435 : // parse ident segment
436 84358 : auto ident_result = parse_path_ident_segment ();
437 84358 : if (!ident_result)
438 : {
439 : // not necessarily an error?
440 8 : return AST::PathExprSegment::create_error ();
441 : }
442 84350 : auto ident = ident_result.value ();
443 :
444 : // parse generic args (and turbofish), if they exist
445 : /* use lookahead to determine if they actually exist (don't want to
446 : * accidently parse over next ident segment) */
447 168700 : if (lexer.peek_token ()->get_id () == SCOPE_RESOLUTION
448 114415 : && (lexer.peek_token (1)->get_id () == LEFT_ANGLE
449 31770 : || lexer.peek_token (1)->get_id () == LEFT_SHIFT))
450 : {
451 : // skip scope resolution
452 906 : lexer.skip_token ();
453 :
454 : // Let parse_path_generic_args split "<<" tokens
455 906 : AST::GenericArgs generic_args = parse_path_generic_args ();
456 :
457 1812 : return AST::PathExprSegment (std::move (ident), locus,
458 906 : std::move (generic_args));
459 906 : }
460 :
461 : // return a generic parameter-less expr segment if not found
462 83444 : return AST::PathExprSegment (std::move (ident), locus);
463 84350 : }
464 :
465 : /* Parses a fully qualified path in expression (i.e. a pattern). FIXME does
466 : * not parse outer attrs. */
467 : template <typename ManagedTokenSource>
468 : AST::QualifiedPathInExpression
469 97 : Parser<ManagedTokenSource>::parse_qualified_path_in_expression (
470 : location_t pratt_parsed_loc)
471 : {
472 : /* Note: the Rust grammar is defined in such a way that it is impossible to
473 : * determine whether a prospective qualified path is a
474 : * QualifiedPathInExpression or QualifiedPathInType in all cases by the
475 : * rules themselves (the only possible difference is a TypePathSegment with
476 : * function, and lookahead to find this is too difficult). However, as this
477 : * is a pattern and QualifiedPathInType is a type, I believe it that their
478 : * construction will not be confused (due to rules regarding patterns vs
479 : * types).
480 : * As such, this function will not attempt to minimise errors created by
481 : * their confusion. */
482 :
483 : // parse the qualified path type (required)
484 97 : AST::QualifiedPathType qual_path_type
485 : = parse_qualified_path_type (pratt_parsed_loc);
486 97 : if (qual_path_type.is_error ())
487 : {
488 : // TODO: should this create a parse error?
489 0 : return AST::QualifiedPathInExpression::create_error ();
490 : }
491 97 : location_t locus = qual_path_type.get_locus ();
492 :
493 : // parse path segments
494 97 : std::vector<AST::PathExprSegment> segments;
495 :
496 : // parse initial required segment
497 194 : if (!expect_token (SCOPE_RESOLUTION))
498 : {
499 : // skip after somewhere?
500 :
501 0 : return AST::QualifiedPathInExpression::create_error ();
502 : }
503 97 : AST::PathExprSegment initial_segment = parse_path_expr_segment ();
504 97 : if (initial_segment.is_error ())
505 : {
506 : // skip after somewhere?
507 0 : Error error (lexer.peek_token ()->get_locus (),
508 : "required initial path expression segment in "
509 : "qualified path in expression could not be parsed");
510 0 : add_error (std::move (error));
511 :
512 0 : return AST::QualifiedPathInExpression::create_error ();
513 0 : }
514 97 : segments.push_back (std::move (initial_segment));
515 :
516 : // parse optional segments (as long as scope resolution operator exists)
517 97 : const_TokenPtr t = lexer.peek_token ();
518 97 : while (t->get_id () == SCOPE_RESOLUTION)
519 : {
520 : // skip scope resolution operator
521 0 : lexer.skip_token ();
522 :
523 : // parse the actual segment - it is an error if it doesn't exist now
524 0 : AST::PathExprSegment segment = parse_path_expr_segment ();
525 0 : if (segment.is_error ())
526 : {
527 : // skip after somewhere?
528 0 : Error error (t->get_locus (),
529 : "could not parse path expression segment in qualified "
530 : "path in expression");
531 0 : add_error (std::move (error));
532 :
533 0 : return AST::QualifiedPathInExpression::create_error ();
534 0 : }
535 :
536 0 : segments.push_back (std::move (segment));
537 :
538 0 : t = lexer.peek_token ();
539 : }
540 :
541 97 : segments.shrink_to_fit ();
542 :
543 : // FIXME: outer attr parsing
544 194 : return AST::QualifiedPathInExpression (std::move (qual_path_type),
545 97 : std::move (segments), {}, locus);
546 194 : }
547 :
548 : // Parses the type syntactical construction at the start of a qualified path.
549 : template <typename ManagedTokenSource>
550 : AST::QualifiedPathType
551 428 : Parser<ManagedTokenSource>::parse_qualified_path_type (
552 : location_t pratt_parsed_loc)
553 : {
554 428 : location_t locus = pratt_parsed_loc;
555 : /* TODO: should this actually be error? is there anywhere where this could
556 : * be valid? */
557 428 : if (locus == UNKNOWN_LOCATION)
558 : {
559 331 : locus = lexer.peek_token ()->get_locus ();
560 :
561 662 : if (lexer.peek_token ()->get_id () == LEFT_SHIFT)
562 1 : lexer.split_current_token (LEFT_ANGLE, LEFT_ANGLE);
563 :
564 : // skip after somewhere?
565 331 : if (!skip_token (LEFT_ANGLE))
566 0 : return AST::QualifiedPathType::create_error ();
567 : }
568 :
569 : // parse type (required)
570 428 : std::unique_ptr<AST::Type> type = parse_type ();
571 428 : if (type == nullptr)
572 : {
573 0 : Error error (lexer.peek_token ()->get_locus (),
574 : "could not parse type in qualified path type");
575 0 : add_error (std::move (error));
576 :
577 : // skip somewhere?
578 0 : return AST::QualifiedPathType::create_error ();
579 0 : }
580 :
581 : // parse optional as clause
582 428 : AST::TypePath as_type_path = AST::TypePath::create_error ();
583 856 : if (lexer.peek_token ()->get_id () == AS)
584 : {
585 393 : lexer.skip_token ();
586 :
587 : // parse type path, which is required now
588 393 : as_type_path = parse_type_path ();
589 393 : if (as_type_path.is_error ())
590 : {
591 0 : Error error (
592 0 : lexer.peek_token ()->get_locus (),
593 : "could not parse type path in as clause in qualified path type");
594 0 : add_error (std::move (error));
595 :
596 : // skip somewhere?
597 0 : return AST::QualifiedPathType::create_error ();
598 0 : }
599 : }
600 :
601 : /* NOTE: should actually be a right-angle token, so
602 : * skip_generics_right_angle shouldn't be required */
603 428 : if (!skip_token (RIGHT_ANGLE))
604 : {
605 : // skip after somewhere?
606 0 : return AST::QualifiedPathType::create_error ();
607 : }
608 :
609 428 : return AST::QualifiedPathType (std::move (type), locus,
610 428 : std::move (as_type_path));
611 428 : }
612 :
613 : // Parses a fully qualified path in type (i.e. a type).
614 : template <typename ManagedTokenSource>
615 : AST::QualifiedPathInType
616 331 : Parser<ManagedTokenSource>::parse_qualified_path_in_type ()
617 : {
618 331 : location_t locus = lexer.peek_token ()->get_locus ();
619 : // parse the qualified path type (required)
620 331 : AST::QualifiedPathType qual_path_type = parse_qualified_path_type ();
621 331 : if (qual_path_type.is_error ())
622 : {
623 : // TODO: should this create a parse error?
624 0 : return AST::QualifiedPathInType::create_error ();
625 : }
626 :
627 : // parse initial required segment
628 662 : if (!expect_token (SCOPE_RESOLUTION))
629 : {
630 : // skip after somewhere?
631 :
632 0 : return AST::QualifiedPathInType::create_error ();
633 : }
634 331 : std::unique_ptr<AST::TypePathSegment> initial_segment
635 : = parse_type_path_segment ();
636 331 : if (initial_segment == nullptr)
637 : {
638 : // skip after somewhere?
639 0 : Error error (lexer.peek_token ()->get_locus (),
640 : "required initial type path segment in qualified path in "
641 : "type could not be parsed");
642 0 : add_error (std::move (error));
643 :
644 0 : return AST::QualifiedPathInType::create_error ();
645 0 : }
646 :
647 : // parse optional segments (as long as scope resolution operator exists)
648 331 : std::vector<std::unique_ptr<AST::TypePathSegment>> segments;
649 331 : const_TokenPtr t = lexer.peek_token ();
650 331 : while (t->get_id () == SCOPE_RESOLUTION)
651 : {
652 : // skip scope resolution operator
653 0 : lexer.skip_token ();
654 :
655 : // parse the actual segment - it is an error if it doesn't exist now
656 0 : std::unique_ptr<AST::TypePathSegment> segment
657 : = parse_type_path_segment ();
658 0 : if (segment == nullptr)
659 : {
660 : // skip after somewhere?
661 0 : Error error (
662 : t->get_locus (),
663 : "could not parse type path segment in qualified path in type");
664 0 : add_error (std::move (error));
665 :
666 0 : return AST::QualifiedPathInType::create_error ();
667 0 : }
668 :
669 0 : segments.push_back (std::move (segment));
670 :
671 0 : t = lexer.peek_token ();
672 : }
673 :
674 331 : segments.shrink_to_fit ();
675 :
676 662 : return AST::QualifiedPathInType (std::move (qual_path_type),
677 : std::move (initial_segment),
678 331 : std::move (segments), locus);
679 331 : }
680 : } // namespace Rust
|