diff options
author | Adrien Hopkins <adrien.p.hopkins@gmail.com> | 2019-03-22 19:35:30 -0400 |
---|---|---|
committer | Adrien Hopkins <adrien.p.hopkins@gmail.com> | 2019-03-22 19:35:30 -0400 |
commit | bfe1f266922bffd3c0c8d8906535be7621217e7a (patch) | |
tree | 3e85bac0398208db251f7365aa479528409f04f3 /src/org/unitConverter/math | |
parent | 943496888d18b031be19ba8e7348ec188dc8eb6b (diff) |
Unit Expressions are now parsed with the expression parser.
Addition and subtraction are now possible.
Diffstat (limited to 'src/org/unitConverter/math')
-rw-r--r-- | src/org/unitConverter/math/ExpressionParser.java | 108 |
1 files changed, 72 insertions, 36 deletions
diff --git a/src/org/unitConverter/math/ExpressionParser.java b/src/org/unitConverter/math/ExpressionParser.java index e06a58b..f34a0c2 100644 --- a/src/org/unitConverter/math/ExpressionParser.java +++ b/src/org/unitConverter/math/ExpressionParser.java @@ -56,6 +56,13 @@ public final class ExpressionParser<T> { private final Function<String, T> objectObtainer; /** + * The function of the space as an operator (like 3 x y) + * + * @since 2019-03-22 + */ + private String spaceFunction = null; + + /** * A map mapping operator strings to operator functions, for unary operators. * * @since 2019-03-14 @@ -115,6 +122,24 @@ public final class ExpressionParser<T> { } /** + * Adds a function for spaces. You must use the text of an existing binary operator. + * + * @param operator + * text of operator to use + * @return this builder + * @since 2019-03-22 + */ + public Builder<T> addSpaceFunction(final String operator) { + Objects.requireNonNull(operator, "operator must not be null."); + + if (!this.binaryOperators.containsKey(operator)) + throw new IllegalArgumentException(String.format("Could not find binary operator '%s'", operator)); + + this.spaceFunction = operator; + return this; + } + + /** * Adds a unary operator to the builder. * * @param text @@ -148,7 +173,8 @@ public final class ExpressionParser<T> { * @since 2019-03-17 */ public ExpressionParser<T> build() { - return new ExpressionParser<>(this.objectObtainer, this.unaryOperators, this.binaryOperators); + return new ExpressionParser<>(this.objectObtainer, this.unaryOperators, this.binaryOperators, + this.spaceFunction); } } @@ -330,34 +356,6 @@ public final class ExpressionParser<T> { throw new IllegalArgumentException("No matching bracket found."); } - public static void main(final String[] args) { - final ExpressionParser<Integer> numberParser = new ExpressionParser.Builder<>(Integer::parseInt) - .addBinaryOperator("+", (o1, o2) -> o1 + o2, 0).addBinaryOperator("*", (o1, o2) -> o1 * o2, 1) - .addBinaryOperator("^", (o1, o2) -> (int) Math.pow(o1, o2), 2).build(); - System.out.println(numberParser.convertExpressionToReversePolish("(1 + 2) ^ 5 * 3")); - System.out.println(numberParser.parseExpression("(1 + 2) ^ 5 * 3")); // 729 - } - - /** - * Swaps two elements in a list. Modifies the list passed in instead of returning a modified list. - * - * @param list - * list to swap elements - * @param firstIndex - * index of first element to swap - * @param otherIndex - * index of other element to swap - * @throws NullPointerException - * if list is null - * @since 2019-03-20 - */ - private static <E> void swap(final List<E> list, final int firstIndex, final int otherIndex) { - Objects.requireNonNull(list, "list must not be null."); - final E temp = list.get(firstIndex); - list.set(firstIndex, list.get(otherIndex)); - list.set(otherIndex, temp); - } - /** * A function that obtains a parseable object from a string. For example, an integer {@code ExpressionParser} would * use {@code Integer::parseInt}. @@ -381,20 +379,32 @@ public final class ExpressionParser<T> { private final Map<String, PriorityBinaryOperator<T>> binaryOperators; /** + * The operator for space, or null if spaces have no function. + * + * @since 2019-03-22 + */ + private final String spaceOperator; + + /** * Creates the {@code ExpressionParser}. * * @param objectObtainer * function to get objects from strings * @param unaryOperators - * operators available to the parser + * unary operators available to the parser + * @param binaryOperators + * binary operators available to the parser + * @param spaceOperator + * operator used by spaces * @since 2019-03-14 */ private ExpressionParser(final Function<String, T> objectObtainer, final Map<String, PriorityUnaryOperator<T>> unaryOperators, - final Map<String, PriorityBinaryOperator<T>> binaryOperators) { + final Map<String, PriorityBinaryOperator<T>> binaryOperators, final String spaceOperator) { this.objectObtainer = objectObtainer; this.unaryOperators = unaryOperators; this.binaryOperators = binaryOperators; + this.spaceOperator = spaceOperator; } /** @@ -422,10 +432,26 @@ public final class ExpressionParser<T> { while (partialExpression.indexOf(OPENING_BRACKET) != -1) { final int openingBracketPosition = partialExpression.indexOf(OPENING_BRACKET); final int closingBracketPosition = findBracketPair(partialExpression, openingBracketPosition); - components.addAll(Arrays.asList(partialExpression.substring(0, openingBracketPosition).split(" "))); - components.add(this.convertExpressionToReversePolish( - partialExpression.substring(openingBracketPosition + 1, closingBracketPosition))); - partialExpression = partialExpression.substring(closingBracketPosition + 1); + + // check for function + if (openingBracketPosition > 0 && partialExpression.charAt(openingBracketPosition - 1) != ' ') { + // function like sin(2) or tempF(32) + // find the position of the last space + int spacePosition = openingBracketPosition; + while (spacePosition >= 0 && partialExpression.charAt(spacePosition) != ' ') { + spacePosition--; + } + // then split the function into pre-function and function, using the space position + components.addAll(Arrays.asList(partialExpression.substring(0, spacePosition + 1).split(" "))); + components.add(partialExpression.substring(spacePosition + 1, closingBracketPosition + 1)); + partialExpression = partialExpression.substring(closingBracketPosition + 1); + } else { + // normal brackets like (1 + 2) * (3 / 5) + components.addAll(Arrays.asList(partialExpression.substring(0, openingBracketPosition).split(" "))); + components.add(this.convertExpressionToReversePolish( + partialExpression.substring(openingBracketPosition + 1, closingBracketPosition))); + partialExpression = partialExpression.substring(closingBracketPosition + 1); + } } // add everything else @@ -436,6 +462,16 @@ public final class ExpressionParser<T> { components.remove(""); } + // deal with space multiplication (x y) + if (this.spaceOperator != null) { + for (int i = 0; i < components.size() - 1; i++) { + if (this.getTokenType(components.get(i)) == TokenType.OBJECT + && this.getTokenType(components.get(i + 1)) == TokenType.OBJECT) { + components.add(++i, this.spaceOperator); + } + } + } + // turn the expression into reverse Polish while (true) { final int highestPriorityOperatorPosition = this.findHighestPriorityOperatorPosition(components); @@ -472,7 +508,7 @@ public final class ExpressionParser<T> { } return expressionRPN; - // TODO method stub org.unitConverter.expressionParser.ExpressionParser.convertExpressionToPolish(expression) + // TODO document org.unitConverter.expressionParser.ExpressionParser.convertExpressionToPolish(expression) } /** |