Skip to content
Permalink
Browse files

Completely rewrite the expression parser in ANTLR.

  • Loading branch information
octylFractal committed Oct 19, 2019
1 parent 9f1e7cd commit 1ba02c54b7030d27ca64b9e3ae4fbb42977d7287
Showing with 1,595 additions and 3,734 deletions.
  1. +126 −75 worldedit-core/src/main/antlr/com/sk89q/worldedit/antlr/Expression.g4
  2. +12 −7 worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java
  3. +1 −1 worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/ExpressionMask.java
  4. +1 −1 worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/ExpressionMask2D.java
  5. +5 −4 ...dedit-core/src/main/java/com/sk89q/worldedit/internal/expression/{runtime → }/BreakException.java
  6. +625 −0 worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/EvaluatingVisitor.java
  7. +1 −1 ...-core/src/main/java/com/sk89q/worldedit/internal/expression/{runtime → }/EvaluationException.java
  8. +59 −74 worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/Expression.java
  9. +1 −1 ...ore/src/main/java/com/sk89q/worldedit/internal/expression/{runtime → }/ExpressionEnvironment.java
  10. +1 −1 worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/ExpressionException.java
  11. +149 −0 worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/ExpressionHelper.java
  12. +1 −1 ...rc/main/java/com/sk89q/worldedit/internal/expression/{runtime → }/ExpressionTimeoutException.java
  13. +70 −0 worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/ExpressionValidator.java
  14. +337 −0 worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/Functions.java
  15. +7 −20 ...om/sk89q/worldedit/internal/expression/{lexer/tokens/KeywordToken.java → LexerErrorListener.java}
  16. +1 −3 worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/{lexer → }/LexerException.java
  17. +69 −0 worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/LocalSlot.java
  18. +7 −20 ...om/sk89q/worldedit/internal/expression/{lexer/tokens/NumberToken.java → ParserErrorListener.java}
  19. +1 −3 ...dedit-core/src/main/java/com/sk89q/worldedit/internal/expression/{parser → }/ParserException.java
  20. +64 −0 worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/SlotTable.java
  21. +0 −240 worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/lexer/Lexer.java
  22. +0 −44 ...dedit-core/src/main/java/com/sk89q/worldedit/internal/expression/lexer/tokens/CharacterToken.java
  23. +0 −44 ...edit-core/src/main/java/com/sk89q/worldedit/internal/expression/lexer/tokens/IdentifierToken.java
  24. +0 −44 worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/lexer/tokens/OperatorToken.java
  25. +0 −40 worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/lexer/tokens/Token.java
  26. +0 −464 worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/parser/Parser.java
  27. +0 −352 worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/parser/ParserProcessors.java
  28. +0 −43 worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/parser/PseudoToken.java
  29. +0 −50 worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/parser/UnaryOperator.java
  30. +0 −80 worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/parser/UnboundVariable.java
  31. +0 −50 worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/runtime/Break.java
  32. +0 −93 worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/runtime/Conditional.java
  33. +0 −49 worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/runtime/Constant.java
  34. +0 −107 worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/runtime/For.java
  35. +0 −123 worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/runtime/Function.java
  36. +0 −487 worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/runtime/Functions.java
  37. +0 −38 worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/runtime/LValue.java
  38. +0 −77 worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/runtime/LValueFunction.java
  39. +0 −54 worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/runtime/Node.java
  40. +0 −228 worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/runtime/Operators.java
  41. +0 −37 worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/runtime/RValue.java
  42. +0 −60 worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/runtime/Return.java
  43. +0 −41 worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/runtime/ReturnException.java
  44. +0 −109 worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/runtime/Sequence.java
  45. +0 −104 worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/runtime/SimpleFor.java
  46. +0 −206 worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/runtime/Switch.java
  47. +0 −67 worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/runtime/Variable.java
  48. +0 −133 worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/runtime/While.java
  49. +1 −1 worldedit-core/src/main/java/com/sk89q/worldedit/regions/shape/WorldEditExpressionEnvironment.java
  50. +56 −57 worldedit-core/src/test/java/com/sk89q/worldedit/internal/expression/ExpressionTest.java
@@ -79,107 +79,158 @@ allStatements : statements EOF ;
statements : statement+ ;

statement
: block # BlockStmt
| ifStatement # IfStmt
| whileStatement # WhileStmt
| doStatement # DoStmt
| forStatement # ForStmt
| breakStatement # BreakStmt
| continueStatement # ContinueStmt
| returnStatement # ReturnStmt
| switchStatement # SwitchStmt
| expressionStatement # ExpressionStmt
| SEMI_COLON # EmptyStmt
: ( block
| ifStatement
| whileStatement
| doStatement
| forStatement
| simpleForStatement
| breakStatement
| continueStatement
| returnStatement
| switchStatement
| expressionStatement
| emptyStatement
) SEMI_COLON?
;

block : '{' statements '}' ;

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

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

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

// C-Style for loop
forStatement
: FOR '('
// C-style for loop
( expression ';' expression ';' expression
// Range for loop
| ID ASSIGN ID ',' ID
)
')' statement ;
: 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 expression? ;
returnStatement : RETURN value=expression? ;

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

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

expressionStatement : expression SEMI_COLON ;

expression
: unaryOp expression # UnaryExpr
| expression binaryOp expression # BinaryExpr
| expression postUnaryOp # PostUnaryExpr
| ID binaryAssignOp expression # AssignExpr
| expression '?' expression ':' expression # TernaryExpr
| functionCall # FunctionCallExpr
| constantExpression # ConstantExpr
| ID # IdExpr
| '(' expression ')' # WrappedExpr
;

constantExpression : NUMBER ;
expressionStatement : expression ;

functionCall : ID '(' (expression ( ',' expression )*)? ')' ;
emptyStatement: SEMI_COLON ;

unaryOp
: MINUS
| EXCLAMATION_MARK
| COMPLEMENT
| INCREMENT
| DECREMENT
;
expression : assignmentExpression ;

postUnaryOp
: INCREMENT
| DECREMENT
| EXCLAMATION_MARK
;
assignmentExpression
: conditionalExpression
| assignment
;

binaryOp
: POWER
| TIMES
| DIVIDE
| MODULO
| PLUS
| MINUS
| LEFT_SHIFT
| RIGHT_SHIFT
| LESS_THAN
| GREATER_THAN
| LESS_THAN_OR_EQUAL
| GREATER_THAN_OR_EQUAL
| EQUAL
| NOT_EQUAL
| NEAR
| AND_SC
| OR_SC
;
assignment
: target=ID assignmentOperator source=expression
;

binaryAssignOp
assignmentOperator
: ASSIGN
| PLUS_ASSIGN
| MINUS_ASSIGN
| POWER_ASSIGN
| TIMES_ASSIGN
| DIVIDE_ASSIGN
| MODULO_ASSIGN
| POWER_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;
@@ -17,18 +17,19 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package com.sk89q.worldedit.internal.expression.runtime;
package com.sk89q.worldedit.internal.expression;

/**
* Thrown when a break or continue is encountered.
* Loop constructs catch this exception.
*/
public class BreakException extends EvaluationException {
public class BreakException extends RuntimeException {

final boolean doContinue;
public final boolean doContinue;

public BreakException(boolean doContinue) {
super(-1, doContinue ? "'continue' encountered outside a loop" : "'break' encountered outside a loop");
super(doContinue ? "'continue' encountered outside a loop" : "'break' encountered outside a loop",
null, true, false);

this.doContinue = doContinue;
}

0 comments on commit 1ba02c5

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