package de.congrace.exp4j;
import java.util.List;
import java.util.Map;
import java.util.Stack;
class RPNExpression implements Calculable {
final List<Token> tokens;
final String expression;
final Map<String, Double> variables;
public RPNExpression(List<Token> tokens, String expression, final Map<String, Double> variables) {
super();
this.tokens = tokens;
this.expression = expression;
this.variables = variables;
}
/**
* calculate the result of the expression and substitute the variables by their values beforehand
*
* @param values
* the variable values to be substituted
* @return the result of the calculation
* @throws IllegalArgumentException
* if the variables are invalid
*/
public double calculate(double... values) throws IllegalArgumentException {
if (variables.size() == 0 && values != null) {
throw new IllegalArgumentException("there are no variables to set values");
} else if (values != null && values.length != variables.size()) {
throw new IllegalArgumentException("The are an unequal number of variables and arguments");
}
int i = 0;
if (variables.size() > 0 && values != null) {
for (Map.Entry<String, Double> entry : variables.entrySet()) {
entry.setValue(values[i++]);
}
}
final Stack<Double> stack = new Stack<Double>();
for (final Token t : tokens) {
((CalculationToken) t).mutateStackForCalculation(stack, variables);
}
return stack.pop();
}
public String getExpression() {
return expression;
}
public void setVariable(String name, double value) {
this.variables.put(name, value);
}
public double calculate() {
return calculate(null);
}
@Override
public boolean containsVariable(String name) {
// Check the token stream
for (Token token : tokens) {
if (token instanceof VariableToken && token.getValue().equals(name)) {
// This variable is mentioned
return true;
}
}
return false;
}
}