ExpressionBuilder: Move evaluation loop to operator objects.
1 files changed, 44 insertions(+), 23 deletions(-)

M src/main/java/nl/grauw/glass/expressions/ExpressionBuilder.java
M src/main/java/nl/grauw/glass/expressions/ExpressionBuilder.java +44 -23
@@ 26,23 26,7 @@ public class ExpressionBuilder {
 	}
 
 	public void addOperatorToken(Operator operator) {
-		evaluateNotYieldingTo(operator);
-
-		if (operator == GROUP_OPEN || operator == INDEX_OPEN) {
-			groupCount++;
-			operators.push(operator);
-			operators.push(SENTINEL);
-		} else if (operator == GROUP_CLOSE || operator == INDEX_CLOSE) {
-			groupCount--;
-			if (operators.pop() != SENTINEL)
-				throw new AssemblyException("Sentinel expected.");
-			if (operator == GROUP_CLOSE && operators.peek() != GROUP_OPEN)
-				throw new ExpressionError("Group open expected.");
-			if (operator == INDEX_CLOSE && operators.peek() != INDEX_OPEN)
-				throw new ExpressionError("Index open expected.");
-		} else {
-			operators.push(operator);
-		}
+		operator.tryEvaluate();
 	}
 
 	public Expression getExpression() {

          
@@ 50,8 34,10 @@ public class ExpressionBuilder {
 			throw new AssemblyException("Operands / operators is empty: " + this);
 
 		// process remainder
-		evaluateNotYieldingTo(SENTINEL);
+		SENTINEL.tryEvaluate();
 
+		if (operators.pop() != SENTINEL)
+			throw new AssemblyException("Sentinel expected.");
 		if (operators.size() > 1 && operators.peek() == SENTINEL)
 			throw new ExpressionError("Group close expected.");
 		if (operands.size() > 1 || operators.size() != 1)

          
@@ 60,11 46,6 @@ public class ExpressionBuilder {
 		return operands.pop();
 	}
 
-	private void evaluateNotYieldingTo(Operator operator) {
-		while (!operators.peek().yieldsTo(operator))
-			operators.pop().evaluate();
-	}
-
 	public boolean hasOpenGroup()
 	{
 		return groupCount > 0;

          
@@ 86,6 67,12 @@ public class ExpressionBuilder {
 			this.token = token;
 		}
 
+		public void tryEvaluate() {
+			while (!operators.peek().yieldsTo(this))
+				operators.pop().evaluate();
+			operators.push(this);
+		}
+
 		public boolean yieldsTo(Operator other) {
 			if (associativity == Associativity.LEFT_TO_RIGHT)
 				return precedence.ordinal() > other.precedence.ordinal();

          
@@ 331,6 318,12 @@ public class ExpressionBuilder {
 		public void evaluate() {
 			operands.push(new Group(operands.pop()));
 		};
+		@Override
+		public void tryEvaluate() {
+			super.tryEvaluate();
+			operators.push(SENTINEL);
+			groupCount++;
+		}
 	};
 
 	public final Operator GROUP_CLOSE = new Operator(Precedence.NONE, Associativity.LEFT_TO_RIGHT, ")") {

          
@@ 338,6 331,17 @@ public class ExpressionBuilder {
 		public void evaluate() {
 			throw new AssemblyException("Can not evaluate group close.");
 		};
+		@Override
+		public void tryEvaluate() {
+			super.tryEvaluate();
+			if (operators.pop() != GROUP_CLOSE)
+				throw new AssemblyException("Group close expected.");
+			if (operators.pop() != SENTINEL)
+				throw new AssemblyException("Sentinel expected.");
+			if (operators.peek() != GROUP_OPEN)
+				throw new ExpressionError("Group open expected.");
+			groupCount--;
+		}
 	};
 
 	public final Operator INDEX_OPEN = new Operator(Precedence.MEMBER, Associativity.LEFT_TO_RIGHT, "[") {

          
@@ 346,6 350,12 @@ public class ExpressionBuilder {
 			Expression operandRight = operands.pop();
 			operands.push(new Index(operands.pop(), operandRight));
 		};
+		@Override
+		public void tryEvaluate() {
+			super.tryEvaluate();
+			operators.push(SENTINEL);
+			groupCount++;
+		}
 	};
 
 	public final Operator INDEX_CLOSE = new Operator(Precedence.NONE, Associativity.LEFT_TO_RIGHT, "]") {

          
@@ 353,6 363,17 @@ public class ExpressionBuilder {
 		public void evaluate() {
 			throw new AssemblyException("Can not evaluate index close.");
 		};
+		@Override
+		public void tryEvaluate() {
+			super.tryEvaluate();
+			if (operators.pop() != INDEX_CLOSE)
+				throw new AssemblyException("Index close expected.");
+			if (operators.pop() != SENTINEL)
+				throw new AssemblyException("Sentinel expected.");
+			if (operators.peek() != INDEX_OPEN)
+				throw new ExpressionError("Index open expected.");
+			groupCount--;
+		}
 	};
 
 	public final Operator SENTINEL = new Operator(Precedence.NONE, Associativity.RIGHT_TO_LEFT, "#") {