aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/util/Calculator.java9
-rw-r--r--src/test/java/io/github/moulberry/notenoughupdates/util/CalculatorTest.java52
-rw-r--r--src/test/kotlin/io/github/moulberry/notenoughupdates/util/CalculatorTest.kt81
3 files changed, 86 insertions, 56 deletions
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/Calculator.java b/src/main/java/io/github/moulberry/notenoughupdates/util/Calculator.java
index 0762d107..2b741e94 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/util/Calculator.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/util/Calculator.java
@@ -98,7 +98,7 @@ public class Calculator {
public static List<Token> lex(String source) throws CalculatorException {
List<Token> tokens = new ArrayList<>();
- boolean justParsedNumber = false;
+ boolean doesNotHaveLValue = true;
for (int i = 0; i < source.length(); ) {
char c = source.charAt(i);
if (Character.isWhitespace(c)) {
@@ -107,7 +107,7 @@ public class Calculator {
}
Token token = new Token();
token.tokenStart = i;
- if (!justParsedNumber && c == '-') {
+ if (doesNotHaveLValue && c == '-') {
token.tokenLength = 1;
token.type = TokenType.PREOP;
token.operatorValue = "-";
@@ -175,7 +175,8 @@ public class Calculator {
} else {
throw new CalculatorException("Unknown thing " + c, i, 1);
}
- justParsedNumber = token.type == TokenType.NUMBER || token.type == TokenType.VARIABLE;
+ doesNotHaveLValue =
+ token.type == TokenType.LPAREN || token.type == TokenType.PREOP || token.type == TokenType.BINOP;
tokens.add(token);
i += token.tokenLength;
}
@@ -218,7 +219,7 @@ public class Calculator {
Token l = op.peek();
if (l.type == TokenType.LPAREN)
break;
- assert (l.type == TokenType.BINOP);
+ assert (l.type == TokenType.BINOP || l.type == TokenType.PREOP);
int pl = getPrecedence(l);
if (pl >= p) { // Association order
out.add(op.pop());
diff --git a/src/test/java/io/github/moulberry/notenoughupdates/util/CalculatorTest.java b/src/test/java/io/github/moulberry/notenoughupdates/util/CalculatorTest.java
deleted file mode 100644
index eff4a8de..00000000
--- a/src/test/java/io/github/moulberry/notenoughupdates/util/CalculatorTest.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2022 NotEnoughUpdates contributors
- *
- * This file is part of NotEnoughUpdates.
- *
- * NotEnoughUpdates is free software: you can redistribute it
- * and/or modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation, either
- * version 3 of the License, or (at your option) any later version.
- *
- * NotEnoughUpdates is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
- */
-
-package io.github.moulberry.notenoughupdates.util;
-
-import java.math.BigDecimal;
-import java.util.List;
-import java.util.Optional;
-import java.util.Scanner;
-
-public class CalculatorTest {
- public static void main(String[] args) throws Calculator.CalculatorException {
- Scanner s = new Scanner(System.in);
- while (true) {
- try {
- List<Calculator.Token> lex = Calculator.lex(s.nextLine());
- List<Calculator.Token> shunted = Calculator.shuntingYard(lex);
- for (Calculator.Token rawToken : shunted) {
- System.out.printf(
- "%s(%s)",
- rawToken.type,
- rawToken.operatorValue == null
- ? rawToken.numericValue + " * 10 ^ " + rawToken.exponent
- : rawToken.operatorValue
- );
- }
- System.out.println();
- BigDecimal evaluate = Calculator.evaluate(name -> Optional.of(BigDecimal.valueOf(16)), shunted);
- System.out.println("Eval: " + evaluate);
- } catch (Calculator.CalculatorException e) {
- e.printStackTrace();
- }
- }
- }
-
-}
diff --git a/src/test/kotlin/io/github/moulberry/notenoughupdates/util/CalculatorTest.kt b/src/test/kotlin/io/github/moulberry/notenoughupdates/util/CalculatorTest.kt
new file mode 100644
index 00000000..ce866eec
--- /dev/null
+++ b/src/test/kotlin/io/github/moulberry/notenoughupdates/util/CalculatorTest.kt
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2023 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.util
+
+import io.github.moulberry.notenoughupdates.util.Calculator.CalculatorException
+import org.junit.jupiter.api.Assertions
+import org.junit.jupiter.api.Test
+import java.math.BigDecimal
+import java.util.*
+import kotlin.math.absoluteValue
+import kotlin.math.pow
+
+internal class CalculatorTest {
+ @Suppress("NOTHING_TO_INLINE")
+ inline fun calculationShouldBe(expr: String, d: Number) =
+ assert(
+ (Calculator.calculate(expr).toDouble() - d.toDouble()).absoluteValue < 0.001
+ ) { "$expr should be equal to $d but is ${Calculator.calculate(expr)}" }
+
+ @Test
+ fun testReasonableCalculations() {
+ calculationShouldBe("1+1", 2)
+ calculationShouldBe("1k+1", 1001)
+ calculationShouldBe("(1)+1", 2)
+ calculationShouldBe("-0", 0)
+ calculationShouldBe("-10+2", -8)
+ calculationShouldBe("14k*23m/2.35+596123-9213", 137021863505.74)
+ calculationShouldBe("1+-10+2", -7)
+ calculationShouldBe("2**--10", 2.0.pow(10))
+ }
+
+ companion object {
+ @JvmStatic
+ fun main(args: Array<String>) {
+ val s = Scanner(System.`in`)
+ while (true) {
+ try {
+ val lex = Calculator.lex(s.nextLine())
+ val shunted = Calculator.shuntingYard(lex)
+ for (rawToken in shunted) {
+ System.out.printf(
+ "%s(%s)",
+ rawToken.type,
+ if (rawToken.operatorValue == null) rawToken.numericValue.toString() + " * 10 ^ " + rawToken.exponent else rawToken.operatorValue
+ )
+ }
+ println()
+ val evaluate = Calculator.evaluate(
+ { name: String? ->
+ Optional.of(
+ BigDecimal.valueOf(
+ 16
+ )
+ )
+ }, shunted
+ )
+ println("Eval: $evaluate")
+ } catch (e: CalculatorException) {
+ e.printStackTrace()
+ }
+ }
+ }
+ }
+}