geforkt von Mirrors/FastAsyncWorldEdit
Added return, break and continue.
Dieser Commit ist enthalten in:
Ursprung
efc2209c0f
Commit
1a57f6e95d
@ -29,6 +29,7 @@ import com.sk89q.worldedit.expression.parser.Parser;
|
|||||||
import com.sk89q.worldedit.expression.runtime.Constant;
|
import com.sk89q.worldedit.expression.runtime.Constant;
|
||||||
import com.sk89q.worldedit.expression.runtime.EvaluationException;
|
import com.sk89q.worldedit.expression.runtime.EvaluationException;
|
||||||
import com.sk89q.worldedit.expression.runtime.RValue;
|
import com.sk89q.worldedit.expression.runtime.RValue;
|
||||||
|
import com.sk89q.worldedit.expression.runtime.ReturnException;
|
||||||
import com.sk89q.worldedit.expression.runtime.Variable;
|
import com.sk89q.worldedit.expression.runtime.Variable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -97,7 +98,12 @@ public class Expression {
|
|||||||
((Variable) invokable).value = values[i];
|
((Variable) invokable).value = values[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
return root.getValue();
|
try {
|
||||||
|
return root.getValue();
|
||||||
|
}
|
||||||
|
catch (ReturnException e) {
|
||||||
|
return e.getValue();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void optimize() throws EvaluationException {
|
public void optimize() throws EvaluationException {
|
||||||
|
@ -48,6 +48,8 @@ public interface Identifiable {
|
|||||||
* I - Conditional
|
* I - Conditional
|
||||||
* w - While
|
* w - While
|
||||||
* F - For
|
* F - For
|
||||||
|
* r - Return
|
||||||
|
* b - Break (includes continue)
|
||||||
* </pre>
|
* </pre>
|
||||||
*/
|
*/
|
||||||
public abstract char id();
|
public abstract char id();
|
||||||
|
@ -107,7 +107,7 @@ public class Lexer {
|
|||||||
characterTokens.add(';');
|
characterTokens.add(';');
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final Set<String> keywords = new HashSet<String>(Arrays.asList("if", "else", "while", "do", "for"));
|
private static final Set<String> keywords = new HashSet<String>(Arrays.asList("if", "else", "while", "do", "for", "break", "continue", "return"));
|
||||||
|
|
||||||
private static final Pattern numberPattern = Pattern.compile("^([0-9]*(?:\\.[0-9]+)?(?:[eE][+-]?[0-9]+)?)");
|
private static final Pattern numberPattern = Pattern.compile("^([0-9]*(?:\\.[0-9]+)?(?:[eE][+-]?[0-9]+)?)");
|
||||||
private static final Pattern identifierPattern = Pattern.compile("^([A-Za-z][0-9A-Za-z_]*)");
|
private static final Pattern identifierPattern = Pattern.compile("^([A-Za-z][0-9A-Za-z_]*)");
|
||||||
|
@ -30,11 +30,13 @@ import com.sk89q.worldedit.expression.lexer.tokens.KeywordToken;
|
|||||||
import com.sk89q.worldedit.expression.lexer.tokens.NumberToken;
|
import com.sk89q.worldedit.expression.lexer.tokens.NumberToken;
|
||||||
import com.sk89q.worldedit.expression.lexer.tokens.OperatorToken;
|
import com.sk89q.worldedit.expression.lexer.tokens.OperatorToken;
|
||||||
import com.sk89q.worldedit.expression.lexer.tokens.Token;
|
import com.sk89q.worldedit.expression.lexer.tokens.Token;
|
||||||
|
import com.sk89q.worldedit.expression.runtime.Break;
|
||||||
import com.sk89q.worldedit.expression.runtime.Conditional;
|
import com.sk89q.worldedit.expression.runtime.Conditional;
|
||||||
import com.sk89q.worldedit.expression.runtime.Constant;
|
import com.sk89q.worldedit.expression.runtime.Constant;
|
||||||
import com.sk89q.worldedit.expression.runtime.For;
|
import com.sk89q.worldedit.expression.runtime.For;
|
||||||
import com.sk89q.worldedit.expression.runtime.Functions;
|
import com.sk89q.worldedit.expression.runtime.Functions;
|
||||||
import com.sk89q.worldedit.expression.runtime.RValue;
|
import com.sk89q.worldedit.expression.runtime.RValue;
|
||||||
|
import com.sk89q.worldedit.expression.runtime.Return;
|
||||||
import com.sk89q.worldedit.expression.runtime.Sequence;
|
import com.sk89q.worldedit.expression.runtime.Sequence;
|
||||||
import com.sk89q.worldedit.expression.runtime.Variable;
|
import com.sk89q.worldedit.expression.runtime.Variable;
|
||||||
import com.sk89q.worldedit.expression.runtime.While;
|
import com.sk89q.worldedit.expression.runtime.While;
|
||||||
@ -163,6 +165,28 @@ public class Parser {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case 'b': // break
|
||||||
|
++position;
|
||||||
|
statements.add(new Break(current.getPosition(), false));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'c': // continue
|
||||||
|
++position;
|
||||||
|
statements.add(new Break(current.getPosition(), true));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'r': // return
|
||||||
|
++position;
|
||||||
|
statements.add(new Return(current.getPosition(), parseExpression(true)));
|
||||||
|
|
||||||
|
if (peek().id() == ';') {
|
||||||
|
++position;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
break loop;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new ParserException(current.getPosition(), "Unimplemented keyword '" + keyword + "'");
|
throw new ParserException(current.getPosition(), "Unimplemented keyword '" + keyword + "'");
|
||||||
}
|
}
|
||||||
|
28
src/main/java/com/sk89q/worldedit/expression/runtime/Break.java
Normale Datei
28
src/main/java/com/sk89q/worldedit/expression/runtime/Break.java
Normale Datei
@ -0,0 +1,28 @@
|
|||||||
|
package com.sk89q.worldedit.expression.runtime;
|
||||||
|
|
||||||
|
public class Break extends Node {
|
||||||
|
boolean doContinue;
|
||||||
|
|
||||||
|
public Break(int position, boolean doContinue) {
|
||||||
|
super(position);
|
||||||
|
|
||||||
|
this.doContinue = doContinue;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getValue() throws EvaluationException {
|
||||||
|
throw new BreakException(doContinue);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public char id() {
|
||||||
|
return 'b';
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return doContinue ? "continue" : "break";
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: optimizer
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
package com.sk89q.worldedit.expression.runtime;
|
||||||
|
|
||||||
|
public class BreakException extends EvaluationException {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
final boolean doContinue;
|
||||||
|
|
||||||
|
public BreakException(boolean doContinue) {
|
||||||
|
super(-1, doContinue ? "'continue' encountered outside a loop" : "'break' encountered outside a loop");
|
||||||
|
|
||||||
|
this.doContinue = doContinue;
|
||||||
|
}
|
||||||
|
}
|
@ -21,11 +21,21 @@ public class For extends Node {
|
|||||||
double ret = 0.0;
|
double ret = 0.0;
|
||||||
|
|
||||||
for (init.getValue(); condition.getValue() > 0; increment.getValue()) {
|
for (init.getValue(); condition.getValue() > 0; increment.getValue()) {
|
||||||
ret = body.getValue();
|
|
||||||
++iterations;
|
|
||||||
if (iterations > 256) {
|
if (iterations > 256) {
|
||||||
throw new EvaluationException(getPosition(), "Loop exceeded 256 iterations.");
|
throw new EvaluationException(getPosition(), "Loop exceeded 256 iterations.");
|
||||||
}
|
}
|
||||||
|
++iterations;
|
||||||
|
|
||||||
|
try {
|
||||||
|
ret = body.getValue();
|
||||||
|
}
|
||||||
|
catch (BreakException e) {
|
||||||
|
if (e.doContinue) {
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
28
src/main/java/com/sk89q/worldedit/expression/runtime/Return.java
Normale Datei
28
src/main/java/com/sk89q/worldedit/expression/runtime/Return.java
Normale Datei
@ -0,0 +1,28 @@
|
|||||||
|
package com.sk89q.worldedit.expression.runtime;
|
||||||
|
|
||||||
|
public class Return extends Node {
|
||||||
|
RValue value;
|
||||||
|
|
||||||
|
public Return(int position, RValue value) {
|
||||||
|
super(position);
|
||||||
|
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getValue() throws EvaluationException {
|
||||||
|
throw new ReturnException(value.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public char id() {
|
||||||
|
return 'r';
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "return "+value;
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: optimizer
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
package com.sk89q.worldedit.expression.runtime;
|
||||||
|
|
||||||
|
public class ReturnException extends EvaluationException {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
final double value;
|
||||||
|
|
||||||
|
public ReturnException(double value) {
|
||||||
|
super(-1);
|
||||||
|
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
@ -20,19 +20,39 @@ public class While extends Node {
|
|||||||
|
|
||||||
if (footChecked) {
|
if (footChecked) {
|
||||||
do {
|
do {
|
||||||
ret = body.getValue();
|
|
||||||
++iterations;
|
|
||||||
if (iterations > 256) {
|
if (iterations > 256) {
|
||||||
throw new EvaluationException(getPosition(), "Loop exceeded 256 iterations.");
|
throw new EvaluationException(getPosition(), "Loop exceeded 256 iterations.");
|
||||||
}
|
}
|
||||||
|
++iterations;
|
||||||
|
|
||||||
|
try {
|
||||||
|
ret = body.getValue();
|
||||||
|
}
|
||||||
|
catch (BreakException e) {
|
||||||
|
if (e.doContinue) {
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
} while (condition.getValue() > 0.0);
|
} while (condition.getValue() > 0.0);
|
||||||
} else {
|
} else {
|
||||||
while (condition.getValue() > 0.0) {
|
while (condition.getValue() > 0.0) {
|
||||||
ret = body.getValue();
|
|
||||||
++iterations;
|
|
||||||
if (iterations > 256) {
|
if (iterations > 256) {
|
||||||
throw new EvaluationException(getPosition(), "Loop exceeded 256 iterations.");
|
throw new EvaluationException(getPosition(), "Loop exceeded 256 iterations.");
|
||||||
}
|
}
|
||||||
|
++iterations;
|
||||||
|
|
||||||
|
try {
|
||||||
|
ret = body.getValue();
|
||||||
|
}
|
||||||
|
catch (BreakException e) {
|
||||||
|
if (e.doContinue) {
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren