2 Copyright 2011 frank asseg
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
8 http://www.apache.org/licenses/LICENSE-2.0
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
17 package net.sf.openrocket.util.exp4j;
19 import java.util.HashMap;
22 import java.util.Stack;
25 * Class for calculating values from a RPN postfix expression.<br/>
26 * The default way to create a new instance of {@link PostfixExpression} is by
27 * using the static factory method fromInfix()
29 * @author fas@congrace.de
31 public final class PostfixExpression extends AbstractExpression implements Calculable {
33 * Factory method for creating {@link PostfixExpression}s from human
34 * readable infix expressions
37 * the infix expression to be used
38 * @return an equivalent {@link PostfixExpression}
39 * @throws UnparsableExpressionException
40 * if the expression was invalid
41 * @throws UnknownFunctionException
42 * if an unknown function has been used
43 * @deprecated please use {@link ExpressionBuilder} API
46 public static PostfixExpression fromInfix(String expression) throws UnparsableExpressionException, UnknownFunctionException {
47 return fromInfix(expression, null);
51 * Factory method for creating {@link PostfixExpression}s from human
52 * readable infix expressions
55 * the infix expression to be used
56 * @param customFunctions
57 * the CustomFunction implementations used
58 * @return an equivalent {@link PostfixExpression}
59 * @throws UnparsableExpressionException
60 * if the expression was invalid
61 * @throws UnknownFunctionException
62 * if an unknown function has been used
63 * @deprecated please use {@link ExpressionBuilder}
66 public static PostfixExpression fromInfix(String expression, Set<CustomFunction> customFunctions) throws UnparsableExpressionException,
67 UnknownFunctionException {
68 String[] variables = null;
70 if ((posStart = expression.indexOf('=')) > 0) {
71 String functionDef = expression.substring(0, posStart);
72 expression = expression.substring(posStart + 1);
73 if ((posStart = functionDef.indexOf('(')) > 0 && (posEnd = functionDef.indexOf(')')) > 0) {
74 variables = functionDef.substring(posStart + 1, posEnd).split(",");
77 return new PostfixExpression(InfixTranslator.toPostfixExpression(expression, variables, customFunctions), variables, customFunctions);
80 private final Map<String, Double> variableValues = new HashMap<String, Double>();
83 * Construct a new simple {@link PostfixExpression}
86 * the postfix expression to be calculated
87 * @param variableNames
88 * the variable names in the expression
89 * @param customFunctions
90 * the CustomFunction implementations used
91 * @throws UnparsableExpressionException
92 * when expression is invalid
93 * @throws UnknownFunctionException
94 * when an unknown function has been used
96 private PostfixExpression(String expression, String[] variableNames, Set<CustomFunction> customFunctions) throws UnparsableExpressionException,
97 UnknownFunctionException {
98 super(expression, new Tokenizer(variableNames, customFunctions).tokenize(expression), variableNames);
102 * delegate the calculation of a simple expression without variables
106 public double calculate() {
107 return calculate(null);
111 * calculate the result of the expression and substitute the variables by
112 * their values beforehand
115 * the variable values to be substituted
116 * @return the result of the calculation
117 * @throws IllegalArgumentException
118 * if the variables are invalid
120 public double calculate(double... values) throws IllegalArgumentException {
121 if (getVariableNames() == null && values != null) {
122 throw new IllegalArgumentException("there are no variables to set values");
123 } else if (getVariableNames() != null && values == null && variableValues.isEmpty()) {
124 throw new IllegalAccessError("variable values have to be set");
125 } else if (values != null && values.length != getVariableNames().length) {
126 throw new IllegalArgumentException("The are an unequal number of variables and arguments");
129 if (getVariableNames() != null && values != null) {
130 for (double val : values) {
131 variableValues.put(getVariableNames()[i++], val);
134 final Stack<Double> stack = new Stack<Double>();
135 for (final Token t : getTokens()) {
136 ((CalculationToken) t).mutateStackForCalculation(stack, variableValues);
141 public void setVariable(String name, double value) {
142 variableValues.put(name, value);