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"); final Expression expression = Expression.compile(expressionString, "x", "y", "z", "type", "data");
expression.optimize(); expression.optimize();
final RValue typeVariable = expression.getVariable("type"); final RValue typeVariable = expression.getVariable("type", false);
final RValue dataVariable = expression.getVariable("data"); final RValue dataVariable = expression.getVariable("data", false);
final ArbitraryShape shape = new ArbitraryShape(region) { final ArbitraryShape shape = new ArbitraryShape(region) {
@Override @Override
@ -2663,9 +2663,9 @@ public class EditSession {
final Expression expression = Expression.compile(expressionString, "x", "y", "z"); final Expression expression = Expression.compile(expressionString, "x", "y", "z");
expression.optimize(); expression.optimize();
final RValue x = expression.getVariable("x"); final RValue x = expression.getVariable("x", false);
final RValue y = expression.getVariable("y"); final RValue y = expression.getVariable("y", false);
final RValue z = expression.getVariable("z"); final RValue z = expression.getVariable("z", false);
Vector zero2 = zero.add(0.5, 0.5, 0.5); 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)); variables.put(variableName, new Variable(0));
} }
root = Parser.parse(tokens, variables); root = Parser.parse(tokens, this);
} }
public double evaluate(double... values) throws EvaluationException { public double evaluate(double... values) throws EvaluationException {
@ -114,7 +114,12 @@ public class Expression {
return root.toString(); return root.toString();
} }
public RValue getVariable(String name) { public RValue getVariable(String name, boolean create) {
return variables.get(name); 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.ArrayList;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; 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.Identifiable;
import com.sk89q.worldedit.expression.lexer.tokens.IdentifierToken; import com.sk89q.worldedit.expression.lexer.tokens.IdentifierToken;
import com.sk89q.worldedit.expression.lexer.tokens.KeywordToken; 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.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.SimpleFor;
import com.sk89q.worldedit.expression.runtime.Variable;
import com.sk89q.worldedit.expression.runtime.While; import com.sk89q.worldedit.expression.runtime.While;
/** /**
@ -68,15 +66,15 @@ public class Parser {
private final List<Token> tokens; private final List<Token> tokens;
private int position = 0; 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.tokens = tokens;
this.variables = variables; this.expression = expression;
} }
public static final RValue parse(List<Token> tokens, Map<String, RValue> variables) throws ParserException { public static final RValue parse(List<Token> tokens, Expression expression) throws ParserException {
return new Parser(tokens, variables).parse(); return new Parser(tokens, expression).parse();
} }
private RValue parse() throws ParserException { private RValue parse() throws ParserException {
@ -176,9 +174,7 @@ public class Parser {
throw new ParserException(variableToken.getPosition(), "Expected identifier"); throw new ParserException(variableToken.getPosition(), "Expected identifier");
} }
// In theory, I should have to create non-existant variables here. RValue variable = expression.getVariable(((IdentifierToken) variableToken).value, true);
// However, the java-for parsing attempt further up already takes care of that :)
RValue variable = variables.get(((IdentifierToken) variableToken).value);
if (!(variable instanceof LValue)) { if (!(variable instanceof LValue)) {
throw new ParserException(variableToken.getPosition(), "Expected variable"); throw new ParserException(variableToken.getPosition(), "Expected variable");
} }
@ -286,14 +282,11 @@ public class Parser {
if (next.id() == '(') { if (next.id() == '(') {
halfProcessed.add(parseFunctionCall(identifierToken)); halfProcessed.add(parseFunctionCall(identifierToken));
} else { } 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 (variable == null) {
if (next instanceof OperatorToken && ((OperatorToken) next).operator.equals("=")) { throw new ParserException(current.getPosition(), "Variable '" + identifierToken.value + "' not found");
// 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");
}
} }
halfProcessed.add(variable); halfProcessed.add(variable);
} }

View File

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