Added return, break and continue.

Dieser Commit ist enthalten in:
TomyLobo 2011-11-22 17:54:43 +01:00
Ursprung efc2209c0f
Commit 1a57f6e95d
10 geänderte Dateien mit 156 neuen und 8 gelöschten Zeilen

Datei anzeigen

@ -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,8 +98,13 @@ public class Expression {
((Variable) invokable).value = values[i];
}
try {
return root.getValue();
}
catch (ReturnException e) {
return e.getValue();
}
}
public void optimize() throws EvaluationException {
root = root.optimize();

Datei anzeigen

@ -48,6 +48,8 @@ public interface Identifiable {
* I - Conditional
* w - While
* F - For
* r - Return
* b - Break (includes continue)
* </pre>
*/
public abstract char id();

Datei anzeigen

@ -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_]*)");

Datei anzeigen

@ -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 + "'");
}

Datei anzeigen

@ -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
}

Datei anzeigen

@ -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;
}
}

Datei anzeigen

@ -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;

Datei anzeigen

@ -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
}

Datei anzeigen

@ -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;
}
}

Datei anzeigen

@ -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;
}
}
}
}