LCOV - code coverage report
Current view: top level - gcc/rust/parse - rust-parse-impl-path.hxx (source / functions) Coverage Total Hit
Test: gcc.info Lines: 79.2 % 289 229
Test Date: 2026-10-24 16:24:59 Functions: 100.0 % 22 22
Legend: Lines:     hit not hit

            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       107098 : Parser<ManagedTokenSource>::parse_simple_path ()
      31              : {
      32       107098 :   bool has_opening_scope_resolution = false;
      33       107098 :   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       214196 :   if (!is_simple_path_segment (lexer.peek_token ()->get_id ())
      39       139124 :       && !is_simple_path_segment (lexer.peek_token (1)->get_id ()))
      40        28960 :     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       156276 :   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        78138 :   auto segment = parse_simple_path_segment ();
      55              : 
      56        78138 :   if (!segment)
      57         3066 :     return tl::unexpected<Parse::Error::Node> (Parse::Error::Node::CHILD_ERROR);
      58              : 
      59              :   // get location if not gotten already
      60        75072 :   if (locus == UNKNOWN_LOCATION)
      61        75072 :     locus = segment->get_locus ();
      62              : 
      63        75072 :   std::vector<AST::SimplePathSegment> segments;
      64        75072 :   segments.push_back (std::move (segment.value ()));
      65              : 
      66              :   // Parse all other simple path segments
      67       158441 :   while (lexer.peek_token ()->get_id () == SCOPE_RESOLUTION)
      68              :     {
      69         4562 :       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         4562 :       if (!new_segment)
      74              :         {
      75          827 :           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         3735 :       segments.push_back (std::move (new_segment.value ()));
      83              :     }
      84              : 
      85        75072 :   return AST::SimplePath (std::move (segments), has_opening_scope_resolution,
      86        75072 :                           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        75072 : }
      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        82700 : Parser<ManagedTokenSource>::parse_simple_path_segment (int base_peek)
      97              : {
      98              :   using namespace Values;
      99        82700 :   const_TokenPtr t = lexer.peek_token (base_peek);
     100        82700 :   switch (t->get_id ())
     101              :     {
     102        77273 :     case IDENTIFIER:
     103        77273 :       lexer.skip_token (base_peek);
     104              : 
     105       154546 :       return AST::SimplePathSegment (t->get_str (), t->get_locus ());
     106          468 :     case SUPER:
     107          468 :       lexer.skip_token (base_peek);
     108              : 
     109          468 :       return AST::SimplePathSegment (Keywords::SUPER, t->get_locus ());
     110          315 :     case SELF:
     111          315 :       lexer.skip_token (base_peek);
     112              : 
     113          315 :       return AST::SimplePathSegment (Keywords::SELF, t->get_locus ());
     114          751 :     case CRATE:
     115          751 :       lexer.skip_token (base_peek);
     116              : 
     117          751 :       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         3893 :       return Parse::Error::SimplePathSegment::make_invalid_token_or_path_end ();
     132              :     }
     133              :   rust_unreachable ();
     134        82700 : }
     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       592060 : Parser<ManagedTokenSource>::parse_path_ident_segment ()
     140              : {
     141       592060 :   const_TokenPtr t = lexer.peek_token ();
     142       592060 :   switch (t->get_id ())
     143              :     {
     144       551819 :     case IDENTIFIER:
     145       551819 :       lexer.skip_token ();
     146              : 
     147      1103638 :       return AST::PathIdentSegment (t->get_str (), t->get_locus ());
     148           86 :     case SUPER:
     149           86 :       lexer.skip_token ();
     150              : 
     151           86 :       return AST::PathIdentSegment (Values::Keywords::SUPER, t->get_locus ());
     152        23286 :     case SELF:
     153        23286 :       lexer.skip_token ();
     154              : 
     155        23286 :       return AST::PathIdentSegment (Values::Keywords::SELF, t->get_locus ());
     156        15252 :     case SELF_ALIAS:
     157        15252 :       lexer.skip_token ();
     158              : 
     159        30504 :       return AST::PathIdentSegment (Values::Keywords::SELF_ALIAS,
     160        15252 :                                     t->get_locus ());
     161         1365 :     case CRATE:
     162         1365 :       lexer.skip_token ();
     163              : 
     164         1365 :       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          252 :       return Parse::Error::PathIdentSegment::make_invalid_token ();
     180              :     }
     181              :   rust_unreachable ();
     182       592060 : }
     183              : 
     184              : // Parses a type path.
     185              : template <typename ManagedTokenSource>
     186              : AST::TypePath
     187       141418 : Parser<ManagedTokenSource>::parse_type_path ()
     188              : {
     189       141418 :   bool has_opening_scope_resolution = false;
     190       141418 :   location_t locus = lexer.peek_token ()->get_locus ();
     191       282836 :   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       141418 :   std::vector<std::unique_ptr<AST::TypePathSegment>> segments;
     199              : 
     200              :   // parse required initial segment
     201       141418 :   std::unique_ptr<AST::TypePathSegment> initial_segment
     202              :     = parse_type_path_segment ();
     203       141418 :   if (initial_segment == nullptr)
     204              :     {
     205              :       // skip after somewhere?
     206              :       // don't necessarily throw error but yeah
     207          241 :       return AST::TypePath::create_error ();
     208              :     }
     209       141177 :   segments.push_back (std::move (initial_segment));
     210              : 
     211              :   // parse optional segments (as long as scope resolution operator exists)
     212       141177 :   const_TokenPtr t = lexer.peek_token ();
     213       146169 :   while (t->get_id () == SCOPE_RESOLUTION)
     214              :     {
     215              :       // skip scope resolution operator
     216         4992 :       lexer.skip_token ();
     217              : 
     218              :       // parse the actual segment - it is an error if it doesn't exist now
     219         4992 :       std::unique_ptr<AST::TypePathSegment> segment
     220              :         = parse_type_path_segment ();
     221         4992 :       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         4992 :       segments.push_back (std::move (segment));
     231              : 
     232         4992 :       t = lexer.peek_token ();
     233              :     }
     234              : 
     235       141177 :   segments.shrink_to_fit ();
     236              : 
     237       282354 :   return AST::TypePath (std::move (segments), locus,
     238       141177 :                         has_opening_scope_resolution);
     239       141418 : }
     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       149993 : Parser<ManagedTokenSource>::parse_type_path_segment ()
     247              : {
     248       149993 :   location_t locus = lexer.peek_token ()->get_locus ();
     249              :   // parse ident segment part
     250       149993 :   auto ident_segment_res = parse_path_ident_segment ();
     251       149993 :   if (!ident_segment_res)
     252              :     {
     253              :       // not necessarily an error
     254          241 :       return nullptr;
     255              :     }
     256       149752 :   auto ident_segment = ident_segment_res.value ();
     257              : 
     258              :   /* lookahead to determine if variants exist - only consume scope resolution
     259              :    * then */
     260       149752 :   bool has_separating_scope_resolution = false;
     261       149752 :   const_TokenPtr next = lexer.peek_token (1);
     262       299504 :   if (lexer.peek_token ()->get_id () == SCOPE_RESOLUTION
     263       149752 :       && (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       149752 :   const_TokenPtr t = lexer.peek_token ();
     271       149752 :   switch (t->get_id ())
     272              :     {
     273        20979 :     case LEFT_SHIFT:
     274              :     case LEFT_ANGLE:
     275              :       {
     276              :         // parse generic args
     277        20979 :         AST::GenericArgs generic_args = parse_path_generic_args ();
     278              : 
     279        20979 :         return std::unique_ptr<AST::TypePathSegmentGeneric> (
     280        41958 :           new AST::TypePathSegmentGeneric (std::move (ident_segment),
     281              :                                            has_separating_scope_resolution,
     282        20979 :                                            std::move (generic_args), locus));
     283        20979 :       }
     284          620 :     case LEFT_PAREN:
     285              :       {
     286              :         // parse type path function
     287          620 :         AST::TypePathFunction type_path_function
     288              :           = parse_type_path_function (locus);
     289              : 
     290          620 :         if (type_path_function.is_error ())
     291              :           {
     292              :             // skip after somewhere?
     293            0 :             return nullptr;
     294              :           }
     295              : 
     296          620 :         return std::unique_ptr<AST::TypePathSegmentFunction> (
     297         1860 :           new AST::TypePathSegmentFunction (std::move (ident_segment),
     298              :                                             has_separating_scope_resolution,
     299              :                                             std::move (type_path_function),
     300          620 :                                             locus));
     301          620 :       }
     302       128153 :     default:
     303              :       // neither of them
     304              :       return std::unique_ptr<AST::TypePathSegment> (
     305       128153 :         new AST::TypePathSegment (std::move (ident_segment),
     306       128153 :                                   has_separating_scope_resolution, locus));
     307              :     }
     308              :   rust_unreachable ();
     309       299504 : }
     310              : 
     311              : // Parses a function call representation inside a type path.
     312              : template <typename ManagedTokenSource>
     313              : AST::TypePathFunction
     314          620 : Parser<ManagedTokenSource>::parse_type_path_function (location_t id_location)
     315              : {
     316          620 :   if (!skip_token (LEFT_PAREN))
     317              :     {
     318              :       // skip somewhere?
     319            0 :       return AST::TypePathFunction::create_error ();
     320              :     }
     321              : 
     322              :   // parse function inputs
     323          620 :   std::vector<std::unique_ptr<AST::Type>> inputs;
     324              : 
     325         2329 :   while (lexer.peek_token ()->get_id () != RIGHT_PAREN)
     326              :     {
     327          834 :       std::unique_ptr<AST::Type> type = parse_type ();
     328          834 :       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          834 :       inputs.push_back (std::move (type));
     342              : 
     343              :       // skip commas, including trailing commas
     344         1668 :       if (lexer.peek_token ()->get_id () != COMMA)
     345              :         break;
     346              : 
     347          248 :       lexer.skip_token ();
     348              :     }
     349              : 
     350          620 :   if (!skip_token (RIGHT_PAREN))
     351              :     {
     352              :       // skip somewhere?
     353            0 :       return AST::TypePathFunction::create_error ();
     354              :     }
     355              : 
     356              :   // parse optional return type
     357          620 :   std::unique_ptr<AST::Type> return_type = parse_function_return_type ();
     358              : 
     359          620 :   inputs.shrink_to_fit ();
     360          620 :   return AST::TypePathFunction (std::move (inputs), id_location,
     361          620 :                                 std::move (return_type));
     362          620 : }
     363              : 
     364              : // Parses a path inside an expression that allows generic arguments.
     365              : template <typename ManagedTokenSource>
     366              : AST::PathInExpression
     367       389398 : Parser<ManagedTokenSource>::parse_path_in_expression ()
     368              : {
     369       389398 :   location_t locus = UNKNOWN_LOCATION;
     370       389398 :   bool has_opening_scope_resolution = false;
     371       778796 :   if (lexer.peek_token ()->get_id () == SCOPE_RESOLUTION)
     372              :     {
     373           12 :       has_opening_scope_resolution = true;
     374              : 
     375           12 :       locus = lexer.peek_token ()->get_locus ();
     376              : 
     377           12 :       lexer.skip_token ();
     378              :     }
     379              : 
     380              :   // create segment vector
     381       389398 :   std::vector<AST::PathExprSegment> segments;
     382              : 
     383       389398 :   if (locus == UNKNOWN_LOCATION)
     384              :     {
     385       778772 :       locus = lexer.peek_token ()->get_locus ();
     386              :     }
     387              : 
     388              :   // parse required initial segment
     389       389398 :   AST::PathExprSegment initial_segment = parse_path_expr_segment ();
     390       389398 :   if (initial_segment.is_error ())
     391              :     {
     392            7 :       if (has_opening_scope_resolution)
     393              :         {
     394            3 :           Error error (locus, "expected identifier");
     395            3 :           add_error (std::move (error));
     396            3 :         }
     397            7 :       return AST::PathInExpression::create_error ();
     398              :     }
     399       389391 :   segments.push_back (std::move (initial_segment));
     400              : 
     401              :   // parse optional segments (as long as scope resolution operator exists)
     402       389391 :   const_TokenPtr t = lexer.peek_token ();
     403       408690 :   while (t->get_id () == SCOPE_RESOLUTION)
     404              :     {
     405              :       // skip scope resolution operator
     406        19299 :       lexer.skip_token ();
     407              : 
     408              :       // parse the actual segment - it is an error if it doesn't exist now
     409        19299 :       AST::PathExprSegment segment = parse_path_expr_segment ();
     410        19299 :       if (segment.is_error ())
     411              :         {
     412              :           // skip after somewhere?
     413            4 :           Error error (t->get_locus (),
     414              :                        "could not parse path expression segment");
     415            4 :           add_error (std::move (error));
     416              : 
     417            4 :           return AST::PathInExpression::create_error ();
     418            4 :         }
     419              : 
     420        19295 :       segments.push_back (std::move (segment));
     421              : 
     422        19295 :       t = lexer.peek_token ();
     423              :     }
     424              : 
     425       389387 :   segments.shrink_to_fit ();
     426              : 
     427       389387 :   return AST::PathInExpression (std::move (segments), {}, locus,
     428       389387 :                                 has_opening_scope_resolution);
     429       778789 : }
     430              : 
     431              : /* Parses a single path in expression path segment (including generic
     432              :  * arguments). */
     433              : template <typename ManagedTokenSource>
     434              : AST::PathExprSegment
     435       442067 : Parser<ManagedTokenSource>::parse_path_expr_segment ()
     436              : {
     437       442067 :   location_t locus = lexer.peek_token ()->get_locus ();
     438              :   // parse ident segment
     439       442067 :   auto ident_result = parse_path_ident_segment ();
     440       442067 :   if (!ident_result)
     441              :     {
     442              :       // not necessarily an error?
     443           11 :       return AST::PathExprSegment::create_error ();
     444              :     }
     445       442056 :   auto ident = ident_result.value ();
     446              : 
     447              :   // parse generic args (and turbofish), if they exist
     448              :   /* use lookahead to determine if they actually exist (don't want to
     449              :    * accidently parse over next ident segment) */
     450       884112 :   if (lexer.peek_token ()->get_id () == SCOPE_RESOLUTION
     451       884112 :       && (lexer.peek_token (1)->get_id () == LEFT_ANGLE
     452       461217 :           || lexer.peek_token (1)->get_id () == LEFT_SHIFT))
     453              :     {
     454              :       // skip scope resolution
     455         1614 :       lexer.skip_token ();
     456              : 
     457              :       // Let parse_path_generic_args split "<<" tokens
     458         1614 :       AST::GenericArgs generic_args = parse_path_generic_args ();
     459              : 
     460         3228 :       return AST::PathExprSegment (std::move (ident), locus,
     461         1614 :                                    std::move (generic_args));
     462         1614 :     }
     463              : 
     464              :   // return a generic parameter-less expr segment if not found
     465       440442 :   return AST::PathExprSegment (std::move (ident), locus);
     466       442056 : }
     467              : 
     468              : /* Parses a fully qualified path in expression (i.e. a pattern). FIXME does
     469              :  * not parse outer attrs. */
     470              : template <typename ManagedTokenSource>
     471              : AST::QualifiedPathInExpression
     472          213 : Parser<ManagedTokenSource>::parse_qualified_path_in_expression (
     473              :   location_t pratt_parsed_loc)
     474              : {
     475              :   /* Note: the Rust grammar is defined in such a way that it is impossible to
     476              :    * determine whether a prospective qualified path is a
     477              :    * QualifiedPathInExpression or QualifiedPathInType in all cases by the
     478              :    * rules themselves (the only possible difference is a TypePathSegment with
     479              :    * function, and lookahead to find this is too difficult). However, as this
     480              :    * is a pattern and QualifiedPathInType is a type, I believe it that their
     481              :    * construction will not be confused (due to rules regarding patterns vs
     482              :    * types).
     483              :    * As such, this function will not attempt to minimise errors created by
     484              :    * their confusion. */
     485              : 
     486              :   // parse the qualified path type (required)
     487          213 :   AST::QualifiedPathType qual_path_type
     488              :     = parse_qualified_path_type (pratt_parsed_loc);
     489          213 :   if (qual_path_type.is_error ())
     490              :     {
     491              :       // TODO: should this create a parse error?
     492            0 :       return AST::QualifiedPathInExpression::create_error ();
     493              :     }
     494          213 :   location_t locus = qual_path_type.get_locus ();
     495              : 
     496              :   // parse path segments
     497          213 :   std::vector<AST::PathExprSegment> segments;
     498              : 
     499              :   // parse initial required segment
     500          426 :   if (!expect_token (SCOPE_RESOLUTION))
     501              :     {
     502              :       // skip after somewhere?
     503              : 
     504            0 :       return AST::QualifiedPathInExpression::create_error ();
     505              :     }
     506          213 :   AST::PathExprSegment initial_segment = parse_path_expr_segment ();
     507          213 :   if (initial_segment.is_error ())
     508              :     {
     509              :       // skip after somewhere?
     510            0 :       Error error (lexer.peek_token ()->get_locus (),
     511              :                    "required initial path expression segment in "
     512              :                    "qualified path in expression could not be parsed");
     513            0 :       add_error (std::move (error));
     514              : 
     515            0 :       return AST::QualifiedPathInExpression::create_error ();
     516            0 :     }
     517          213 :   segments.push_back (std::move (initial_segment));
     518              : 
     519              :   // parse optional segments (as long as scope resolution operator exists)
     520          213 :   const_TokenPtr t = lexer.peek_token ();
     521          214 :   while (t->get_id () == SCOPE_RESOLUTION)
     522              :     {
     523              :       // skip scope resolution operator
     524            1 :       lexer.skip_token ();
     525              : 
     526              :       // parse the actual segment - it is an error if it doesn't exist now
     527            1 :       AST::PathExprSegment segment = parse_path_expr_segment ();
     528            1 :       if (segment.is_error ())
     529              :         {
     530              :           // skip after somewhere?
     531            0 :           Error error (t->get_locus (),
     532              :                        "could not parse path expression segment in qualified "
     533              :                        "path in expression");
     534            0 :           add_error (std::move (error));
     535              : 
     536            0 :           return AST::QualifiedPathInExpression::create_error ();
     537            0 :         }
     538              : 
     539            1 :       segments.push_back (std::move (segment));
     540              : 
     541            1 :       t = lexer.peek_token ();
     542              :     }
     543              : 
     544          213 :   segments.shrink_to_fit ();
     545              : 
     546              :   // FIXME: outer attr parsing
     547          426 :   return AST::QualifiedPathInExpression (std::move (qual_path_type),
     548          213 :                                          std::move (segments), {}, locus);
     549          426 : }
     550              : 
     551              : // Parses the type syntactical construction at the start of a qualified path.
     552              : template <typename ManagedTokenSource>
     553              : AST::QualifiedPathType
     554         3796 : Parser<ManagedTokenSource>::parse_qualified_path_type (
     555              :   location_t pratt_parsed_loc)
     556              : {
     557         3796 :   location_t locus = pratt_parsed_loc;
     558              :   /* TODO: should this actually be error? is there anywhere where this could
     559              :    * be valid? */
     560         3796 :   if (locus == UNKNOWN_LOCATION)
     561              :     {
     562         3583 :       locus = lexer.peek_token ()->get_locus ();
     563              : 
     564         7166 :       if (lexer.peek_token ()->get_id () == LEFT_SHIFT)
     565            2 :         lexer.split_current_token (LEFT_ANGLE, LEFT_ANGLE);
     566              : 
     567              :       // skip after somewhere?
     568         3583 :       if (!skip_token (LEFT_ANGLE))
     569            0 :         return AST::QualifiedPathType::create_error ();
     570              :     }
     571              : 
     572              :   // parse type (required)
     573         3796 :   std::unique_ptr<AST::Type> type = parse_type ();
     574         3796 :   if (type == nullptr)
     575              :     {
     576            0 :       Error error (lexer.peek_token ()->get_locus (),
     577              :                    "could not parse type in qualified path type");
     578            0 :       add_error (std::move (error));
     579              : 
     580              :       // skip somewhere?
     581            0 :       return AST::QualifiedPathType::create_error ();
     582            0 :     }
     583              : 
     584              :   // parse optional as clause
     585         3796 :   AST::TypePath as_type_path = AST::TypePath::create_error ();
     586         7592 :   if (lexer.peek_token ()->get_id () == AS)
     587              :     {
     588         3675 :       lexer.skip_token ();
     589              : 
     590              :       // parse type path, which is required now
     591         3675 :       as_type_path = parse_type_path ();
     592         3675 :       if (as_type_path.is_error ())
     593              :         {
     594            0 :           Error error (
     595            0 :             lexer.peek_token ()->get_locus (),
     596              :             "could not parse type path in as clause in qualified path type");
     597            0 :           add_error (std::move (error));
     598              : 
     599              :           // skip somewhere?
     600            0 :           return AST::QualifiedPathType::create_error ();
     601            0 :         }
     602              :     }
     603              : 
     604              :   /* NOTE: should actually be a right-angle token, so
     605              :    * skip_generics_right_angle shouldn't be required */
     606         3796 :   if (!skip_token (RIGHT_ANGLE))
     607              :     {
     608              :       // skip after somewhere?
     609            0 :       return AST::QualifiedPathType::create_error ();
     610              :     }
     611              : 
     612         3796 :   return AST::QualifiedPathType (std::move (type), locus,
     613         3796 :                                  std::move (as_type_path));
     614         3796 : }
     615              : 
     616              : // Parses a fully qualified path in type (i.e. a type).
     617              : template <typename ManagedTokenSource>
     618              : AST::QualifiedPathInType
     619         3583 : Parser<ManagedTokenSource>::parse_qualified_path_in_type ()
     620              : {
     621         3583 :   location_t locus = lexer.peek_token ()->get_locus ();
     622              :   // parse the qualified path type (required)
     623         3583 :   AST::QualifiedPathType qual_path_type = parse_qualified_path_type ();
     624         3583 :   if (qual_path_type.is_error ())
     625              :     {
     626              :       // TODO: should this create a parse error?
     627            0 :       return AST::QualifiedPathInType::create_error ();
     628              :     }
     629              : 
     630              :   // parse initial required segment
     631         7166 :   if (!expect_token (SCOPE_RESOLUTION))
     632              :     {
     633              :       // skip after somewhere?
     634              : 
     635            0 :       return AST::QualifiedPathInType::create_error ();
     636              :     }
     637         3583 :   std::unique_ptr<AST::TypePathSegment> initial_segment
     638              :     = parse_type_path_segment ();
     639         3583 :   if (initial_segment == nullptr)
     640              :     {
     641              :       // skip after somewhere?
     642            0 :       Error error (lexer.peek_token ()->get_locus (),
     643              :                    "required initial type path segment in qualified path in "
     644              :                    "type could not be parsed");
     645            0 :       add_error (std::move (error));
     646              : 
     647            0 :       return AST::QualifiedPathInType::create_error ();
     648            0 :     }
     649              : 
     650              :   // parse optional segments (as long as scope resolution operator exists)
     651         3583 :   std::vector<std::unique_ptr<AST::TypePathSegment>> segments;
     652         3583 :   const_TokenPtr t = lexer.peek_token ();
     653         3583 :   while (t->get_id () == SCOPE_RESOLUTION)
     654              :     {
     655              :       // skip scope resolution operator
     656            0 :       lexer.skip_token ();
     657              : 
     658              :       // parse the actual segment - it is an error if it doesn't exist now
     659            0 :       std::unique_ptr<AST::TypePathSegment> segment
     660              :         = parse_type_path_segment ();
     661            0 :       if (segment == nullptr)
     662              :         {
     663              :           // skip after somewhere?
     664            0 :           Error error (
     665              :             t->get_locus (),
     666              :             "could not parse type path segment in qualified path in type");
     667            0 :           add_error (std::move (error));
     668              : 
     669            0 :           return AST::QualifiedPathInType::create_error ();
     670            0 :         }
     671              : 
     672            0 :       segments.push_back (std::move (segment));
     673              : 
     674            0 :       t = lexer.peek_token ();
     675              :     }
     676              : 
     677         3583 :   segments.shrink_to_fit ();
     678              : 
     679         7166 :   return AST::QualifiedPathInType (std::move (qual_path_type),
     680              :                                    std::move (initial_segment),
     681         3583 :                                    std::move (segments), locus);
     682         3583 : }
     683              : } // namespace Rust
        

Generated by: LCOV version 2.5.0-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.