in Minecraft/src/main/java/com/microsoft/Malmo/Utils/EvaluationHelper.java [52:151]
static public float eval(String expression, float t, Random rand) throws Exception
{
Stack<Float> values = new Stack<Float>();
Stack<String> operators = new Stack<String>();
boolean mustBeUnaryMinus = true;
while (!expression.isEmpty())
{
String number = "";
expression = expression.trim(); // Remove any white space
// Is the next token a number?
while (!expression.isEmpty() && expression.substring(0, 1).matches("[0-9\\.]"))
{
number += expression.substring(0,1);
expression = expression.substring(1);
}
Float f;
if (!number.isEmpty())
{
f = Float.valueOf(number);
// Yes, so push it straight to the values stack:
values.push(f);
mustBeUnaryMinus = false; // A unary '-' can't follow a value.
}
else
{
// Not a number - what is it?
String op = null;
for (int i = 0; i < functions.length + tokens.length; i++)
{
String tok = (i < functions.length) ? functions[i] : tokens[i - functions.length];
if (expression.startsWith(tok))
{
// Found it.
op = tok;
expression = expression.substring(op.length());
break;
}
}
if (op == null) // unrecognised token
throw new Exception("Unrecognised token at start of " + expression + " in eval()");
// Determine what to do for this token..
if (op.equals("-") && mustBeUnaryMinus) // check for unary minus
op = "unary_minus"; // to distinguish from, for example, "a-b".
if (op.equals("t"))
{
// time variable - substitute actual value of t and push straight to values:
values.push(t);
mustBeUnaryMinus = false; // A unary '-' can't follow a value.
}
else if (op.equals("rand"))
{
// push a random value straight to values:
values.push(rand.nextFloat());
mustBeUnaryMinus = false; // A unary '-' can't follow a value.
}
else if (op.equals("("))
{
// push to operators stack
operators.push(op);
mustBeUnaryMinus = true; // A '-' following a '(' must be a unary minus - eg "(-4*8)"
}
else if (op.equals(")"))
{
// closing bracket - pop the operators until we find the matching opening bracket.
while (!operators.isEmpty())
{
op = operators.pop();
if (op.equals("("))
break;
doOp(op, values, operators, rand); // carry out this operation.
}
mustBeUnaryMinus = false; // A '-' following a ')' can't be a unary minus - eg "(4^2)-16"
}
else if (isFunction(op)) // sin, cos, abs, etc. go straight on the operator stack
operators.push(op);
else
{
// token is an operator - need to consider the operator precedence, and pop any stacked operators
// that should be applied first.
int precedence = getPrecedence(op);
if (isRightAssociative(op))
precedence++; // Force <= comparison to behave as < comparison.
while (!operators.isEmpty() && !operators.peek().equals("(") && precedence <= getPrecedence(operators.peek()))
{
String op2 = operators.pop();
doOp(op2, values, operators, rand);
}
operators.push(op);
mustBeUnaryMinus = true; // A '-' following another operator must be unary - eg "4*-7"
}
}
}
// Finished going through the input string - apply any outstanding operators, functions, etc:
while (!operators.empty())
{
String op = operators.pop();
doOp(op, values, operators, rand);
}
return values.pop();
}