diff options
author | Roman / Linnea Gräf <roman.graef@gmail.com> | 2023-07-06 12:41:33 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-07-06 12:41:33 +0200 |
commit | 0c94c8cf85824c2a8798a4c72d345738b1583388 (patch) | |
tree | fcf278acc366f05b3355fe786cb0d8dde9fcce8f | |
parent | b3b43eed2fe6677741ee52065016f319b6c9d723 (diff) | |
download | NotEnoughUpdates-0c94c8cf85824c2a8798a4c72d345738b1583388.tar.gz NotEnoughUpdates-0c94c8cf85824c2a8798a4c72d345738b1583388.tar.bz2 NotEnoughUpdates-0c94c8cf85824c2a8798a4c72d345738b1583388.zip |
Fix calculator preop operations (#758)
Fix calculator postop operations
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() + } + } + } + } +} |