package de.congrace.exp4j;
import java.util.Map;
import java.util.Stack;
abstract class RPNConverter {
private static String substituteUnaryOperators(String expr, Map<String, CustomOperator> operators) {
final StringBuilder exprBuilder = new StringBuilder(expr.length());
final char[] data = expr.toCharArray();
char lastChar = ' ';
StringBuilder lastOperation = new StringBuilder();
for (int i = 0; i < expr.length(); i++) {
if (exprBuilder.length() > 0) {
lastChar = exprBuilder.charAt(exprBuilder.length() - 1);
}
final char c = data[i];
if (i > 0 && isOperatorCharacter(expr.charAt(i - 1), operators)) {
if (!operators.containsKey(lastOperation.toString() + expr.charAt(i - 1))) {
lastOperation = new StringBuilder();
}
lastOperation.append(expr.charAt(i - 1));
} else if (i > 0 && !Character.isWhitespace(expr.charAt(i - 1))) {
lastOperation = new StringBuilder();
}
switch (c) {
case '+':
if (i > 0 && lastChar != '(' && operators.get(lastOperation.toString()) == null) {
exprBuilder.append(c);
}
break;
case '-':
if (i > 0 && lastChar != '(' && operators.get(lastOperation.toString()) == null) {
exprBuilder.append(c);
} else {
exprBuilder.append('\'');
}
break;
default:
if (!Character.isWhitespace(c)) {
exprBuilder.append(c);
}
}
}
return exprBuilder.toString();
}
static RPNExpression toRPNExpression(String infix, Map<String, Double> variables,
Map<String, CustomFunction> customFunctions, Map<String, CustomOperator> operators)
throws UnknownFunctionException, UnparsableExpressionException {
final Tokenizer tokenizer = new Tokenizer(variables.keySet(), customFunctions, operators);
final StringBuilder output = new StringBuilder(infix.length());
final Stack<Token> operatorStack = new Stack<Token>();
for (final Token token : tokenizer.getTokens(substituteUnaryOperators(infix, operators))) {
token.mutateStackForInfixTranslation(operatorStack, output);
}
// all tokens read, put the rest of the operations on the output;
while (operatorStack.size() > 0) {
output.append(operatorStack.pop().getValue()).append(" ");
}
String postfix = output.toString().trim();
return new RPNExpression(tokenizer.getTokens(postfix), postfix, variables);
}
private static boolean isOperatorCharacter(char c, Map<String, CustomOperator> operators) {
for (String symbol : operators.keySet()) {
if (symbol.indexOf(c) != -1) {
return true;
}
}
return false;
}
}