Skip to content
Permalink
Browse files

Merge pull request #527 from EngineHub/feature/extended-expressions

Expressions Part 1: ANTLR
  • Loading branch information
octylFractal committed Nov 8, 2019
2 parents 94bdd76 + 257988b commit 1fbb7a70f972c89c6609de96413251b5e84a02e0
Showing with 2,041 additions and 3,733 deletions.
  1. +1 −0 buildSrc/src/main/kotlin/PlatformConfig.kt
  2. +4 −0 config/checkstyle/import-control.xml
  3. +2 −0 worldedit-bukkit/build.gradle.kts
  4. +37 −0 worldedit-core/build.gradle.kts
  5. +236 −0 worldedit-core/src/main/antlr/com/sk89q/worldedit/antlr/Expression.g4
  6. +12 −7 worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java
  7. +1 −1 worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/ExpressionMask.java
  8. +1 −1 worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/ExpressionMask2D.java
  9. +5 −4 ...dedit-core/src/main/java/com/sk89q/worldedit/internal/expression/{runtime → }/BreakException.java
  10. +625 −0 worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/EvaluatingVisitor.java
  11. +1 −1 ...-core/src/main/java/com/sk89q/worldedit/internal/expression/{runtime → }/EvaluationException.java
  12. +70 −80 worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/Expression.java
  13. +1 −1 ...ore/src/main/java/com/sk89q/worldedit/internal/expression/{runtime → }/ExpressionEnvironment.java
  14. +1 −1 worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/ExpressionException.java
  15. +149 −0 worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/ExpressionHelper.java
  16. +1 −1 ...rc/main/java/com/sk89q/worldedit/internal/expression/{runtime → }/ExpressionTimeoutException.java
  17. +70 −0 worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/ExpressionValidator.java
  18. +337 −0 worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/Functions.java
  19. +7 −20 ...om/sk89q/worldedit/internal/expression/{lexer/tokens/KeywordToken.java → LexerErrorListener.java}
  20. +1 −3 worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/{lexer → }/LexerException.java
  21. +69 −0 worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/LocalSlot.java
  22. +7 −20 ...om/sk89q/worldedit/internal/expression/{lexer/tokens/NumberToken.java → ParserErrorListener.java}
  23. +1 −3 ...dedit-core/src/main/java/com/sk89q/worldedit/internal/expression/{parser → }/ParserException.java
  24. +64 −0 worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/SlotTable.java
  25. +0 −240 worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/lexer/Lexer.java
  26. +0 −44 ...dedit-core/src/main/java/com/sk89q/worldedit/internal/expression/lexer/tokens/CharacterToken.java
  27. +0 −44 ...edit-core/src/main/java/com/sk89q/worldedit/internal/expression/lexer/tokens/IdentifierToken.java
  28. +0 −44 worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/lexer/tokens/OperatorToken.java
  29. +0 −40 worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/lexer/tokens/Token.java
  30. +0 −464 worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/parser/Parser.java
  31. +0 −352 worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/parser/ParserProcessors.java
  32. +0 −43 worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/parser/PseudoToken.java
  33. +0 −50 worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/parser/UnaryOperator.java
  34. +0 −80 worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/parser/UnboundVariable.java
  35. +0 −50 worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/runtime/Break.java
  36. +0 −93 worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/runtime/Conditional.java
  37. +0 −49 worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/runtime/Constant.java
  38. +0 −107 worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/runtime/For.java
  39. +0 −123 worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/runtime/Function.java
  40. +0 −487 worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/runtime/Functions.java
  41. +0 −38 worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/runtime/LValue.java
  42. +0 −77 worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/runtime/LValueFunction.java
  43. +0 −54 worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/runtime/Node.java
  44. +0 −228 worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/runtime/Operators.java
  45. +0 −37 worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/runtime/RValue.java
  46. +0 −60 worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/runtime/Return.java
  47. +0 −41 worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/runtime/ReturnException.java
  48. +0 −109 worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/runtime/Sequence.java
  49. +0 −104 worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/runtime/SimpleFor.java
  50. +0 −206 worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/runtime/Switch.java
  51. +0 −67 worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/runtime/Variable.java
  52. +0 −133 worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/runtime/While.java
  53. +1 −1 worldedit-core/src/main/java/com/sk89q/worldedit/regions/shape/WorldEditExpressionEnvironment.java
  54. +100 −0 worldedit-core/src/test/java/com/sk89q/worldedit/internal/expression/BaseExpressionTest.java
  55. +61 −124 worldedit-core/src/test/java/com/sk89q/worldedit/internal/expression/ExpressionTest.java
  56. +171 −0 worldedit-core/src/test/java/com/sk89q/worldedit/internal/expression/RealExpressionTest.java
  57. +1 −1 worldedit-core/src/test/resources/junit-platform.properties
  58. +2 −0 worldedit-fabric/build.gradle.kts
  59. +2 −0 worldedit-forge/build.gradle.kts
@@ -110,6 +110,7 @@ fun Project.applyShadowConfiguration() {
exclude("GradleStart**")
exclude(".cache")
exclude("LICENSE*")
exclude("META-INF/maven/**")
minimize()
}
}
@@ -42,6 +42,10 @@
<allow pkg="com.google.auto"/>
<allow pkg="it.unimi.dsi.fastutil"/>

<subpackage name="internal.expression">
<allow pkg="org.antlr.v4"/>
</subpackage>

<subpackage name="bukkit">
<allow pkg="org.bukkit"/>
<allow pkg="org.bstats.bukkit"/>
@@ -54,9 +54,11 @@ tasks.named<ShadowJar>("shadowJar") {
dependencies {
relocate("org.slf4j", "com.sk89q.worldedit.slf4j")
relocate("org.apache.logging.slf4j", "com.sk89q.worldedit.log4jbridge")
relocate("org.antlr.v4", "com.sk89q.worldedit.antlr4")
include(dependency(":worldedit-core"))
include(dependency("org.slf4j:slf4j-api"))
include(dependency("org.apache.logging.log4j:log4j-slf4j-impl"))
include(dependency("org.antlr:antlr4-runtime"))
relocate("org.bstats", "com.sk89q.worldedit.bukkit.bstats") {
include(dependency("org.bstats:bstats-bukkit:1.5"))
}
@@ -1,7 +1,11 @@
import net.minecrell.gradle.licenser.LicenseExtension
import org.gradle.plugins.ide.idea.model.IdeaModel

plugins {
id("java-library")
id("net.ltgt.apt-eclipse")
id("net.ltgt.apt-idea")
id("antlr")
}

applyPlatformAndCoreConfiguration()
@@ -23,6 +27,10 @@ dependencies {
"compile"("org.slf4j:slf4j-api:1.7.26")
"compile"("it.unimi.dsi:fastutil:8.2.1")

val antlrVersion = "4.7.2"
"antlr"("org.antlr:antlr4:$antlrVersion")
"implementation"("org.antlr:antlr4-runtime:$antlrVersion")

"compileOnly"(project(":worldedit-libs:core:ap"))
"annotationProcessor"(project(":worldedit-libs:core:ap"))
// ensure this is on the classpath for the AP
@@ -36,6 +44,35 @@ tasks.withType<JavaCompile>().configureEach {
options.compilerArgs.add("-Aarg.name.key.prefix=")
}

tasks.named<AntlrTask>("generateGrammarSource").configure {
val pkg = "com.sk89q.worldedit.antlr"
outputDirectory = file("build/generated-src/antlr/main/${pkg.replace('.', '/')}")
arguments = listOf(
"-visitor", "-package", pkg,
"-Xexact-output-dir"
)
}

configure<LicenseExtension> {
exclude {
it.file.startsWith(project.buildDir)
}
}
tasks.withType<Checkstyle>().configureEach {
exclude("com/sk89q/worldedit/antlr/**/*.java")
}

// Give intellij info about where ANTLR code comes from
plugins.withId("idea") {
configure<IdeaModel> {
afterEvaluate {
module.sourceDirs.add(file("src/main/antlr"))
module.sourceDirs.add(file("build/generated-src/antlr/main"))
module.generatedSourceDirs.add(file("build/generated-src/antlr/main"))
}
}
}

sourceSets {
main {
java {
@@ -0,0 +1,236 @@
grammar Expression;

// Lexer tokens:

PLUS : '+' ;
MINUS : '-' ;
TIMES : '*' ;
DIVIDE : '/' ;
MODULO : '%' ;
POWER : '^' | '**' ;
LEFT_SHIFT : '<<' ;
RIGHT_SHIFT : '>>' ;
ASSIGN : '=' ;
COMPLEMENT : '~' ;

PLUS_ASSIGN : '+=' ;
MINUS_ASSIGN : '-=' ;
TIMES_ASSIGN : '*=' ;
DIVIDE_ASSIGN : '/=' ;
MODULO_ASSIGN : '%=' ;
POWER_ASSIGN : '^=' ;

EQUAL : '==' ;
NOT_EQUAL : '!=' ;
NEAR : '~=' ;
LESS_THAN : '<' ;
LESS_THAN_OR_EQUAL : '<=' ;
GREATER_THAN : '>' ;
GREATER_THAN_OR_EQUAL : '>=' ;
// SC = "Short Circuit"
// Non-SC variants not currently implemented.
AND_SC : '&&' ;
OR_SC : '||' ;

INCREMENT : '++' ;
DECREMENT : '--' ;

COMMA : ',' ;
OPEN_PAREN : '(' ;
CLOSE_PAREN : ')' ;
OPEN_BRACKET : '{' ;
CLOSE_BRACKET : '}' ;
SEMI_COLON : ';' ;
QUESTION_MARK : '?' ;
COLON : ':' ;
EXCLAMATION_MARK : '!' ;

IF : 'if' ;
ELSE : 'else' ;
WHILE : 'while' ;
DO : 'do' ;
FOR : 'for' ;
BREAK : 'break' ;
CONTINUE : 'continue' ;
RETURN : 'return' ;
SWITCH : 'switch' ;
CASE : 'case' ;
DEFAULT : 'default' ;

fragment DIGIT : [0-9] ;
fragment SIGN : [+-] ;
fragment EXP_CHAR : [eE] ;
fragment DECIMAL : '.' DIGIT+ ( EXP_CHAR SIGN? DIGIT+ )? ;

// All numbers are treated the same. No int/dec divide.
NUMBER : ( DIGIT+ DECIMAL? | DECIMAL ) ;

ID : [A-Za-z] [0-9A-Za-z_]* ;

WS : [ \t\r\n\u000C]+ -> skip ;

// Parser rules:

/**
* All statements parseable from the input. Forces consumption of EOF token.
*/
allStatements : statements EOF ;

statements : statement+ ;

statement
: ( block
| ifStatement
| whileStatement
| doStatement
| forStatement
| simpleForStatement
| breakStatement
| continueStatement
| returnStatement
| switchStatement
| expressionStatement
| emptyStatement
) SEMI_COLON?
;

block : '{' statements '}' ;

ifStatement : IF '(' condition=expression ')' trueBranch=statement ( ELSE falseBranch=statement )? ;

whileStatement : WHILE '(' condition=expression ')' body=statement ;

doStatement : DO body=statement WHILE '(' condition=expression ')' ;

// C-Style for loop
forStatement
: FOR '(' init=expression ';' condition=expression ';' update=expression ')' body=statement ;

// Range for loop
simpleForStatement
: FOR '(' counter=ID ASSIGN first=expression ',' last=expression ')' body=statement ;

breakStatement : BREAK ;

continueStatement : CONTINUE ;

returnStatement : RETURN value=expression? ;

switchStatement : SWITCH '(' target=expression ')' '{' (labels+=switchLabel ':' bodies+=statements )+ '}' ;

switchLabel
: CASE constant=constantExpression # Case
| DEFAULT # Default
;

expressionStatement : expression ;

emptyStatement: SEMI_COLON ;

expression : assignmentExpression ;

assignmentExpression
: conditionalExpression
| assignment
;

assignment
: target=ID assignmentOperator source=expression
;

assignmentOperator
: ASSIGN
| POWER_ASSIGN
| TIMES_ASSIGN
| DIVIDE_ASSIGN
| MODULO_ASSIGN
| PLUS_ASSIGN
| MINUS_ASSIGN
;

conditionalExpression
: conditionalOrExpression # CEFallthrough
| condition=conditionalOrExpression QUESTION_MARK
trueBranch=expression COLON falseBranch=conditionalExpression # TernaryExpr
;

conditionalOrExpression
: conditionalAndExpression # COFallthrough
| left=conditionalOrExpression OR_SC right=conditionalAndExpression # ConditionalOrExpr
;

conditionalAndExpression
: equalityExpression # CAFallthrough
| left=conditionalAndExpression AND_SC right=equalityExpression # ConditionalAndExpr
;

equalityExpression
: relationalExpression # EqFallthrough
| left=equalityExpression
op=
( EQUAL
| NOT_EQUAL
| NEAR
) right=relationalExpression # EqualityExpr
;

relationalExpression
: shiftExpression # ReFallthrough
| left=relationalExpression
op=
( LESS_THAN
| GREATER_THAN
| LESS_THAN_OR_EQUAL
| GREATER_THAN_OR_EQUAL
) right=shiftExpression # RelationalExpr
;

shiftExpression
: additiveExpression # ShFallthrough
| left=shiftExpression op=( LEFT_SHIFT | RIGHT_SHIFT ) right=additiveExpression # ShiftExpr
;

additiveExpression
: multiplicativeExpression # AdFallthrough
| left=additiveExpression op=( PLUS | MINUS ) right=multiplicativeExpression # AddExpr
;

multiplicativeExpression
: powerExpression # MuFallthrough
| left=multiplicativeExpression
op=
( TIMES
| DIVIDE
| MODULO
) right=powerExpression # MultiplicativeExpr
;

powerExpression
: unaryExpression # PwFallthrough
| left=powerExpression POWER right=unaryExpression # PowerExpr
;

unaryExpression
: op=( INCREMENT | DECREMENT ) target=ID # PreCrementExpr
| op=( PLUS | MINUS ) expr=unaryExpression # PlusMinusExpr
| postfixExpression # UaFallthrough
| COMPLEMENT expr=unaryExpression # ComplementExpr
| EXCLAMATION_MARK expr=unaryExpression # NotExpr
;

postfixExpression
: unprioritizedExpression # PoFallthrough
| target=ID op=( INCREMENT | DECREMENT) # PostCrementExpr
| expr=postfixExpression op=EXCLAMATION_MARK # PostfixExpr
;

unprioritizedExpression
: functionCall # FunctionCallExpr
| constantExpression # ConstantExpr
| source=ID # IdExpr
| '(' expression ')' # WrappedExpr
;

constantExpression : NUMBER ;

functionCall : name=ID '(' (args+=expression ( ',' args+=expression )*)? ')' ;
@@ -80,8 +80,8 @@
import com.sk89q.worldedit.history.changeset.ChangeSet;
import com.sk89q.worldedit.internal.expression.Expression;
import com.sk89q.worldedit.internal.expression.ExpressionException;
import com.sk89q.worldedit.internal.expression.runtime.ExpressionTimeoutException;
import com.sk89q.worldedit.internal.expression.runtime.RValue;
import com.sk89q.worldedit.internal.expression.ExpressionTimeoutException;
import com.sk89q.worldedit.internal.expression.LocalSlot.Variable;
import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.math.MathUtils;
@@ -1989,8 +1989,10 @@ public int makeShape(final Region region, final Vector3 zero, final Vector3 unit
final Expression expression = Expression.compile(expressionString, "x", "y", "z", "type", "data");
expression.optimize();

final RValue typeVariable = expression.getVariable("type", false);
final RValue dataVariable = expression.getVariable("data", false);
final Variable typeVariable = expression.getSlots().getVariable("type")
.orElseThrow(IllegalStateException::new);
final Variable dataVariable = expression.getSlots().getVariable("data")
.orElseThrow(IllegalStateException::new);

final WorldEditExpressionEnvironment environment = new WorldEditExpressionEnvironment(this, unit, zero);
expression.setEnvironment(environment);
@@ -2052,9 +2054,12 @@ public int deformRegion(final Region region, final Vector3 zero, final Vector3 u
final Expression expression = Expression.compile(expressionString, "x", "y", "z");
expression.optimize();

final RValue x = expression.getVariable("x", false);
final RValue y = expression.getVariable("y", false);
final RValue z = expression.getVariable("z", false);
final Variable x = expression.getSlots().getVariable("x")
.orElseThrow(IllegalStateException::new);
final Variable y = expression.getSlots().getVariable("y")
.orElseThrow(IllegalStateException::new);
final Variable z = expression.getSlots().getVariable("z")
.orElseThrow(IllegalStateException::new);

final WorldEditExpressionEnvironment environment = new WorldEditExpressionEnvironment(this, unit, zero);
expression.setEnvironment(environment);
@@ -23,7 +23,7 @@

import com.sk89q.worldedit.internal.expression.Expression;
import com.sk89q.worldedit.internal.expression.ExpressionException;
import com.sk89q.worldedit.internal.expression.runtime.EvaluationException;
import com.sk89q.worldedit.internal.expression.EvaluationException;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.shape.WorldEditExpressionEnvironment;

@@ -23,7 +23,7 @@

import com.sk89q.worldedit.internal.expression.Expression;
import com.sk89q.worldedit.internal.expression.ExpressionException;
import com.sk89q.worldedit.internal.expression.runtime.EvaluationException;
import com.sk89q.worldedit.internal.expression.EvaluationException;
import com.sk89q.worldedit.math.BlockVector2;

import javax.annotation.Nullable;

0 comments on commit 1fbb7a7

Please sign in to comment.
You can’t perform that action at this time.