geforkt von Mirrors/FastAsyncWorldEdit
Added a simple for loop to the expression parser.
Syntax: for (counter = first, last) { body } Also added a test case.
Dieser Commit ist enthalten in:
Ursprung
7e13b60a51
Commit
71287299b5
@ -50,6 +50,7 @@ public interface Identifiable {
|
|||||||
* F - For
|
* F - For
|
||||||
* r - Return
|
* r - Return
|
||||||
* b - Break (includes continue)
|
* b - Break (includes continue)
|
||||||
|
* S - SimpleFor
|
||||||
* </pre>
|
* </pre>
|
||||||
*/
|
*/
|
||||||
public abstract char id();
|
public abstract char id();
|
||||||
|
@ -35,9 +35,11 @@ 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.LValue;
|
||||||
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.Return;
|
||||||
import com.sk89q.worldedit.expression.runtime.Sequence;
|
import com.sk89q.worldedit.expression.runtime.Sequence;
|
||||||
|
import com.sk89q.worldedit.expression.runtime.SimpleFor;
|
||||||
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;
|
||||||
|
|
||||||
@ -153,8 +155,11 @@ public class Parser {
|
|||||||
case 'f': { // for
|
case 'f': { // for
|
||||||
++position;
|
++position;
|
||||||
consumeCharacter('(');
|
consumeCharacter('(');
|
||||||
|
int oldPosition = position;
|
||||||
final RValue init = parseExpression(true);
|
final RValue init = parseExpression(true);
|
||||||
consumeCharacter(';');
|
//if ((init instanceof LValue) && )
|
||||||
|
if (peek().id() == ';') {
|
||||||
|
++position;
|
||||||
final RValue condition = parseExpression(true);
|
final RValue condition = parseExpression(true);
|
||||||
consumeCharacter(';');
|
consumeCharacter(';');
|
||||||
final RValue increment = parseExpression(true);
|
final RValue increment = parseExpression(true);
|
||||||
@ -162,6 +167,38 @@ public class Parser {
|
|||||||
final RValue body = parseStatements(true);
|
final RValue body = parseStatements(true);
|
||||||
|
|
||||||
statements.add(new For(current.getPosition(), init, condition, increment, body));
|
statements.add(new For(current.getPosition(), init, condition, increment, body));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
position = oldPosition;
|
||||||
|
|
||||||
|
final Token variableToken = peek();
|
||||||
|
if (!(variableToken instanceof IdentifierToken)) {
|
||||||
|
throw new ParserException(variableToken.getPosition(), "Expected identifier");
|
||||||
|
}
|
||||||
|
|
||||||
|
// In theory, I should have to create non-existant variables here.
|
||||||
|
// However, the java-for parsing attempt further up already takes care of that :)
|
||||||
|
RValue variable = variables.get(((IdentifierToken) variableToken).value);
|
||||||
|
if (!(variable instanceof LValue)) {
|
||||||
|
throw new ParserException(variableToken.getPosition(), "Expected variable");
|
||||||
|
}
|
||||||
|
|
||||||
|
++position;
|
||||||
|
|
||||||
|
final Token equalsToken = peek();
|
||||||
|
if (!(equalsToken instanceof OperatorToken) || !((OperatorToken) equalsToken).operator.equals("=")) {
|
||||||
|
throw new ParserException(variableToken.getPosition(), "Expected '=' or a term and ';'");
|
||||||
|
}
|
||||||
|
++position;
|
||||||
|
|
||||||
|
final RValue first = parseExpression(true);
|
||||||
|
consumeCharacter(',');
|
||||||
|
final RValue last = parseExpression(true);
|
||||||
|
consumeCharacter(')');
|
||||||
|
final RValue body = parseStatements(true);
|
||||||
|
|
||||||
|
statements.add(new SimpleFor(current.getPosition(), (LValue) variable, first, last, body));
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
58
src/main/java/com/sk89q/worldedit/expression/runtime/SimpleFor.java
Normale Datei
58
src/main/java/com/sk89q/worldedit/expression/runtime/SimpleFor.java
Normale Datei
@ -0,0 +1,58 @@
|
|||||||
|
package com.sk89q.worldedit.expression.runtime;
|
||||||
|
|
||||||
|
public class SimpleFor extends Node {
|
||||||
|
LValue counter;
|
||||||
|
RValue first;
|
||||||
|
RValue last;
|
||||||
|
RValue body;
|
||||||
|
|
||||||
|
public SimpleFor(int position, LValue counter, RValue first, RValue last, RValue body) {
|
||||||
|
super(position);
|
||||||
|
|
||||||
|
this.counter = counter;
|
||||||
|
this.first = first;
|
||||||
|
this.last = last;
|
||||||
|
this.body = body;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getValue() throws EvaluationException {
|
||||||
|
int iterations = 0;
|
||||||
|
double ret = 0.0;
|
||||||
|
|
||||||
|
double firstValue = first.getValue();
|
||||||
|
double lastValue = last.getValue();
|
||||||
|
|
||||||
|
for (double i = firstValue; i <= lastValue; ++i) {
|
||||||
|
if (iterations > 256) {
|
||||||
|
throw new EvaluationException(getPosition(), "Loop exceeded 256 iterations.");
|
||||||
|
}
|
||||||
|
++iterations;
|
||||||
|
|
||||||
|
try {
|
||||||
|
counter.assign(i);
|
||||||
|
ret = body.getValue();
|
||||||
|
} catch (BreakException e) {
|
||||||
|
if (e.doContinue) {
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public char id() {
|
||||||
|
return 'S';
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "for (" + counter + " = " + first + ", " + last + ") { " + body + " }";
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: optimizer
|
||||||
|
}
|
@ -95,6 +95,7 @@ public class ExpressionTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testFor() throws ExpressionException {
|
public void testFor() throws ExpressionException {
|
||||||
assertEquals(5, simpleEval("a=0; for (i=0; i<5; ++i) { ++a; } a"), 0);
|
assertEquals(5, simpleEval("a=0; for (i=0; i<5; ++i) { ++a; } a"), 0);
|
||||||
|
assertEquals(12345, simpleEval("y=0; for (i=1,5) { y *= 10; y += i; } y"), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private double simpleEval(String expression) throws ExpressionException {
|
private double simpleEval(String expression) throws ExpressionException {
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren