]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
gccrs: Parse exclusive range pattern
authorPierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
Tue, 21 May 2024 15:45:34 +0000 (17:45 +0200)
committerArthur Cohen <arthur.cohen@embecosm.com>
Mon, 17 Mar 2025 15:35:34 +0000 (16:35 +0100)
Exclusive range pattern were not handled by the parser as this an
experimental feature.

gcc/rust/ChangeLog:

* ast/rust-pattern.cc (tokenid_to_rangekind): Add a new function to
get a range kind from the current token type.
(RangePattern::as_string): Change the string representation for range
pattern in order to handle excluded ranges.
* ast/rust-pattern.h (enum class): Add new enum class to differentiate
range kinds.
(tokenid_to_rangekind): New prototype for a function that converts a
token id to it's corresponding range kind.
(class RangePattern): Change the class to accept a range kind instead
of an ellipsis boolean.
* hir/rust-ast-lower-pattern.cc (ASTLoweringPattern::visit): Abort
when an excluded pattern has been found as we do not handle their
lowering yet.
* parse/rust-parse-impl.h (Parser::parse_literal_or_range_pattern):
Parse excluded range patterns.
(Parser::parse_pattern_no_alt): Likewise.
(Parser::parse_ident_leading_pattern): Likewise.

Signed-off-by: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
gcc/rust/ast/rust-pattern.cc
gcc/rust/ast/rust-pattern.h
gcc/rust/hir/rust-ast-lower-pattern.cc
gcc/rust/parse/rust-parse-impl.h

index 85b3f5f3f5162da54b4cbd32772626b14dd93a06..98fd8e52f5fab7cd30cacf264ebde6c02b5e20ff 100644 (file)
@@ -30,6 +30,22 @@ along with GCC; see the file COPYING3.  If not see
 namespace Rust {
 namespace AST {
 
+RangeKind
+tokenid_to_rangekind (TokenId id)
+{
+  switch (id)
+    {
+    case DOT_DOT_EQ:
+      return RangeKind::INCLUDED;
+    case ELLIPSIS:
+      return RangeKind::ELLIPSIS;
+    case DOT_DOT:
+      return RangeKind::EXCLUDED;
+    default:
+      rust_unreachable ();
+    }
+}
+
 std::string
 LiteralPattern::as_string () const
 {
@@ -73,10 +89,17 @@ std::string
 RangePattern::as_string () const
 {
   // TODO: maybe rewrite to work with non-linearisable bounds
-  if (has_ellipsis_syntax)
-    return lower->as_string () + "..." + upper->as_string ();
-  else
-    return lower->as_string () + "..=" + upper->as_string ();
+  switch (range_kind)
+    {
+    case RangeKind::EXCLUDED:
+      return lower->as_string () + ".." + upper->as_string ();
+    case RangeKind::INCLUDED:
+      return lower->as_string () + "..=" + upper->as_string ();
+    case RangeKind::ELLIPSIS:
+      return lower->as_string () + "..." + upper->as_string ();
+    default:
+      rust_unreachable ();
+    }
 }
 
 std::string
index 7cb09a5c2abe2a13104d0225b6195bb3f40cce3c..383a5ee40a7cbd8eb2fc6b9633d6a0542ca5fd5b 100644 (file)
@@ -368,13 +368,22 @@ protected:
   }
 };
 
+enum class RangeKind
+{
+  INCLUDED,
+  ELLIPSIS,
+  EXCLUDED,
+};
+
+RangeKind
+tokenid_to_rangekind (TokenId id);
 // AST node for matching within a certain range (range pattern)
 class RangePattern : public Pattern
 {
   std::unique_ptr<RangePatternBound> lower;
   std::unique_ptr<RangePatternBound> upper;
 
-  bool has_ellipsis_syntax;
+  RangeKind range_kind;
 
   /* location only stored to avoid a dereference - lower pattern should give
    * correct location so maybe change in future */
@@ -386,10 +395,10 @@ public:
 
   // Constructor
   RangePattern (std::unique_ptr<RangePatternBound> lower,
-               std::unique_ptr<RangePatternBound> upper, location_t locus,
-               bool has_ellipsis_syntax = false)
+               std::unique_ptr<RangePatternBound> upper, RangeKind range_kind,
+               location_t locus)
     : lower (std::move (lower)), upper (std::move (upper)),
-      has_ellipsis_syntax (has_ellipsis_syntax), locus (locus),
+      range_kind (range_kind), locus (locus),
       node_id (Analysis::Mappings::get ().get_next_node_id ())
   {}
 
@@ -397,7 +406,7 @@ public:
   RangePattern (RangePattern const &other)
     : lower (other.lower->clone_range_pattern_bound ()),
       upper (other.upper->clone_range_pattern_bound ()),
-      has_ellipsis_syntax (other.has_ellipsis_syntax), locus (other.locus),
+      range_kind (other.range_kind), locus (other.locus),
       node_id (other.node_id)
   {}
 
@@ -406,7 +415,7 @@ public:
   {
     lower = other.lower->clone_range_pattern_bound ();
     upper = other.upper->clone_range_pattern_bound ();
-    has_ellipsis_syntax = other.has_ellipsis_syntax;
+    range_kind = other.range_kind;
     locus = other.locus;
     node_id = other.node_id;
 
@@ -419,11 +428,16 @@ public:
 
   location_t get_locus () const override final { return locus; }
 
-  bool get_has_ellipsis_syntax () { return has_ellipsis_syntax; }
+  bool get_has_ellipsis_syntax () const
+  {
+    return range_kind == RangeKind::ELLIPSIS;
+  }
+
+  RangeKind get_range_kind () const { return range_kind; }
 
-  bool get_has_lower_bound () { return lower != nullptr; }
+  bool get_has_lower_bound () const { return lower != nullptr; }
 
-  bool get_has_upper_bound () { return upper != nullptr; }
+  bool get_has_upper_bound () const { return upper != nullptr; }
 
   void accept_vis (ASTVisitor &vis) override;
 
index b64cf3ae069872d9c25d15ff8117c942fe0b4ab5..b7a4c564782b1f32285d2f105bde4fe490461c11 100644 (file)
@@ -18,6 +18,7 @@
 
 #include "rust-ast-lower-pattern.h"
 #include "rust-ast-lower-expr.h"
+#include "rust-system.h"
 
 namespace Rust {
 namespace HIR {
@@ -253,6 +254,8 @@ ASTLoweringPattern::visit (AST::LiteralPattern &pattern)
 void
 ASTLoweringPattern::visit (AST::RangePattern &pattern)
 {
+  if (pattern.get_range_kind () == AST::RangeKind::EXCLUDED)
+    rust_unreachable (); // Not supported yet
   auto upper_bound = lower_range_pattern_bound (pattern.get_upper_bound ());
   auto lower_bound = lower_range_pattern_bound (pattern.get_lower_bound ());
 
index 91f09f64fe3b3b3533e63c0052dde752d7c1e8a1..cabfb5bf5e20153dbbeace63b9324505ca48d4cb 100644 (file)
@@ -10261,8 +10261,10 @@ Parser<ManagedTokenSource>::parse_literal_or_range_pattern ()
     }
 
   const_TokenPtr next = lexer.peek_token ();
-  if (next->get_id () == DOT_DOT_EQ || next->get_id () == ELLIPSIS)
+  if (next->get_id () == DOT_DOT_EQ || next->get_id () == ELLIPSIS
+      || next->get_id () == DOT_DOT)
     {
+      AST::RangeKind kind = AST::tokenid_to_rangekind (next->get_id ());
       // range pattern
       lexer.skip_token ();
       std::unique_ptr<AST::RangePatternBound> lower (
@@ -10283,7 +10285,7 @@ Parser<ManagedTokenSource>::parse_literal_or_range_pattern ()
        }
 
       return std::unique_ptr<AST::RangePattern> (
-       new AST::RangePattern (std::move (lower), std::move (upper),
+       new AST::RangePattern (std::move (lower), std::move (upper), kind,
                               range_lower->get_locus ()));
     }
   else
@@ -10532,11 +10534,12 @@ Parser<ManagedTokenSource>::parse_pattern_no_alt ()
          = parse_qualified_path_in_expression ();
 
        if (lexer.peek_token ()->get_id () == DOT_DOT_EQ
-           || lexer.peek_token ()->get_id () == ELLIPSIS)
+           || lexer.peek_token ()->get_id () == ELLIPSIS
+           || lexer.peek_token ()->get_id () == DOT_DOT)
          {
            // qualified range pattern bound, so parse rest of range pattern
-           bool has_ellipsis_syntax
-             = lexer.peek_token ()->get_id () == ELLIPSIS;
+           AST::RangeKind kind
+             = AST::tokenid_to_rangekind (lexer.peek_token ()->get_id ());
            lexer.skip_token ();
 
            std::unique_ptr<AST::RangePatternBoundQualPath> lower_bound (
@@ -10546,8 +10549,8 @@ Parser<ManagedTokenSource>::parse_pattern_no_alt ()
 
            return std::unique_ptr<AST::RangePattern> (
              new AST::RangePattern (std::move (lower_bound),
-                                    std::move (upper_bound), t->get_locus (),
-                                    has_ellipsis_syntax));
+                                    std::move (upper_bound), kind,
+                                    t->get_locus ()));
          }
        else
          {
@@ -10569,10 +10572,10 @@ Parser<ManagedTokenSource>::parse_pattern_no_alt ()
        switch (next->get_id ())
          {
          case DOT_DOT_EQ:
+         case DOT_DOT:
            case ELLIPSIS: {
              // qualified range pattern bound, so parse rest of range pattern
-             bool has_ellipsis_syntax
-               = lexer.peek_token ()->get_id () == ELLIPSIS;
+             AST::RangeKind kind = AST::tokenid_to_rangekind (next->get_id ());
              lexer.skip_token ();
 
              std::unique_ptr<AST::RangePatternBoundPath> lower_bound (
@@ -10582,8 +10585,8 @@ Parser<ManagedTokenSource>::parse_pattern_no_alt ()
 
              return std::unique_ptr<AST::RangePattern> (
                new AST::RangePattern (std::move (lower_bound),
-                                      std::move (upper_bound),
-                                      UNKNOWN_LOCATION, has_ellipsis_syntax));
+                                      std::move (upper_bound), kind,
+                                      UNKNOWN_LOCATION));
            }
          case EXCLAM:
            return parse_macro_invocation_partial (std::move (path),
@@ -11093,9 +11096,11 @@ Parser<ManagedTokenSource>::parse_ident_leading_pattern ()
                                  std::move (elems)));
       }
     case DOT_DOT_EQ:
+    case DOT_DOT:
       case ELLIPSIS: {
        // range
-       bool has_ellipsis_syntax = lexer.peek_token ()->get_id () == ELLIPSIS;
+       AST::RangeKind kind
+         = AST::tokenid_to_rangekind (lexer.peek_token ()->get_id ());
 
        lexer.skip_token ();
 
@@ -11106,8 +11111,8 @@ Parser<ManagedTokenSource>::parse_ident_leading_pattern ()
 
        return std::unique_ptr<AST::RangePattern> (
          new AST::RangePattern (std::move (lower_bound),
-                                std::move (upper_bound), UNKNOWN_LOCATION,
-                                has_ellipsis_syntax));
+                                std::move (upper_bound), kind,
+                                UNKNOWN_LOCATION));
       }
       case PATTERN_BIND: {
        // only allow on single-segment paths