From bfe1f266922bffd3c0c8d8906535be7621217e7a Mon Sep 17 00:00:00 2001 From: Adrien Hopkins Date: Fri, 22 Mar 2019 19:35:30 -0400 Subject: Unit Expressions are now parsed with the expression parser. Addition and subtraction are now possible. --- src/org/unitConverter/math/ExpressionParser.java | 108 +++++++++++++++-------- 1 file changed, 72 insertions(+), 36 deletions(-) (limited to 'src/org/unitConverter/math/ExpressionParser.java') 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 @@ -55,6 +55,13 @@ public final class ExpressionParser { */ private final Function 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. * @@ -114,6 +121,24 @@ public final class ExpressionParser { return this; } + /** + * 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 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. * @@ -148,7 +173,8 @@ public final class ExpressionParser { * @since 2019-03-17 */ public ExpressionParser 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 { throw new IllegalArgumentException("No matching bracket found."); } - public static void main(final String[] args) { - final ExpressionParser 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 void swap(final List 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}. @@ -380,21 +378,33 @@ public final class ExpressionParser { */ private final Map> 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 objectObtainer, final Map> unaryOperators, - final Map> binaryOperators) { + final Map> binaryOperators, final String spaceOperator) { this.objectObtainer = objectObtainer; this.unaryOperators = unaryOperators; this.binaryOperators = binaryOperators; + this.spaceOperator = spaceOperator; } /** @@ -422,10 +432,26 @@ public final class ExpressionParser { 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 { 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 { } return expressionRPN; - // TODO method stub org.unitConverter.expressionParser.ExpressionParser.convertExpressionToPolish(expression) + // TODO document org.unitConverter.expressionParser.ExpressionParser.convertExpressionToPolish(expression) } /** -- cgit v1.2.3