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()) {