static public float eval()

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();
    }