X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=core%2Fsrc%2Fde%2Fcongrace%2Fexp4j%2FOperatorToken.java;fp=core%2Fsrc%2Fde%2Fcongrace%2Fexp4j%2FOperatorToken.java;h=765f45083f3f1158cda91b1f1ea730c40a382308;hb=9349577cdfdff682b2aabd6daa24fdc3a7449b58;hp=0000000000000000000000000000000000000000;hpb=30ba0a882f0c061176ba14dbf86d3d6fad096c02;p=debian%2Fopenrocket diff --git a/core/src/de/congrace/exp4j/OperatorToken.java b/core/src/de/congrace/exp4j/OperatorToken.java new file mode 100644 index 00000000..765f4508 --- /dev/null +++ b/core/src/de/congrace/exp4j/OperatorToken.java @@ -0,0 +1,243 @@ +/* + Copyright 2011 frank asseg + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + */ +package de.congrace.exp4j; + +import java.util.Stack; + +/** + * {@link Token} for Operations like +,-,*,/,% and ^ + * + * @author fas@congrace.de + */ +class OperatorToken extends CalculationToken { + + /** + * the valid {@link Operation}s for the {@link OperatorToken} + * + * @author fas@congrace.de + */ + enum Operation { + ADDITION(1, true), SUBTRACTION(1, true), MULTIPLICATION(2, true), DIVISION(2, true), MODULO(2, true), EXPONENTIATION(3, false), UNARY_MINUS(4, false), UNARY_PLUS( + 4, false); + private final int precedence; + private final boolean leftAssociative; + + private Operation(int precedence, boolean leftAssociative) { + this.precedence = precedence; + this.leftAssociative = leftAssociative; + } + } + + /** + * return a corresponding {@link Operation} for a symbol + * + * @param c + * the symbol of the operation + * @return the corresponding {@link Operation} + */ + static Operation getOperation(char c) { + switch (c) { + case '+': + return Operation.ADDITION; + case '-': + return Operation.SUBTRACTION; + case '*': + return Operation.MULTIPLICATION; + case '/': + return Operation.DIVISION; + case '^': + return Operation.EXPONENTIATION; + case '#': + return Operation.UNARY_MINUS; + case '%': + return Operation.MODULO; + default: + return null; + } + } + + static boolean isOperator(char c) { + return getOperation(c) != null; + } + + private final Operation operation; + + /** + * construct a new {@link OperatorToken} + * + * @param value + * the symbol (e.g.: '+') + * @param operation + * the {@link Operation} of this {@link Token} + */ + OperatorToken(String value, Operation operation) { + super(value); + this.operation = operation; + } + + /** + * apply the {@link Operation} + * + * @param values + * the doubles to operate on + * @return the result of the {@link Operation} + * @throws UnparsableExpressionException + */ + public Variable applyOperation(Variable... values) { + + values = expandVariables(values); + + double[] inputs = new double[values.length]; + switch (values[0].getPrimary()){ + + case DOUBLE: + for (int i = 0; i stack, VariableSet variables) { + if (this.getOperandCount() == 2) { + final Variable n2 = stack.pop(); + final Variable n1 = stack.pop(); + stack.push(this.applyOperation(n1, n2)); + } else if (this.getOperandCount() == 1) { + final Variable n1 = stack.pop(); + stack.push(this.applyOperation(n1)); + } + } + + @Override + void mutateStackForInfixTranslation(Stack operatorStack, StringBuilder output) { + Token before; + while (!operatorStack.isEmpty() && (before = operatorStack.peek()) != null && (before instanceof OperatorToken || before instanceof FunctionToken)) { + if (before instanceof FunctionToken) { + operatorStack.pop(); + output.append(before.getValue()).append(" "); + } else { + final OperatorToken stackOperator = (OperatorToken) before; + if (this.isLeftAssociative() && this.getPrecedence() <= stackOperator.getPrecedence()) { + output.append(operatorStack.pop().getValue()).append(" "); + } else if (!this.isLeftAssociative() && this.getPrecedence() < stackOperator.getPrecedence()) { + output.append(operatorStack.pop().getValue()).append(" "); + } else { + break; + } + } + } + operatorStack.push(this); + } +}