summaryrefslogtreecommitdiff
path: root/src/org/unitConverter/math
diff options
context:
space:
mode:
Diffstat (limited to 'src/org/unitConverter/math')
-rw-r--r--src/org/unitConverter/math/ExpressionParser.java108
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)
}
/**