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.EvaluationException;
|
||||
import com.sk89q.worldedit.expression.runtime.RValue;
|
||||
import com.sk89q.worldedit.expression.runtime.ReturnException;
|
||||
import com.sk89q.worldedit.expression.runtime.Variable;
|
||||
|
||||
/**
|
||||
@ -97,7 +98,12 @@ public class Expression {
|
||||
((Variable) invokable).value = values[i];
|
||||
}
|
||||
|
||||
return root.getValue();
|
||||
try {
|
||||
return root.getValue();
|
||||
}
|
||||
catch (ReturnException e) {
|
||||
return e.getValue();
|
||||
}
|
||||
}
|
||||
|
||||
public void optimize() throws EvaluationException {
|
||||
|
@ -48,6 +48,8 @@ public interface Identifiable {
|
||||
* I - Conditional
|
||||
* w - While
|
||||
* F - For
|
||||
* r - Return
|
||||
* b - Break (includes continue)
|
||||
* </pre>
|
||||
*/
|
||||
public abstract char id();
|
||||
|
@ -107,7 +107,7 @@ public class Lexer {
|
||||
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 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.OperatorToken;
|
||||
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.Constant;
|
||||
import com.sk89q.worldedit.expression.runtime.For;
|
||||
import com.sk89q.worldedit.expression.runtime.Functions;
|
||||
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.Variable;
|
||||
import com.sk89q.worldedit.expression.runtime.While;
|
||||
@ -163,6 +165,28 @@ public class Parser {
|
||||
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:
|
||||
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;
|
||||
|
||||
for (init.getValue(); condition.getValue() > 0; increment.getValue()) {
|
||||
ret = body.getValue();
|
||||
++iterations;
|
||||
if (iterations > 256) {
|
||||
throw new EvaluationException(getPosition(), "Loop exceeded 256 iterations.");
|
||||
}
|
||||
++iterations;
|
||||
|
||||
try {
|
||||
ret = body.getValue();
|
||||
}
|
||||
catch (BreakException e) {
|
||||
if (e.doContinue) {
|
||||
continue;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
do {
|
||||
ret = body.getValue();
|
||||
++iterations;
|
||||
if (iterations > 256) {
|
||||
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);
|
||||
} else {
|
||||
while (condition.getValue() > 0.0) {
|
||||
ret = body.getValue();
|
||||
++iterations;
|
||||
if (iterations > 256) {
|
||||
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