Moved temporary variable creation from Parser to Expression.

This commit is contained in:
TomyLobo 2011-11-30 04:21:10 +01:00
parent 11245014c8
commit 662e597f1a
4 changed files with 30 additions and 32 deletions

View File

@ -2635,8 +2635,8 @@ public class EditSession {
final Expression expression = Expression.compile(expressionString, "x", "y", "z", "type", "data");
expression.optimize();
final RValue typeVariable = expression.getVariable("type");
final RValue dataVariable = expression.getVariable("data");
final RValue typeVariable = expression.getVariable("type", false);
final RValue dataVariable = expression.getVariable("data", false);
final ArbitraryShape shape = new ArbitraryShape(region) {
@Override
@ -2663,9 +2663,9 @@ public class EditSession {
final Expression expression = Expression.compile(expressionString, "x", "y", "z");
expression.optimize();
final RValue x = expression.getVariable("x");
final RValue y = expression.getVariable("y");
final RValue z = expression.getVariable("z");
final RValue x = expression.getVariable("x", false);
final RValue y = expression.getVariable("y", false);
final RValue z = expression.getVariable("z", false);
Vector zero2 = zero.add(0.5, 0.5, 0.5);

View File

@ -84,7 +84,7 @@ public class Expression {
variables.put(variableName, new Variable(0));
}
root = Parser.parse(tokens, variables);
root = Parser.parse(tokens, this);
}
public double evaluate(double... values) throws EvaluationException {
@ -114,7 +114,12 @@ public class Expression {
return root.toString();
}
public RValue getVariable(String name) {
return variables.get(name);
public RValue getVariable(String name, boolean create) {
RValue variable = variables.get(name);
if (variable == null && create) {
variables.put(name, variable = new Variable(0));
}
return variable;
}
}

View File

@ -22,8 +22,7 @@ package com.sk89q.worldedit.expression.parser;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import com.sk89q.worldedit.expression.Expression;
import com.sk89q.worldedit.expression.Identifiable;
import com.sk89q.worldedit.expression.lexer.tokens.IdentifierToken;
import com.sk89q.worldedit.expression.lexer.tokens.KeywordToken;
@ -40,7 +39,6 @@ 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.SimpleFor;
import com.sk89q.worldedit.expression.runtime.Variable;
import com.sk89q.worldedit.expression.runtime.While;
/**
@ -68,15 +66,15 @@ public class Parser {
private final List<Token> tokens;
private int position = 0;
private Map<String, RValue> variables;
private Expression expression;
private Parser(List<Token> tokens, Map<String, RValue> variables) {
private Parser(List<Token> tokens, Expression expression) {
this.tokens = tokens;
this.variables = variables;
this.expression = expression;
}
public static final RValue parse(List<Token> tokens, Map<String, RValue> variables) throws ParserException {
return new Parser(tokens, variables).parse();
public static final RValue parse(List<Token> tokens, Expression expression) throws ParserException {
return new Parser(tokens, expression).parse();
}
private RValue parse() throws ParserException {
@ -176,9 +174,7 @@ public class Parser {
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);
RValue variable = expression.getVariable(((IdentifierToken) variableToken).value, true);
if (!(variable instanceof LValue)) {
throw new ParserException(variableToken.getPosition(), "Expected variable");
}
@ -286,14 +282,11 @@ public class Parser {
if (next.id() == '(') {
halfProcessed.add(parseFunctionCall(identifierToken));
} else {
RValue variable = variables.get(identifierToken.value);
// Ugly hack to make temporary variables work while not sacrificing error reporting.
final boolean isSimpleAssignment = next instanceof OperatorToken && ((OperatorToken) next).operator.equals("=");
RValue variable = expression.getVariable(identifierToken.value, isSimpleAssignment);
if (variable == null) {
if (next instanceof OperatorToken && ((OperatorToken) next).operator.equals("=")) {
// Ugly hack to make temporary variables work while not sacrificing error reporting.
variables.put(identifierToken.value, variable = new Variable(0));
} else {
throw new ParserException(current.getPosition(), "Variable '" + identifierToken.value + "' not found");
}
throw new ParserException(current.getPosition(), "Variable '" + identifierToken.value + "' not found");
}
halfProcessed.add(variable);
}

View File

@ -65,9 +65,9 @@ public class ExpressionTest {
public void testAssign() throws ExpressionException {
Expression foo = compile("{a=x} b=y; c=z", "x", "y", "z", "a", "b", "c");
foo.evaluate(2, 3, 5);
assertEquals(2, foo.getVariable("a").getValue(), 0);
assertEquals(3, foo.getVariable("b").getValue(), 0);
assertEquals(5, foo.getVariable("c").getValue(), 0);
assertEquals(2, foo.getVariable("a", false).getValue(), 0);
assertEquals(3, foo.getVariable("b", false).getValue(), 0);
assertEquals(5, foo.getVariable("c", false).getValue(), 0);
}
@Test
@ -78,13 +78,13 @@ public class ExpressionTest {
// test 'dangling else'
final Expression expression1 = compile("if (1) if (0) x=4; else y=5;", "x", "y");
expression1.evaluate(1, 2);
assertEquals(1, expression1.getVariable("x").getValue(), 0);
assertEquals(5, expression1.getVariable("y").getValue(), 0);
assertEquals(1, expression1.getVariable("x", false).getValue(), 0);
assertEquals(5, expression1.getVariable("y", false).getValue(), 0);
// test if the if construct is correctly recognized as a statement
final Expression expression2 = compile("if (0) if (1) x=5; y=4;", "x", "y");
expression2.evaluate(1, 2);
assertEquals(4, expression2.getVariable("y").getValue(), 0);
assertEquals(4, expression2.getVariable("y", false).getValue(), 0);
}
@Test