This is an automated email from the ASF dual-hosted git repository. paulk pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/groovy.git
commit e3ba8e65e0b3b9cb0068bb64f3123be52a8442dd Author: Iiro Kiviluoma <[email protected]> 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 | 8 +++-- .../codehaus/groovy/ast/expr/RangeExpression.java | 36 +++++++++++++++++++--- .../completion/antlr4/ReflectionCompleter.groovy | 8 +++-- 5 files changed, 64 insertions(+), 28 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 16024a6..bff566b 100644 --- a/src/antlr/GroovyParser.g4 +++ b/src/antlr/GroovyParser.g4 @@ -766,7 +766,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 9ede47f..1fe7595 100644 --- a/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java +++ b/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java @@ -330,7 +330,9 @@ import static org.apache.groovy.parser.antlr4.GroovyParser.LT; import static org.apache.groovy.parser.antlr4.GroovyParser.NOT_IN; import static org.apache.groovy.parser.antlr4.GroovyParser.NOT_INSTANCEOF; import static org.apache.groovy.parser.antlr4.GroovyParser.PRIVATE; -import static org.apache.groovy.parser.antlr4.GroovyParser.RANGE_EXCLUSIVE; +import static org.apache.groovy.parser.antlr4.GroovyParser.RANGE_EXCLUSIVE_FULL; +import static org.apache.groovy.parser.antlr4.GroovyParser.RANGE_EXCLUSIVE_LEFT; +import static org.apache.groovy.parser.antlr4.GroovyParser.RANGE_EXCLUSIVE_RIGHT; import static org.apache.groovy.parser.antlr4.GroovyParser.RANGE_INCLUSIVE; import static org.apache.groovy.parser.antlr4.GroovyParser.SAFE_INDEX; import static org.apache.groovy.parser.antlr4.GroovyParser.STATIC; @@ -2870,7 +2872,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; @@ -4473,7 +4475,7 @@ public class AstBuilder extends GroovyParserBaseVisitor<Object> { int tokenType = token.getType(); String text = 1 == cardinality ? tokenText : StringGroovyMethods.multiply(tokenText, cardinality); return new org.codehaus.groovy.syntax.Token( - RANGE_EXCLUSIVE == tokenType || RANGE_INCLUSIVE == tokenType + RANGE_EXCLUSIVE_FULL == tokenType || RANGE_EXCLUSIVE_LEFT == tokenType || RANGE_EXCLUSIVE_RIGHT == tokenType || RANGE_INCLUSIVE == tokenType ? Types.RANGE_OPERATOR : SAFE_INDEX == tokenType ? Types.LEFT_SQUARE_BRACKET 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()) {
