You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by pa...@apache.org on 2021/04/12 06:04:07 UTC

[groovy] 01/26: GROOVY-9649: - Added left and full exclusive patterns to parser - Added exclusiveLeft and exclusiveRight class variables to RangeExpression

This is an automated email from the ASF dual-hosted git repository.

paulk pushed a commit to branch groovy9649
in repository https://gitbox.apache.org/repos/asf/groovy.git

commit 6e832879bbd44cde60cb5223b36d44cba7cf40ac
Author: Iiro Kiviluoma <ii...@outlook.com>
AuthorDate: Wed Mar 24 15:10:17 2021 +0200

    GROOVY-9649: - Added left and full exclusive patterns to parser - Added exclusiveLeft and exclusiveRight class variables to RangeExpression
---
 src/antlr/GroovyLexer.g4                           | 36 ++++++++++++----------
 src/antlr/GroovyParser.g4                          |  4 ++-
 .../apache/groovy/parser/antlr4/AstBuilder.java    |  2 +-
 .../codehaus/groovy/ast/expr/RangeExpression.java  | 36 +++++++++++++++++++---
 .../completion/antlr4/ReflectionCompleter.groovy   |  8 +++--
 5 files changed, 60 insertions(+), 26 deletions(-)

diff --git a/src/antlr/GroovyLexer.g4 b/src/antlr/GroovyLexer.g4
index 6989d6d..147e126 100644
--- a/src/antlr/GroovyLexer.g4
+++ b/src/antlr/GroovyLexer.g4
@@ -808,23 +808,25 @@ NullLiteral
 
 // Groovy Operators
 
-RANGE_INCLUSIVE     : '..';
-RANGE_EXCLUSIVE     : '..<';
-SPREAD_DOT          : '*.';
-SAFE_DOT            : '?.';
-SAFE_INDEX          : '?[';
-SAFE_CHAIN_DOT      : '??.';
-ELVIS               : '?:';
-METHOD_POINTER      : '.&';
-METHOD_REFERENCE    : '::';
-REGEX_FIND          : '=~';
-REGEX_MATCH         : '==~';
-POWER               : '**';
-POWER_ASSIGN        : '**=';
-SPACESHIP           : '<=>';
-IDENTICAL           : '===';
-NOT_IDENTICAL       : '!==';
-ARROW               : '->';
+RANGE_INCLUSIVE         : '..';
+RANGE_EXCLUSIVE_LEFT    : '<..';
+RANGE_EXCLUSIVE_RIGHT   : '..<';
+RANGE_EXCLUSIVE_FULL    : '<..<';
+SPREAD_DOT              : '*.';
+SAFE_DOT                : '?.';
+SAFE_INDEX              : '?[';
+SAFE_CHAIN_DOT          : '??.';
+ELVIS                   : '?:';
+METHOD_POINTER          : '.&';
+METHOD_REFERENCE        : '::';
+REGEX_FIND              : '=~';
+REGEX_MATCH             : '==~';
+POWER                   : '**';
+POWER_ASSIGN            : '**=';
+SPACESHIP               : '<=>';
+IDENTICAL               : '===';
+NOT_IDENTICAL           : '!==';
+ARROW                   : '->';
 
 // !internalPromise will be parsed as !in ternalPromise, so semantic predicates are necessary
 NOT_INSTANCEOF      : '!instanceof' { isFollowedBy(_input, ' ', '\t', '\r', '\n') }?;
diff --git a/src/antlr/GroovyParser.g4 b/src/antlr/GroovyParser.g4
index 39797da..5465959 100644
--- a/src/antlr/GroovyParser.g4
+++ b/src/antlr/GroovyParser.g4
@@ -777,7 +777,9 @@ expression
                         |   dgOp=GT GT
                         )
             |   rangeOp=(    RANGE_INCLUSIVE
-                        |    RANGE_EXCLUSIVE
+                        |    RANGE_EXCLUSIVE_LEFT
+                        |    RANGE_EXCLUSIVE_RIGHT
+                        |    RANGE_EXCLUSIVE_FULL
                         )
             ) nls
         right=expression                                                                    #shiftExprAlt
diff --git a/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java b/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java
index 2510a25..3e5364f 100644
--- a/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java
+++ b/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java
@@ -2870,7 +2870,7 @@ public class AstBuilder extends GroovyParserBaseVisitor<Object> {
         Expression right = (Expression) this.visit(ctx.right);
 
         if (asBoolean(ctx.rangeOp)) {
-            return configureAST(new RangeExpression(left, right, !ctx.rangeOp.getText().endsWith("<")), ctx);
+            return configureAST(new RangeExpression(left, right, ctx.rangeOp.getText().startsWith("<"), ctx.rangeOp.getText().endsWith("<")), ctx);
         }
 
         org.codehaus.groovy.syntax.Token op;
diff --git a/src/main/java/org/codehaus/groovy/ast/expr/RangeExpression.java b/src/main/java/org/codehaus/groovy/ast/expr/RangeExpression.java
index 04a4923..a03cecf 100644
--- a/src/main/java/org/codehaus/groovy/ast/expr/RangeExpression.java
+++ b/src/main/java/org/codehaus/groovy/ast/expr/RangeExpression.java
@@ -27,18 +27,34 @@ import org.codehaus.groovy.ast.GroovyCodeVisitor;
  * <pre>for i in 0..10 {...}</pre>
  */
 public class RangeExpression extends Expression {
-
     private final Expression from;
     private final Expression to;
-    private final boolean inclusive;
+    private final boolean inclusive; // Kept to keep old code depending on this working
+    // GROOVY-9649
+    private final boolean exclusiveLeft;
+    private final boolean exclusiveRight;
 
+    // Kept until sure this can be removed
     public RangeExpression(Expression from, Expression to, boolean inclusive) {
         this.from = from;
         this.to = to;
         this.inclusive = inclusive;
+        this.exclusiveLeft = false;
+        this.exclusiveRight = !inclusive;
+        setType(ClassHelper.RANGE_TYPE);
+    }
+
+    // GROOVY-9649
+    public RangeExpression(Expression from, Expression to, boolean exclusiveLeft, boolean exclusiveRight) {
+        this.from = from;
+        this.to = to;
+        this.inclusive = !exclusiveRight; // Old code depends on this
+        this.exclusiveLeft = exclusiveLeft;
+        this.exclusiveRight = exclusiveRight;
         setType(ClassHelper.RANGE_TYPE);
     }
 
+
     @Override
     public void visit(GroovyCodeVisitor visitor) {
         visitor.visitRangeExpression(this);
@@ -46,7 +62,7 @@ public class RangeExpression extends Expression {
 
     @Override
     public Expression transformExpression(ExpressionTransformer transformer) {
-        Expression ret = new RangeExpression(transformer.transform(from), transformer.transform(to), inclusive);
+        Expression ret = new RangeExpression(transformer.transform(from), transformer.transform(to), exclusiveLeft, exclusiveRight);
         ret.setSourcePosition(this);
         ret.copyNodeMetaData(this);
         return ret;
@@ -64,10 +80,20 @@ public class RangeExpression extends Expression {
         return inclusive;
     }
 
+    public boolean isExclusiveLeft() {
+        return exclusiveLeft;
+    }
+
+    public boolean isExclusiveRight() {
+        return exclusiveRight;
+    }
+
     @Override
     public String getText() {
         return "(" + from.getText() +
-               (!isInclusive()? "..<" : ".." ) +
-               to.getText() + ")";
+                (this.exclusiveLeft ? "<" : "") +
+                ".." +
+                (this.exclusiveRight ? "<" : "") +
+                to.getText() + ")";
     }
 }
diff --git a/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/antlr4/ReflectionCompleter.groovy b/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/antlr4/ReflectionCompleter.groovy
index 74b182a..610e279 100644
--- a/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/antlr4/ReflectionCompleter.groovy
+++ b/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/completion/antlr4/ReflectionCompleter.groovy
@@ -69,7 +69,9 @@ import static org.apache.groovy.parser.antlr4.GroovyLexer.NOT
 import static org.apache.groovy.parser.antlr4.GroovyLexer.NOTEQUAL
 import static org.apache.groovy.parser.antlr4.GroovyLexer.OR
 import static org.apache.groovy.parser.antlr4.GroovyLexer.OR_ASSIGN
-import static org.apache.groovy.parser.antlr4.GroovyLexer.RANGE_EXCLUSIVE
+import static org.apache.groovy.parser.antlr4.GroovyLexer.RANGE_EXCLUSIVE_FULL
+import static org.apache.groovy.parser.antlr4.GroovyLexer.RANGE_EXCLUSIVE_LEFT
+import static org.apache.groovy.parser.antlr4.GroovyLexer.RANGE_EXCLUSIVE_RIGHT
 import static org.apache.groovy.parser.antlr4.GroovyLexer.RANGE_INCLUSIVE
 import static org.apache.groovy.parser.antlr4.GroovyLexer.RBRACK
 import static org.apache.groovy.parser.antlr4.GroovyLexer.RPAREN
@@ -349,7 +351,9 @@ class ReflectionCompleter {
                     break
             // may begin expression when outside brackets (from back)
                 case RANGE_INCLUSIVE:
-                case RANGE_EXCLUSIVE:
+                case RANGE_EXCLUSIVE_LEFT:
+                case RANGE_EXCLUSIVE_RIGHT:
+                case RANGE_EXCLUSIVE_FULL:
                 case COLON:
                 case COMMA:
                     if (expectedOpeners.empty()) {