LCOV - code coverage report
Current view: top level - gcc/rust/parse - rust-parse-impl-pattern.hxx (source / functions) Coverage Total Hit
Test: gcc.info Lines: 73.5 % 634 466
Test Date: 2026-08-08 15:37:49 Functions: 87.5 % 24 21
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              : template <typename ManagedTokenSource>
      28              : std::unique_ptr<AST::Pattern>
      29       107947 : Parser<ManagedTokenSource>::parse_pattern ()
      30              : {
      31       107947 :   location_t start_locus = lexer.peek_token ()->get_locus ();
      32              : 
      33              :   /* skip optional starting pipe */
      34       107947 :   maybe_skip_token (PIPE);
      35              : 
      36       107947 :   auto first = parse_pattern_no_alt ();
      37              : 
      38       215894 :   if (lexer.peek_token ()->get_id () != PIPE)
      39              :     /* no alternates */
      40       107699 :     return first;
      41              : 
      42          248 :   std::vector<std::unique_ptr<AST::Pattern>> alts;
      43          248 :   if (first != nullptr)
      44          247 :     alts.push_back (std::move (first));
      45              : 
      46              :   do
      47              :     {
      48          303 :       lexer.skip_token ();
      49          303 :       auto follow = parse_pattern_no_alt ();
      50          303 :       if (follow != nullptr)
      51          303 :         alts.push_back (std::move (follow));
      52          303 :     }
      53              : 
      54          606 :   while (lexer.peek_token ()->get_id () == PIPE);
      55              : 
      56          248 :   if (alts.empty ())
      57            0 :     return nullptr;
      58              : 
      59              :   /* alternates */
      60              :   return std::unique_ptr<AST::Pattern> (
      61          248 :     new AST::AltPattern (std::move (alts), start_locus));
      62       107947 : }
      63              : 
      64              : // Parses a pattern without alternates ('|')
      65              : // (will further disambiguate any pattern).
      66              : template <typename ManagedTokenSource>
      67              : std::unique_ptr<AST::Pattern>
      68       108839 : Parser<ManagedTokenSource>::parse_pattern_no_alt ()
      69              : {
      70       108839 :   const_TokenPtr t = lexer.peek_token ();
      71       108839 :   switch (t->get_id ())
      72              :     {
      73           31 :     case TRUE_LITERAL:
      74           31 :       lexer.skip_token ();
      75           31 :       return std::unique_ptr<AST::LiteralPattern> (
      76           93 :         new AST::LiteralPattern (Values::Keywords::TRUE_LITERAL,
      77              :                                  AST::Literal::BOOL, t->get_locus (),
      78           31 :                                  t->get_type_hint ()));
      79           23 :     case FALSE_LITERAL:
      80           23 :       lexer.skip_token ();
      81           23 :       return std::unique_ptr<AST::LiteralPattern> (
      82           69 :         new AST::LiteralPattern (Values::Keywords::FALSE_LITERAL,
      83              :                                  AST::Literal::BOOL, t->get_locus (),
      84           23 :                                  t->get_type_hint ()));
      85        45646 :     case CHAR_LITERAL:
      86              :     case BYTE_CHAR_LITERAL:
      87              :     case INT_LITERAL:
      88              :     case FLOAT_LITERAL:
      89        45646 :       return parse_literal_or_range_pattern ();
      90            4 :     case STRING_LITERAL:
      91            4 :       lexer.skip_token ();
      92            4 :       return std::unique_ptr<AST::LiteralPattern> (
      93           16 :         new AST::LiteralPattern (t->get_str (), AST::Literal::STRING,
      94            4 :                                  t->get_locus (), t->get_type_hint ()));
      95            0 :     case BYTE_STRING_LITERAL:
      96            0 :       lexer.skip_token ();
      97            0 :       return std::unique_ptr<AST::LiteralPattern> (
      98            0 :         new AST::LiteralPattern (t->get_str (), AST::Literal::BYTE_STRING,
      99            0 :                                  t->get_locus (), t->get_type_hint ()));
     100            0 :     case RAW_STRING_LITERAL:
     101            0 :       lexer.skip_token ();
     102            0 :       return std::unique_ptr<AST::LiteralPattern> (
     103            0 :         new AST::LiteralPattern (t->get_str (), AST::Literal::RAW_STRING,
     104            0 :                                  t->get_locus (), t->get_type_hint ()));
     105              :     // raw string and raw byte string literals too if they are readded to
     106              :     // lexer
     107           27 :     case MINUS:
     108           54 :       if (lexer.peek_token (1)->get_id () == INT_LITERAL)
     109              :         {
     110           25 :           return parse_literal_or_range_pattern ();
     111              :         }
     112            4 :       else if (lexer.peek_token (1)->get_id () == FLOAT_LITERAL)
     113              :         {
     114            2 :           return parse_literal_or_range_pattern ();
     115              :         }
     116              :       else
     117              :         {
     118            0 :           Error error (t->get_locus (), "unexpected token %<-%> in pattern - "
     119              :                                         "did you forget an integer literal");
     120            0 :           add_error (std::move (error));
     121              : 
     122            0 :           return nullptr;
     123            0 :         }
     124         5426 :     case UNDERSCORE:
     125         5426 :       lexer.skip_token ();
     126         5426 :       return std::unique_ptr<AST::WildcardPattern> (
     127         5426 :         new AST::WildcardPattern (t->get_locus ()));
     128           63 :     case DOT_DOT:
     129           63 :       lexer.skip_token ();
     130           63 :       return std::unique_ptr<AST::RestPattern> (
     131           63 :         new AST::RestPattern (t->get_locus ()));
     132         2072 :     case REF:
     133              :     case MUT:
     134         2072 :       return parse_identifier_pattern ();
     135        52300 :     case IDENTIFIER:
     136              :       /* if identifier with no scope resolution afterwards, identifier
     137              :        * pattern. if scope resolution afterwards, path pattern (or range
     138              :        * pattern or struct pattern or tuple struct pattern) or macro
     139              :        * invocation */
     140        52300 :       return parse_ident_leading_pattern ();
     141          101 :     case AMP:
     142              :     case LOGICAL_AND:
     143              :       // reference pattern
     144          101 :       return parse_reference_pattern ();
     145         3031 :     case LEFT_PAREN:
     146              :       // tuple pattern or grouped pattern
     147         3031 :       return parse_grouped_or_tuple_pattern ();
     148          104 :     case LEFT_SQUARE:
     149              :       // slice pattern
     150          104 :       return parse_slice_pattern ();
     151            0 :     case LEFT_SHIFT:
     152              :     case LEFT_ANGLE:
     153              :       {
     154              :         // qualified path in expression or qualified range pattern bound
     155            0 :         AST::QualifiedPathInExpression path
     156              :           = parse_qualified_path_in_expression ();
     157              : 
     158            0 :         if (lexer.peek_token ()->get_id () == DOT_DOT_EQ
     159            0 :             || lexer.peek_token ()->get_id () == ELLIPSIS
     160            0 :             || lexer.peek_token ()->get_id () == DOT_DOT)
     161              :           {
     162              :             // qualified range pattern bound, so parse rest of range pattern
     163              :             AST::RangeKind kind
     164            0 :               = AST::tokenid_to_rangekind (lexer.peek_token ()->get_id ());
     165            0 :             lexer.skip_token ();
     166              : 
     167            0 :             std::unique_ptr<AST::RangePatternBoundQualPath> lower_bound (
     168            0 :               new AST::RangePatternBoundQualPath (std::move (path)));
     169            0 :             std::unique_ptr<AST::RangePatternBound> upper_bound
     170              :               = parse_range_pattern_bound ();
     171              : 
     172            0 :             return std::unique_ptr<AST::RangePattern> (
     173            0 :               new AST::RangePattern (std::move (lower_bound),
     174              :                                      std::move (upper_bound), kind,
     175            0 :                                      t->get_locus ()));
     176            0 :           }
     177              :         else
     178              :           {
     179              :             // just qualified path in expression
     180            0 :             return std::unique_ptr<AST::QualifiedPathInExpression> (
     181            0 :               new AST::QualifiedPathInExpression (std::move (path)));
     182              :           }
     183            0 :       }
     184           10 :     case SUPER:
     185              :     case SELF:
     186              :     case SELF_ALIAS:
     187              :     case CRATE:
     188              :     case SCOPE_RESOLUTION:
     189              :     case DOLLAR_SIGN:
     190              :       {
     191              :         // path in expression or range pattern bound
     192           10 :         AST::PathInExpression path = parse_path_in_expression ();
     193              : 
     194           10 :         const_TokenPtr next = lexer.peek_token ();
     195           10 :         switch (next->get_id ())
     196              :           {
     197            0 :           case DOT_DOT_EQ:
     198              :           case DOT_DOT:
     199              :           case ELLIPSIS:
     200              :             {
     201              :               // qualified range pattern bound, so parse rest of range pattern
     202            0 :               AST::RangeKind kind = AST::tokenid_to_rangekind (next->get_id ());
     203            0 :               lexer.skip_token ();
     204              : 
     205            0 :               std::unique_ptr<AST::RangePatternBoundPath> lower_bound (
     206            0 :                 new AST::RangePatternBoundPath (std::move (path)));
     207            0 :               std::unique_ptr<AST::RangePatternBound> upper_bound
     208              :                 = parse_range_pattern_bound ();
     209              : 
     210            0 :               return std::unique_ptr<AST::RangePattern> (
     211            0 :                 new AST::RangePattern (std::move (lower_bound),
     212              :                                        std::move (upper_bound), kind,
     213              :                                        next->get_locus ()));
     214            0 :             }
     215            0 :           case EXCLAM:
     216            0 :             return parse_macro_invocation_partial (std::move (path),
     217            0 :                                                    AST::AttrVec ());
     218            0 :           case LEFT_PAREN:
     219              :             {
     220              :               // tuple struct
     221            0 :               lexer.skip_token ();
     222              : 
     223              :               // parse items
     224            0 :               std::unique_ptr<AST::TupleStructItems> items
     225              :                 = parse_tuple_struct_items ();
     226            0 :               if (items == nullptr)
     227              :                 {
     228            0 :                   Error error (lexer.peek_token ()->get_locus (),
     229              :                                "failed to parse tuple struct items");
     230            0 :                   add_error (std::move (error));
     231              : 
     232            0 :                   return nullptr;
     233            0 :                 }
     234              : 
     235            0 :               if (!skip_token (RIGHT_PAREN))
     236              :                 {
     237            0 :                   return nullptr;
     238              :                 }
     239              : 
     240            0 :               return std::unique_ptr<AST::TupleStructPattern> (
     241            0 :                 new AST::TupleStructPattern (std::move (path),
     242            0 :                                              std::move (items)));
     243            0 :             }
     244            1 :           case LEFT_CURLY:
     245              :             {
     246              :               // struct
     247            1 :               lexer.skip_token ();
     248              : 
     249              :               // parse elements (optional)
     250            1 :               AST::StructPatternElements elems = parse_struct_pattern_elems ();
     251              : 
     252            1 :               if (!skip_token (RIGHT_CURLY))
     253              :                 {
     254            0 :                   return nullptr;
     255              :                 }
     256              : 
     257            1 :               return std::unique_ptr<AST::StructPattern> (
     258            2 :                 new AST::StructPattern (std::move (path), t->get_locus (),
     259            1 :                                         std::move (elems)));
     260            1 :             }
     261            9 :           default:
     262              :             // assume path in expression
     263            9 :             return std::unique_ptr<AST::PathInExpression> (
     264            9 :               new AST::PathInExpression (std::move (path)));
     265              :           }
     266           10 :       }
     267            1 :     default:
     268            1 :       add_error (Error (t->get_locus (), "unexpected token %qs in pattern",
     269              :                         t->get_token_description ()));
     270              : 
     271            1 :       return nullptr;
     272              :     }
     273       108839 : }
     274              : 
     275              : // Parses a single or double reference pattern.
     276              : template <typename ManagedTokenSource>
     277              : std::unique_ptr<AST::ReferencePattern>
     278          101 : Parser<ManagedTokenSource>::parse_reference_pattern ()
     279              : {
     280              :   // parse double or single ref
     281          101 :   bool is_double_ref = false;
     282          101 :   const_TokenPtr t = lexer.peek_token ();
     283          101 :   switch (t->get_id ())
     284              :     {
     285           87 :     case AMP:
     286              :       // still false
     287           87 :       lexer.skip_token ();
     288              :       break;
     289           14 :     case LOGICAL_AND:
     290           14 :       is_double_ref = true;
     291           14 :       lexer.skip_token ();
     292              :       break;
     293            0 :     default:
     294            0 :       add_error (Error (t->get_locus (),
     295              :                         "unexpected token %qs in reference pattern",
     296              :                         t->get_token_description ()));
     297              : 
     298            0 :       return nullptr;
     299              :     }
     300              : 
     301              :   // parse mut (if it exists)
     302          101 :   bool is_mut = false;
     303          202 :   if (lexer.peek_token ()->get_id () == MUT)
     304              :     {
     305            4 :       is_mut = true;
     306            4 :       lexer.skip_token ();
     307              :     }
     308              : 
     309              :   // parse pattern to get reference of (required)
     310          101 :   std::unique_ptr<AST::Pattern> pattern = parse_pattern_no_alt ();
     311          101 :   if (pattern == nullptr)
     312              :     {
     313            0 :       Error error (lexer.peek_token ()->get_locus (),
     314              :                    "failed to parse pattern in reference pattern");
     315            0 :       add_error (std::move (error));
     316              : 
     317              :       // skip somewhere?
     318            0 :       return nullptr;
     319            0 :     }
     320              : 
     321              :   return std::unique_ptr<AST::ReferencePattern> (
     322          101 :     new AST::ReferencePattern (std::move (pattern), is_mut, is_double_ref,
     323          101 :                                t->get_locus ()));
     324          101 : }
     325              : 
     326              : /* Parses a grouped pattern or tuple pattern. Prefers grouped over tuple if
     327              :  * only a single element with no commas. */
     328              : template <typename ManagedTokenSource>
     329              : std::unique_ptr<AST::Pattern>
     330         3031 : Parser<ManagedTokenSource>::parse_grouped_or_tuple_pattern ()
     331              : {
     332         3031 :   location_t paren_locus = lexer.peek_token ()->get_locus ();
     333         3031 :   skip_token (LEFT_PAREN);
     334              : 
     335              :   // detect '..' token (ranged with no lower range)
     336         6062 :   if (lexer.peek_token ()->get_id () == DOT_DOT)
     337              :     {
     338            6 :       lexer.skip_token ();
     339              : 
     340              :       // parse new patterns while next token is a comma
     341            6 :       std::vector<std::unique_ptr<AST::Pattern>> patterns;
     342              : 
     343            6 :       const_TokenPtr t = lexer.peek_token ();
     344            6 :       while (t->get_id () == COMMA)
     345              :         {
     346            0 :           lexer.skip_token ();
     347              : 
     348              :           // break if next token is ')'
     349            0 :           if (lexer.peek_token ()->get_id () == RIGHT_PAREN)
     350              :             {
     351              :               break;
     352              :             }
     353              : 
     354              :           // parse pattern, which is required
     355            0 :           std::unique_ptr<AST::Pattern> pattern = parse_pattern ();
     356            0 :           if (pattern == nullptr)
     357              :             {
     358            0 :               Error error (
     359            0 :                 lexer.peek_token ()->get_locus (),
     360              :                 "failed to parse pattern inside ranged tuple pattern");
     361            0 :               add_error (std::move (error));
     362              : 
     363              :               // skip somewhere?
     364            0 :               return nullptr;
     365            0 :             }
     366            0 :           patterns.push_back (std::move (pattern));
     367              : 
     368            0 :           t = lexer.peek_token ();
     369              :         }
     370              : 
     371            6 :       if (!skip_token (RIGHT_PAREN))
     372              :         {
     373              :           // skip somewhere?
     374            0 :           return nullptr;
     375              :         }
     376              : 
     377              :       // create tuple pattern items with only upper pattern items
     378            6 :       std::unique_ptr<AST::TuplePatternItemsHasRest> items (
     379            6 :         new AST::TuplePatternItemsHasRest (
     380            6 :           std::vector<std::unique_ptr<AST::Pattern>> (), std::move (patterns)));
     381            6 :       return std::unique_ptr<AST::TuplePattern> (
     382            6 :         new AST::TuplePattern (std::move (items), paren_locus));
     383           12 :     }
     384         6050 :   else if (lexer.peek_token ()->get_id () == RIGHT_PAREN)
     385              :     {
     386           24 :       skip_token (RIGHT_PAREN);
     387           24 :       auto items = std::unique_ptr<AST::TuplePatternItemsNoRest> (
     388           24 :         new AST::TuplePatternItemsNoRest (
     389           24 :           std::vector<std::unique_ptr<AST::Pattern>> ()));
     390           24 :       return std::unique_ptr<AST::TuplePattern> (
     391           24 :         new AST::TuplePattern (std::move (items), paren_locus));
     392           24 :     }
     393              : 
     394              :   // parse initial pattern (required)
     395         3001 :   std::unique_ptr<AST::Pattern> initial_pattern = parse_pattern ();
     396         3001 :   if (initial_pattern == nullptr)
     397              :     {
     398            0 :       Error error (lexer.peek_token ()->get_locus (),
     399              :                    "failed to parse pattern in grouped or tuple pattern");
     400            0 :       add_error (std::move (error));
     401              : 
     402            0 :       return nullptr;
     403            0 :     }
     404              : 
     405              :   // branch on whether next token is a comma or not
     406         3001 :   const_TokenPtr t = lexer.peek_token ();
     407         3001 :   switch (t->get_id ())
     408              :     {
     409           48 :     case RIGHT_PAREN:
     410              :       // grouped pattern
     411           48 :       lexer.skip_token ();
     412              : 
     413           48 :       return std::unique_ptr<AST::GroupedPattern> (
     414           48 :         new AST::GroupedPattern (std::move (initial_pattern), paren_locus));
     415         2952 :     case COMMA:
     416              :       {
     417              :         // tuple pattern
     418         2952 :         lexer.skip_token ();
     419              : 
     420              :         // create vector of patterns
     421         2952 :         std::vector<std::unique_ptr<AST::Pattern>> patterns;
     422         2952 :         patterns.push_back (std::move (initial_pattern));
     423              : 
     424         2952 :         t = lexer.peek_token ();
     425         6760 :         while (t->get_id () != RIGHT_PAREN && t->get_id () != DOT_DOT)
     426              :           {
     427              :             // parse pattern (required)
     428         3808 :             std::unique_ptr<AST::Pattern> pattern = parse_pattern ();
     429         3808 :             if (pattern == nullptr)
     430              :               {
     431            0 :                 Error error (t->get_locus (),
     432              :                              "failed to parse pattern in tuple pattern");
     433            0 :                 add_error (std::move (error));
     434              : 
     435            0 :                 return nullptr;
     436            0 :               }
     437         3808 :             patterns.push_back (std::move (pattern));
     438              : 
     439         7616 :             if (lexer.peek_token ()->get_id () != COMMA)
     440              :               break;
     441              : 
     442          954 :             lexer.skip_token ();
     443          954 :             t = lexer.peek_token ();
     444              :           }
     445              : 
     446         2952 :         t = lexer.peek_token ();
     447         2952 :         if (t->get_id () == RIGHT_PAREN)
     448              :           {
     449              :             // non-ranged tuple pattern
     450         2920 :             lexer.skip_token ();
     451              : 
     452         2920 :             std::unique_ptr<AST::TuplePatternItemsNoRest> items (
     453         2920 :               new AST::TuplePatternItemsNoRest (std::move (patterns)));
     454         2920 :             return std::unique_ptr<AST::TuplePattern> (
     455         2920 :               new AST::TuplePattern (std::move (items), paren_locus));
     456         2920 :           }
     457           32 :         else if (t->get_id () == DOT_DOT)
     458              :           {
     459              :             // ranged tuple pattern
     460           32 :             lexer.skip_token ();
     461              : 
     462              :             // parse upper patterns
     463           32 :             std::vector<std::unique_ptr<AST::Pattern>> upper_patterns;
     464           32 :             t = lexer.peek_token ();
     465           68 :             while (t->get_id () == COMMA)
     466              :               {
     467           36 :                 lexer.skip_token ();
     468              : 
     469              :                 // break if end
     470           72 :                 if (lexer.peek_token ()->get_id () == RIGHT_PAREN)
     471              :                   break;
     472              : 
     473              :                 // parse pattern (required)
     474           36 :                 std::unique_ptr<AST::Pattern> pattern = parse_pattern ();
     475           36 :                 if (pattern == nullptr)
     476              :                   {
     477            0 :                     Error error (lexer.peek_token ()->get_locus (),
     478              :                                  "failed to parse pattern in tuple pattern");
     479            0 :                     add_error (std::move (error));
     480              : 
     481            0 :                     return nullptr;
     482            0 :                   }
     483           36 :                 upper_patterns.push_back (std::move (pattern));
     484              : 
     485           36 :                 t = lexer.peek_token ();
     486              :               }
     487              : 
     488           32 :             if (!skip_token (RIGHT_PAREN))
     489              :               {
     490            0 :                 return nullptr;
     491              :               }
     492              : 
     493           32 :             std::unique_ptr<AST::TuplePatternItemsHasRest> items (
     494           32 :               new AST::TuplePatternItemsHasRest (std::move (patterns),
     495              :                                                  std::move (upper_patterns)));
     496           32 :             return std::unique_ptr<AST::TuplePattern> (
     497           32 :               new AST::TuplePattern (std::move (items), paren_locus));
     498           32 :           }
     499              :         else
     500              :           {
     501              :             // some kind of error
     502            0 :             Error error (t->get_locus (),
     503              :                          "failed to parse tuple pattern (probably) or maybe "
     504              :                          "grouped pattern");
     505            0 :             add_error (std::move (error));
     506              : 
     507            0 :             return nullptr;
     508            0 :           }
     509         2952 :       }
     510            1 :     default:
     511              :       // error
     512            1 :       add_error (Error (t->get_locus (),
     513              :                         "unrecognised token %qs in grouped or tuple pattern "
     514              :                         "after first pattern",
     515              :                         t->get_token_description ()));
     516              : 
     517            1 :       return nullptr;
     518              :     }
     519         3001 : }
     520              : 
     521              : /* Parses a slice pattern that can match arrays or slices. Parses the square
     522              :  * brackets too. */
     523              : template <typename ManagedTokenSource>
     524              : std::unique_ptr<AST::SlicePattern>
     525          104 : Parser<ManagedTokenSource>::parse_slice_pattern ()
     526              : {
     527          208 :   location_t square_locus = lexer.peek_token ()->get_locus ();
     528          104 :   std::vector<std::unique_ptr<AST::Pattern>> sub_patterns;
     529              : 
     530          104 :   skip_token (LEFT_SQUARE);
     531              : 
     532          104 :   bool is_first = true;
     533              : 
     534          496 :   while (true)
     535              :     {
     536          352 :       const_TokenPtr t = lexer.peek_token ();
     537              : 
     538          352 :       if (!is_first && t->get_id () == COMMA)
     539              :         {
     540          149 :           skip_token (COMMA);
     541          149 :           t = lexer.peek_token ();
     542              :         }
     543              : 
     544          352 :       if (t->get_id () == RIGHT_SQUARE)
     545              :         {
     546          104 :           skip_token (RIGHT_SQUARE);
     547              :           break;
     548              :         }
     549              : 
     550              :       // parse pattern (required)
     551          248 :       std::unique_ptr<AST::Pattern> pattern = parse_pattern ();
     552          248 :       if (pattern == nullptr)
     553              :         {
     554            0 :           Error error (lexer.peek_token ()->get_locus (),
     555              :                        "failed to parse pattern in slice pattern");
     556            0 :           add_error (std::move (error));
     557              :           // TODO: skip until closing square bracket
     558              : 
     559            0 :           return nullptr;
     560            0 :         }
     561              : 
     562          248 :       sub_patterns.push_back (std::move (pattern));
     563          248 :       is_first = false;
     564              :     }
     565              : 
     566              :   return std::make_unique<AST::SlicePattern> (std::move (sub_patterns),
     567          104 :                                               square_locus);
     568          104 : }
     569              : 
     570              : /* Parses an identifier pattern (pattern that binds a value matched to a
     571              :  * variable). */
     572              : template <typename ManagedTokenSource>
     573              : std::unique_ptr<AST::IdentifierPattern>
     574         2072 : Parser<ManagedTokenSource>::parse_identifier_pattern ()
     575              : {
     576         2072 :   location_t locus = lexer.peek_token ()->get_locus ();
     577              : 
     578         2072 :   bool has_ref = false;
     579         4144 :   if (lexer.peek_token ()->get_id () == REF)
     580              :     {
     581          233 :       has_ref = true;
     582          233 :       lexer.skip_token ();
     583              : 
     584              :       // DEBUG
     585          233 :       rust_debug ("parsed ref in identifier pattern");
     586              :     }
     587              : 
     588         2072 :   bool has_mut = false;
     589         4144 :   if (lexer.peek_token ()->get_id () == MUT)
     590              :     {
     591         1893 :       has_mut = true;
     592         1893 :       lexer.skip_token ();
     593              :     }
     594              : 
     595              :   // parse identifier (required)
     596         2072 :   const_TokenPtr ident_tok = expect_token (IDENTIFIER);
     597         2072 :   if (ident_tok == nullptr)
     598              :     {
     599              :       // skip somewhere?
     600            0 :       return nullptr;
     601              :     }
     602         2072 :   Identifier ident{ident_tok};
     603              : 
     604              :   // DEBUG
     605         2072 :   rust_debug ("parsed identifier in identifier pattern");
     606              : 
     607              :   // parse optional pattern binding thing
     608         2072 :   std::unique_ptr<AST::Pattern> bind_pattern = nullptr;
     609         4144 :   if (lexer.peek_token ()->get_id () == PATTERN_BIND)
     610              :     {
     611            1 :       lexer.skip_token ();
     612              : 
     613              :       // parse required pattern to bind
     614            1 :       bind_pattern = parse_pattern_no_alt ();
     615            1 :       if (bind_pattern == nullptr)
     616              :         {
     617            0 :           Error error (lexer.peek_token ()->get_locus (),
     618              :                        "failed to parse pattern to bind in identifier pattern");
     619            0 :           add_error (std::move (error));
     620              : 
     621            0 :           return nullptr;
     622            0 :         }
     623              :     }
     624              : 
     625              :   // DEBUG
     626         2072 :   rust_debug ("about to return identifier pattern");
     627              : 
     628              :   return std::unique_ptr<AST::IdentifierPattern> (
     629         2072 :     new AST::IdentifierPattern (std::move (ident), locus, has_ref, has_mut,
     630         2072 :                                 std::move (bind_pattern)));
     631         2072 : }
     632              : 
     633              : /* Parses a pattern that opens with an identifier. This includes identifier
     634              :  * patterns, path patterns (and derivatives such as struct patterns, tuple
     635              :  * struct patterns, and macro invocations), and ranges. */
     636              : template <typename ManagedTokenSource>
     637              : std::unique_ptr<AST::Pattern>
     638        52300 : Parser<ManagedTokenSource>::parse_ident_leading_pattern ()
     639              : {
     640              :   // ensure first token is actually identifier
     641        52300 :   const_TokenPtr initial_tok = lexer.peek_token ();
     642        52300 :   if (initial_tok->get_id () != IDENTIFIER)
     643              :     {
     644            0 :       return nullptr;
     645              :     }
     646              : 
     647              :   // save initial identifier as it may be useful (but don't skip)
     648        52300 :   std::string initial_ident = initial_tok->get_str ();
     649              : 
     650              :   // parse next tokens as a PathInExpression
     651        52300 :   AST::PathInExpression path = parse_path_in_expression ();
     652              : 
     653              :   // branch on next token
     654        52300 :   const_TokenPtr t = lexer.peek_token ();
     655        52300 :   switch (t->get_id ())
     656              :     {
     657            4 :     case EXCLAM:
     658            8 :       return parse_macro_invocation_partial (std::move (path), AST::AttrVec ());
     659         1675 :     case LEFT_PAREN:
     660              :       {
     661              :         // tuple struct
     662         1675 :         lexer.skip_token ();
     663              : 
     664              :         // DEBUG
     665         1675 :         rust_debug ("parsing tuple struct pattern");
     666              : 
     667              :         // parse items
     668         1675 :         std::unique_ptr<AST::TupleStructItems> items
     669              :           = parse_tuple_struct_items ();
     670         1675 :         if (items == nullptr)
     671              :           {
     672            1 :             Error error (lexer.peek_token ()->get_locus (),
     673              :                          "failed to parse tuple struct items");
     674            1 :             add_error (std::move (error));
     675              : 
     676            1 :             return nullptr;
     677            1 :           }
     678              : 
     679              :         // DEBUG
     680         1674 :         rust_debug ("successfully parsed tuple struct items");
     681              : 
     682         1674 :         if (!skip_token (RIGHT_PAREN))
     683              :           {
     684            0 :             return nullptr;
     685              :           }
     686              : 
     687              :         // DEBUG
     688         1674 :         rust_debug ("successfully parsed tuple struct pattern");
     689              : 
     690         1674 :         return std::unique_ptr<AST::TupleStructPattern> (
     691         1674 :           new AST::TupleStructPattern (std::move (path), std::move (items)));
     692         1675 :       }
     693          161 :     case LEFT_CURLY:
     694              :       {
     695              :         // struct
     696          161 :         lexer.skip_token ();
     697              : 
     698              :         // parse elements (optional)
     699          161 :         AST::StructPatternElements elems = parse_struct_pattern_elems ();
     700              : 
     701          161 :         if (!skip_token (RIGHT_CURLY))
     702              :           {
     703            0 :             return nullptr;
     704              :           }
     705              : 
     706              :         // DEBUG
     707          161 :         rust_debug ("successfully parsed struct pattern");
     708              : 
     709          161 :         return std::unique_ptr<AST::StructPattern> (
     710          322 :           new AST::StructPattern (std::move (path), initial_tok->get_locus (),
     711          161 :                                   std::move (elems)));
     712          161 :       }
     713            9 :     case DOT_DOT_EQ:
     714              :     case DOT_DOT:
     715              :     case ELLIPSIS:
     716              :       {
     717              :         // range
     718              :         AST::RangeKind kind
     719            9 :           = AST::tokenid_to_rangekind (lexer.peek_token ()->get_id ());
     720              : 
     721            9 :         lexer.skip_token ();
     722              : 
     723            9 :         std::unique_ptr<AST::RangePatternBoundPath> lower_bound (
     724            9 :           new AST::RangePatternBoundPath (std::move (path)));
     725            9 :         std::unique_ptr<AST::RangePatternBound> upper_bound
     726              :           = parse_range_pattern_bound ();
     727              : 
     728            9 :         return std::unique_ptr<AST::RangePattern> (
     729            9 :           new AST::RangePattern (std::move (lower_bound),
     730              :                                  std::move (upper_bound), kind,
     731            9 :                                  t->get_locus ()));
     732            9 :       }
     733           47 :     case PATTERN_BIND:
     734              :       {
     735              :         // only allow on single-segment paths
     736           47 :         if (path.is_single_segment ())
     737              :           {
     738              :             // identifier with pattern bind
     739           47 :             lexer.skip_token ();
     740              : 
     741           47 :             std::unique_ptr<AST::Pattern> bind_pattern
     742              :               = parse_pattern_no_alt ();
     743           47 :             if (bind_pattern == nullptr)
     744              :               {
     745            1 :                 Error error (
     746              :                   t->get_locus (),
     747              :                   "failed to parse pattern to bind to identifier pattern");
     748            1 :                 add_error (std::move (error));
     749              : 
     750            1 :                 return nullptr;
     751            1 :               }
     752           46 :             return std::unique_ptr<AST::IdentifierPattern> (
     753          138 :               new AST::IdentifierPattern (std::move (initial_ident),
     754              :                                           initial_tok->get_locus (), false,
     755           46 :                                           false, std::move (bind_pattern)));
     756           47 :           }
     757            0 :         Error error (
     758              :           t->get_locus (),
     759              :           "failed to parse pattern bind to a path, not an identifier");
     760            0 :         add_error (std::move (error));
     761              : 
     762            0 :         return nullptr;
     763            0 :       }
     764        50404 :     default:
     765              :       // assume identifier if single segment
     766        50404 :       if (path.is_single_segment ())
     767              :         {
     768        49288 :           return std::unique_ptr<AST::IdentifierPattern> (
     769       147864 :             new AST::IdentifierPattern (std::move (initial_ident),
     770        49288 :                                         initial_tok->get_locus ()));
     771              :         }
     772              :       // return path otherwise
     773         1116 :       return std::unique_ptr<AST::PathInExpression> (
     774         1116 :         new AST::PathInExpression (std::move (path)));
     775              :     }
     776        52300 : }
     777              : 
     778              : // Parses struct pattern elements if they exist.
     779              : template <typename ManagedTokenSource>
     780              : AST::StructPatternElements
     781          162 : Parser<ManagedTokenSource>::parse_struct_pattern_elems ()
     782              : {
     783          162 :   std::vector<std::unique_ptr<AST::StructPatternField>> fields;
     784              : 
     785          162 :   AST::AttrVec etc_attrs;
     786          162 :   bool has_rest = false;
     787              : 
     788              :   // try parsing struct pattern fields
     789          162 :   const_TokenPtr t = lexer.peek_token ();
     790          520 :   while (t->get_id () != RIGHT_CURLY)
     791              :     {
     792          253 :       AST::AttrVec outer_attrs = parse_outer_attributes ();
     793              : 
     794              :       // parse etc (must be last in struct pattern, so breaks)
     795          506 :       if (lexer.peek_token ()->get_id () == DOT_DOT)
     796              :         {
     797            6 :           lexer.skip_token ();
     798            6 :           etc_attrs = std::move (outer_attrs);
     799            6 :           has_rest = true;
     800            6 :           break;
     801              :         }
     802              : 
     803          247 :       std::unique_ptr<AST::StructPatternField> field
     804          247 :         = parse_struct_pattern_field_partial (std::move (outer_attrs));
     805          247 :       if (field == nullptr)
     806              :         {
     807            0 :           Error error (lexer.peek_token ()->get_locus (),
     808              :                        "failed to parse struct pattern field");
     809            0 :           add_error (std::move (error));
     810              : 
     811              :           // skip after somewhere?
     812            0 :           return AST::StructPatternElements::create_empty ();
     813            0 :         }
     814          247 :       fields.push_back (std::move (field));
     815              : 
     816          494 :       if (lexer.peek_token ()->get_id () != COMMA)
     817              :         break;
     818              : 
     819              :       // skip comma
     820          105 :       lexer.skip_token ();
     821          105 :       t = lexer.peek_token ();
     822              :     }
     823              : 
     824          162 :   if (has_rest)
     825            6 :     return AST::StructPatternElements (std::move (fields),
     826            6 :                                        std::move (etc_attrs));
     827              :   else
     828          156 :     return AST::StructPatternElements (std::move (fields));
     829          162 : }
     830              : 
     831              : /* Parses a struct pattern field (tuple index/pattern, identifier/pattern, or
     832              :  * identifier). */
     833              : template <typename ManagedTokenSource>
     834              : std::unique_ptr<AST::StructPatternField>
     835            0 : Parser<ManagedTokenSource>::parse_struct_pattern_field ()
     836              : {
     837              :   // parse outer attributes (if they exist)
     838            0 :   AST::AttrVec outer_attrs = parse_outer_attributes ();
     839              : 
     840            0 :   return parse_struct_pattern_field_partial (std::move (outer_attrs));
     841            0 : }
     842              : 
     843              : /* Parses a struct pattern field (tuple index/pattern, identifier/pattern, or
     844              :  * identifier), with outer attributes passed in. */
     845              : template <typename ManagedTokenSource>
     846              : std::unique_ptr<AST::StructPatternField>
     847          247 : Parser<ManagedTokenSource>::parse_struct_pattern_field_partial (
     848              :   AST::AttrVec outer_attrs)
     849              : {
     850              :   // branch based on next token
     851          247 :   const_TokenPtr t = lexer.peek_token ();
     852          247 :   switch (t->get_id ())
     853              :     {
     854           26 :     case INT_LITERAL:
     855              :       {
     856              :         // tuple index
     857           52 :         std::string index_str = t->get_str ();
     858           26 :         int index = atoi (index_str.c_str ());
     859              : 
     860           26 :         lexer.skip_token ();
     861              : 
     862           26 :         if (!skip_token (COLON))
     863              :           {
     864            0 :             return nullptr;
     865              :           }
     866              : 
     867              :         // parse required pattern
     868           26 :         std::unique_ptr<AST::Pattern> pattern = parse_pattern ();
     869           26 :         if (pattern == nullptr)
     870              :           {
     871            0 :             Error error (
     872              :               t->get_locus (),
     873              :               "failed to parse pattern in tuple index struct pattern field");
     874            0 :             add_error (std::move (error));
     875              : 
     876            0 :             return nullptr;
     877            0 :           }
     878              : 
     879           26 :         return std::unique_ptr<AST::StructPatternFieldTuplePat> (
     880           26 :           new AST::StructPatternFieldTuplePat (index, std::move (pattern),
     881              :                                                std::move (outer_attrs),
     882           26 :                                                t->get_locus ()));
     883           52 :       }
     884          219 :     case IDENTIFIER:
     885              :       // identifier-pattern OR only identifier
     886              :       // branch on next token
     887          438 :       switch (lexer.peek_token (1)->get_id ())
     888              :         {
     889          115 :         case COLON:
     890              :           {
     891              :             // identifier-pattern
     892          115 :             Identifier ident{t};
     893          115 :             lexer.skip_token ();
     894              : 
     895          115 :             skip_token (COLON);
     896              : 
     897              :             // parse required pattern
     898          115 :             std::unique_ptr<AST::Pattern> pattern = parse_pattern ();
     899          115 :             if (pattern == nullptr)
     900              :               {
     901            0 :                 Error error (t->get_locus (),
     902              :                              "failed to parse pattern in struct pattern field");
     903            0 :                 add_error (std::move (error));
     904              : 
     905            0 :                 return nullptr;
     906            0 :               }
     907              : 
     908          115 :             return std::unique_ptr<AST::StructPatternFieldIdentPat> (
     909          230 :               new AST::StructPatternFieldIdentPat (std::move (ident),
     910              :                                                    std::move (pattern),
     911              :                                                    std::move (outer_attrs),
     912          115 :                                                    t->get_locus ()));
     913          115 :           }
     914          104 :         case COMMA:
     915              :         case RIGHT_CURLY:
     916              :           {
     917              :             // identifier only
     918          104 :             Identifier ident = {t};
     919          104 :             lexer.skip_token ();
     920              : 
     921          104 :             return std::unique_ptr<AST::StructPatternFieldIdent> (
     922          208 :               new AST::StructPatternFieldIdent (std::move (ident), false, false,
     923              :                                                 std::move (outer_attrs),
     924          104 :                                                 t->get_locus ()));
     925          104 :           }
     926            0 :         default:
     927              :           // error
     928            0 :           add_error (Error (t->get_locus (),
     929              :                             "unrecognised token %qs in struct pattern field",
     930              :                             t->get_token_description ()));
     931              : 
     932            0 :           return nullptr;
     933              :         }
     934            2 :     case REF:
     935              :     case MUT:
     936              :       {
     937              :         // only identifier
     938            2 :         bool has_ref = false;
     939            2 :         if (t->get_id () == REF)
     940              :           {
     941            0 :             has_ref = true;
     942            0 :             lexer.skip_token ();
     943              :           }
     944              : 
     945            2 :         bool has_mut = false;
     946            4 :         if (lexer.peek_token ()->get_id () == MUT)
     947              :           {
     948            2 :             has_mut = true;
     949            2 :             lexer.skip_token ();
     950              :           }
     951              : 
     952            2 :         const_TokenPtr ident_tok = expect_token (IDENTIFIER);
     953            2 :         if (ident_tok == nullptr)
     954              :           {
     955            0 :             return nullptr;
     956              :           }
     957            2 :         Identifier ident{ident_tok};
     958              : 
     959            2 :         return std::unique_ptr<AST::StructPatternFieldIdent> (
     960            4 :           new AST::StructPatternFieldIdent (std::move (ident), has_ref, has_mut,
     961              :                                             std::move (outer_attrs),
     962            2 :                                             t->get_locus ()));
     963            4 :       }
     964            0 :     default:
     965              :       // not necessarily an error
     966            0 :       return nullptr;
     967              :     }
     968          247 : }
     969              : 
     970              : /* Parses a literal pattern or range pattern. Assumes that literals passed in
     971              :  * are valid range pattern bounds. Do not pass in paths in expressions, for
     972              :  * instance. */
     973              : template <typename ManagedTokenSource>
     974              : std::unique_ptr<AST::Pattern>
     975        45673 : Parser<ManagedTokenSource>::parse_literal_or_range_pattern ()
     976              : {
     977        45673 :   const_TokenPtr range_lower = lexer.peek_token ();
     978        45673 :   AST::Literal::LitType type = AST::Literal::STRING;
     979        45673 :   bool has_minus = false;
     980              : 
     981              :   // get lit type
     982        45673 :   switch (range_lower->get_id ())
     983              :     {
     984           98 :     case CHAR_LITERAL:
     985           98 :       type = AST::Literal::CHAR;
     986           98 :       lexer.skip_token ();
     987              :       break;
     988           87 :     case BYTE_CHAR_LITERAL:
     989           87 :       type = AST::Literal::BYTE;
     990           87 :       lexer.skip_token ();
     991              :       break;
     992        45459 :     case INT_LITERAL:
     993        45459 :       type = AST::Literal::INT;
     994        45459 :       lexer.skip_token ();
     995              :       break;
     996            2 :     case FLOAT_LITERAL:
     997            2 :       type = AST::Literal::FLOAT;
     998            2 :       lexer.skip_token ();
     999              :       break;
    1000           27 :     case MINUS:
    1001              :       // branch on next token
    1002           27 :       range_lower = lexer.peek_token (1);
    1003           27 :       switch (range_lower->get_id ())
    1004              :         {
    1005           25 :         case INT_LITERAL:
    1006           25 :           type = AST::Literal::INT;
    1007           25 :           has_minus = true;
    1008           25 :           lexer.skip_token (1);
    1009           25 :           break;
    1010            2 :         case FLOAT_LITERAL:
    1011            2 :           type = AST::Literal::FLOAT;
    1012            2 :           has_minus = true;
    1013            2 :           lexer.skip_token (1);
    1014            2 :           break;
    1015            0 :         default:
    1016            0 :           add_error (Error (range_lower->get_locus (),
    1017              :                             "token type %qs cannot be parsed as range pattern "
    1018              :                             "bound or literal after minus symbol",
    1019              :                             range_lower->get_token_description ()));
    1020              : 
    1021            0 :           return nullptr;
    1022              :         }
    1023              :       break;
    1024            0 :     default:
    1025            0 :       add_error (
    1026            0 :         Error (range_lower->get_locus (),
    1027              :                "token type %qs cannot be parsed as range pattern bound",
    1028              :                range_lower->get_token_description ()));
    1029              : 
    1030            0 :       return nullptr;
    1031              :     }
    1032              : 
    1033        45673 :   std::string literal_value;
    1034        45673 :   if (range_lower->get_id () == INT_LITERAL)
    1035        90968 :     literal_value = LiteralResolve::evaluate_integer_literal (range_lower);
    1036          189 :   else if (range_lower->get_id () == FLOAT_LITERAL)
    1037            8 :     literal_value = LiteralResolve::evaluate_float_literal (range_lower);
    1038              :   else
    1039          185 :     literal_value = range_lower->get_str ();
    1040              : 
    1041        45673 :   const_TokenPtr next = lexer.peek_token ();
    1042        45673 :   if (next->get_id () == DOT_DOT_EQ || next->get_id () == ELLIPSIS
    1043        91205 :       || next->get_id () == DOT_DOT)
    1044              :     {
    1045          168 :       AST::RangeKind kind = AST::tokenid_to_rangekind (next->get_id ());
    1046              :       // range pattern
    1047          168 :       lexer.skip_token ();
    1048          168 :       std::unique_ptr<AST::RangePatternBound> lower (
    1049          336 :         new AST::RangePatternBoundLiteral (
    1050          336 :           AST::Literal (std::move (literal_value), type,
    1051              :                         PrimitiveCoreType::CORETYPE_UNKNOWN),
    1052              :           range_lower->get_locus (), has_minus));
    1053              : 
    1054          168 :       std::unique_ptr<AST::RangePatternBound> upper
    1055              :         = parse_range_pattern_bound ();
    1056          168 :       if (upper == nullptr)
    1057              :         {
    1058            1 :           Error error (next->get_locus (),
    1059              :                        "failed to parse range pattern bound in range pattern");
    1060            1 :           add_error (std::move (error));
    1061              : 
    1062            1 :           return nullptr;
    1063            1 :         }
    1064              : 
    1065          167 :       return std::unique_ptr<AST::RangePattern> (
    1066          167 :         new AST::RangePattern (std::move (lower), std::move (upper), kind,
    1067          167 :                                range_lower->get_locus ()));
    1068          168 :     }
    1069              :   else
    1070              :     {
    1071              :       // literal pattern
    1072              : 
    1073        45505 :       auto type_hint = (range_lower->get_id () == INT_LITERAL
    1074          100 :                         || range_lower->get_id () == FLOAT_LITERAL)
    1075       136319 :                          ? LiteralResolve::resolve_literal_suffix (range_lower)
    1076           98 :                          : range_lower->get_type_hint ();
    1077              : 
    1078        45505 :       return std::unique_ptr<AST::LiteralPattern> (
    1079        91010 :         new AST::LiteralPattern (std::move (literal_value), type,
    1080              :                                  range_lower->get_locus (), type_hint,
    1081        45505 :                                  has_minus));
    1082              :     }
    1083        45673 : }
    1084              : 
    1085              : // Parses a range pattern bound (value only).
    1086              : template <typename ManagedTokenSource>
    1087              : std::unique_ptr<AST::RangePatternBound>
    1088          177 : Parser<ManagedTokenSource>::parse_range_pattern_bound ()
    1089              : {
    1090          177 :   const_TokenPtr range_lower = lexer.peek_token ();
    1091          177 :   location_t range_lower_locus = range_lower->get_locus ();
    1092              : 
    1093              :   // get lit type
    1094          177 :   switch (range_lower->get_id ())
    1095              :     {
    1096           52 :     case CHAR_LITERAL:
    1097           52 :       lexer.skip_token ();
    1098           52 :       return std::unique_ptr<AST::RangePatternBoundLiteral> (
    1099          104 :         new AST::RangePatternBoundLiteral (
    1100          208 :           AST::Literal (range_lower->get_str (), AST::Literal::CHAR,
    1101              :                         range_lower->get_type_hint ()),
    1102           52 :           range_lower_locus));
    1103           35 :     case BYTE_CHAR_LITERAL:
    1104           35 :       lexer.skip_token ();
    1105           35 :       return std::unique_ptr<AST::RangePatternBoundLiteral> (
    1106           70 :         new AST::RangePatternBoundLiteral (
    1107          140 :           AST::Literal (range_lower->get_str (), AST::Literal::BYTE,
    1108              :                         range_lower->get_type_hint ()),
    1109           35 :           range_lower_locus));
    1110           61 :     case INT_LITERAL:
    1111           61 :       lexer.skip_token ();
    1112           61 :       return std::unique_ptr<AST::RangePatternBoundLiteral> (
    1113          122 :         new AST::RangePatternBoundLiteral (
    1114          244 :           AST::Literal (LiteralResolve::evaluate_integer_literal (range_lower),
    1115              :                         AST::Literal::INT,
    1116          122 :                         LiteralResolve::resolve_literal_suffix (range_lower)),
    1117           61 :           range_lower_locus));
    1118            0 :     case FLOAT_LITERAL:
    1119            0 :       lexer.skip_token ();
    1120            0 :       rust_debug ("warning: used deprecated float range pattern bound");
    1121            0 :       return std::unique_ptr<AST::RangePatternBoundLiteral> (
    1122            0 :         new AST::RangePatternBoundLiteral (
    1123            0 :           AST::Literal (LiteralResolve::evaluate_float_literal (range_lower),
    1124              :                         AST::Literal::FLOAT,
    1125            0 :                         LiteralResolve::resolve_literal_suffix (range_lower)),
    1126            0 :           range_lower_locus));
    1127           12 :     case MINUS:
    1128              :       // branch on next token
    1129           12 :       range_lower = lexer.peek_token (1);
    1130           12 :       switch (range_lower->get_id ())
    1131              :         {
    1132           10 :         case INT_LITERAL:
    1133           10 :           lexer.skip_token (1);
    1134           10 :           return std::unique_ptr<AST::RangePatternBoundLiteral> (
    1135           20 :             new AST::RangePatternBoundLiteral (
    1136           30 :               AST::Literal (
    1137           30 :                 LiteralResolve::evaluate_integer_literal (range_lower),
    1138              :                 AST::Literal::INT,
    1139           20 :                 LiteralResolve::resolve_literal_suffix (range_lower)),
    1140           10 :               range_lower_locus, true));
    1141            2 :         case FLOAT_LITERAL:
    1142            2 :           lexer.skip_token (1);
    1143            2 :           rust_debug ("warning: used deprecated float range pattern bound");
    1144            2 :           return std::unique_ptr<AST::RangePatternBoundLiteral> (
    1145            4 :             new AST::RangePatternBoundLiteral (
    1146            6 :               AST::Literal (
    1147            6 :                 LiteralResolve::evaluate_float_literal (range_lower),
    1148              :                 AST::Literal::FLOAT,
    1149            4 :                 LiteralResolve::resolve_literal_suffix (range_lower)),
    1150            2 :               range_lower_locus, true));
    1151            0 :         default:
    1152            0 :           add_error (Error (range_lower->get_locus (),
    1153              :                             "token type %qs cannot be parsed as range pattern "
    1154              :                             "bound after minus symbol",
    1155              :                             range_lower->get_token_description ()));
    1156              : 
    1157            0 :           return nullptr;
    1158              :         }
    1159           15 :     case IDENTIFIER:
    1160              :     case SUPER:
    1161              :     case SELF:
    1162              :     case SELF_ALIAS:
    1163              :     case CRATE:
    1164              :     case SCOPE_RESOLUTION:
    1165              :     case DOLLAR_SIGN:
    1166              :       {
    1167              :         // path in expression
    1168           15 :         AST::PathInExpression path = parse_path_in_expression ();
    1169           15 :         if (path.is_error ())
    1170              :           {
    1171            0 :             Error error (
    1172              :               range_lower->get_locus (),
    1173              :               "failed to parse path in expression range pattern bound");
    1174            0 :             add_error (std::move (error));
    1175              : 
    1176            0 :             return nullptr;
    1177            0 :           }
    1178           15 :         return std::unique_ptr<AST::RangePatternBoundPath> (
    1179           15 :           new AST::RangePatternBoundPath (std::move (path)));
    1180           15 :       }
    1181            0 :     case LEFT_SHIFT:
    1182              :     case LEFT_ANGLE:
    1183              :       {
    1184              :         // qualified path in expression
    1185            0 :         AST::QualifiedPathInExpression path
    1186              :           = parse_qualified_path_in_expression ();
    1187            0 :         if (path.is_error ())
    1188              :           {
    1189            0 :             Error error (range_lower->get_locus (),
    1190              :                          "failed to parse qualified path in expression range "
    1191              :                          "pattern bound");
    1192            0 :             add_error (std::move (error));
    1193              : 
    1194            0 :             return nullptr;
    1195            0 :           }
    1196            0 :         return std::unique_ptr<AST::RangePatternBoundQualPath> (
    1197            0 :           new AST::RangePatternBoundQualPath (std::move (path)));
    1198            0 :       }
    1199            2 :     default:
    1200            2 :       add_error (
    1201            2 :         Error (range_lower->get_locus (),
    1202              :                "token type %qs cannot be parsed as range pattern bound",
    1203              :                range_lower->get_token_description ()));
    1204              : 
    1205            2 :       return nullptr;
    1206              :     }
    1207          177 : }
    1208              : 
    1209              : } // namespace Rust
        

Generated by: LCOV version 2.4-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.