[COMMITTED 071/145] gccrs: Parse exclusive range pattern

arthur.cohen@embecosm.com arthur.cohen@embecosm.com
Mon Mar 17 15:32:29 GMT 2025


From: Pierre-Emmanuel Patry <pierre-emmanuel.patry@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.patry@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



More information about the Gcc-rust mailing list