From: Pierre-Emmanuel Patry <pierre-emmanuel.pa...@embecosm.com>

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.pa...@embecosm.com>
---
 gcc/rust/ast/rust-pattern.cc           | 31 ++++++++++++++++++++----
 gcc/rust/ast/rust-pattern.h            | 32 ++++++++++++++++++-------
 gcc/rust/hir/rust-ast-lower-pattern.cc |  3 +++
 gcc/rust/parse/rust-parse-impl.h       | 33 +++++++++++++++-----------
 4 files changed, 72 insertions(+), 27 deletions(-)

diff --git a/gcc/rust/ast/rust-pattern.cc b/gcc/rust/ast/rust-pattern.cc
index 85b3f5f3f51..98fd8e52f5f 100644
--- a/gcc/rust/ast/rust-pattern.cc
+++ b/gcc/rust/ast/rust-pattern.cc
@@ -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
diff --git a/gcc/rust/ast/rust-pattern.h b/gcc/rust/ast/rust-pattern.h
index 7cb09a5c2ab..383a5ee40a7 100644
--- a/gcc/rust/ast/rust-pattern.h
+++ b/gcc/rust/ast/rust-pattern.h
@@ -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;
 
diff --git a/gcc/rust/hir/rust-ast-lower-pattern.cc 
b/gcc/rust/hir/rust-ast-lower-pattern.cc
index b64cf3ae069..b7a4c564782 100644
--- a/gcc/rust/hir/rust-ast-lower-pattern.cc
+++ b/gcc/rust/hir/rust-ast-lower-pattern.cc
@@ -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 ());
 
diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index 91f09f64fe3..cabfb5bf5e2 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -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
-- 
2.45.2

Reply via email to