From 21e059c1cafdb51a35cf8c75aaef76e56aae8d86 Mon Sep 17 00:00:00 2001 From: Danila Fedorin Date: Fri, 18 Aug 2017 14:20:37 -0700 Subject: [PATCH 1/7] Add a new TokenType for variables. --- core/src/main/java/org/nwapw/abacus/tree/TokenType.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/org/nwapw/abacus/tree/TokenType.java b/core/src/main/java/org/nwapw/abacus/tree/TokenType.java index ebb8861..aa1957a 100644 --- a/core/src/main/java/org/nwapw/abacus/tree/TokenType.java +++ b/core/src/main/java/org/nwapw/abacus/tree/TokenType.java @@ -7,7 +7,7 @@ package org.nwapw.abacus.tree; public enum TokenType { INTERNAL_FUNCTION_END(-1), - ANY(0), WHITESPACE(1), COMMA(2), OP(3), NUM(4), FUNCTION(5), OPEN_PARENTH(6), CLOSE_PARENTH(7); + ANY(0), WHITESPACE(1), COMMA(2), OP(3), NUM(4), VARIABLE(5), FUNCTION(6), OPEN_PARENTH(7), CLOSE_PARENTH(8); /** * The priority by which this token gets sorted. From 0a15043b636301cf9920a8975b1eeea20a9a7e7f Mon Sep 17 00:00:00 2001 From: Danila Fedorin Date: Fri, 18 Aug 2017 14:20:49 -0700 Subject: [PATCH 2/7] Implement a variable TreeNode. --- .../org/nwapw/abacus/tree/VariableNode.kt | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 core/src/main/kotlin/org/nwapw/abacus/tree/VariableNode.kt diff --git a/core/src/main/kotlin/org/nwapw/abacus/tree/VariableNode.kt b/core/src/main/kotlin/org/nwapw/abacus/tree/VariableNode.kt new file mode 100644 index 0000000..0bf05c6 --- /dev/null +++ b/core/src/main/kotlin/org/nwapw/abacus/tree/VariableNode.kt @@ -0,0 +1,21 @@ +package org.nwapw.abacus.tree + +/** + * A tree node that holds a placeholder variable. + * + * This node holds a variable string, and acts similarly to a number, + * with the key difference of not actually holding a value at runtime. + * + * @param variable the actual variable name that this node represents. + */ +data class VariableNode(val variable: String) : TreeNode() { + + override fun reduce(reducer: Reducer): T? { + return reducer.reduceNode(this) + } + + override fun toString(): String { + return variable + } + +} \ No newline at end of file From 1c751353f1aeefd9cd3005d6093f826765982ce2 Mon Sep 17 00:00:00 2001 From: Danila Fedorin Date: Fri, 18 Aug 2017 14:21:14 -0700 Subject: [PATCH 3/7] Lex and parse variables. --- .../main/java/org/nwapw/abacus/parsing/LexerTokenizer.java | 1 + .../java/org/nwapw/abacus/parsing/ShuntingYardParser.java | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/org/nwapw/abacus/parsing/LexerTokenizer.java b/core/src/main/java/org/nwapw/abacus/parsing/LexerTokenizer.java index 790882a..b7bdd1f 100644 --- a/core/src/main/java/org/nwapw/abacus/parsing/LexerTokenizer.java +++ b/core/src/main/java/org/nwapw/abacus/parsing/LexerTokenizer.java @@ -34,6 +34,7 @@ public class LexerTokenizer implements Tokenizer>, PluginListen register(" ", TokenType.WHITESPACE); register(",", TokenType.COMMA); register("[0-9]*(\\.[0-9]+)?", TokenType.NUM); + register("[a-zA-Z]+", TokenType.VARIABLE); register("\\(", TokenType.OPEN_PARENTH); register("\\)", TokenType.CLOSE_PARENTH); }}; diff --git a/core/src/main/java/org/nwapw/abacus/parsing/ShuntingYardParser.java b/core/src/main/java/org/nwapw/abacus/parsing/ShuntingYardParser.java index c7a5615..af9936b 100644 --- a/core/src/main/java/org/nwapw/abacus/parsing/ShuntingYardParser.java +++ b/core/src/main/java/org/nwapw/abacus/parsing/ShuntingYardParser.java @@ -61,7 +61,7 @@ public class ShuntingYardParser implements Parser>, PluginListe Match match = from.remove(0); previousType = matchType; matchType = match.getType(); - if (matchType == TokenType.NUM) { + if (matchType == TokenType.NUM || matchType == TokenType.VARIABLE) { output.add(match); } else if (matchType == TokenType.FUNCTION) { output.add(new Match<>("", TokenType.INTERNAL_FUNCTION_END)); @@ -144,6 +144,8 @@ public class ShuntingYardParser implements Parser>, PluginListe } } else if (matchType == TokenType.NUM) { return new NumberNode(abacus.numberFromString(match.getContent())); + } else if (matchType == TokenType.VARIABLE) { + return new VariableNode(match.getContent()); } else if (matchType == TokenType.FUNCTION) { String functionName = match.getContent(); FunctionNode node = new FunctionNode(functionName); From e0ff229df4dda6bdcd6a2ebbc6c7710c3acd0cef Mon Sep 17 00:00:00 2001 From: Danila Fedorin Date: Fri, 18 Aug 2017 14:21:48 -0700 Subject: [PATCH 4/7] Temporarily substitute 0 for variables. --- core/src/main/java/org/nwapw/abacus/tree/NumberReducer.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/src/main/java/org/nwapw/abacus/tree/NumberReducer.java b/core/src/main/java/org/nwapw/abacus/tree/NumberReducer.java index 8584231..1cda9a5 100644 --- a/core/src/main/java/org/nwapw/abacus/tree/NumberReducer.java +++ b/core/src/main/java/org/nwapw/abacus/tree/NumberReducer.java @@ -28,6 +28,8 @@ public class NumberReducer implements Reducer { public NumberInterface reduceNode(TreeNode node, Object... children) { if (node instanceof NumberNode) { return ((NumberNode) node).getNumber(); + } else if(node instanceof VariableNode) { + return abacus.numberFromString("0"); } else if (node instanceof BinaryNode) { NumberInterface left = (NumberInterface) children[0]; NumberInterface right = (NumberInterface) children[1]; From beb583a231c31131f0669bb2323ab8a15c20a358 Mon Sep 17 00:00:00 2001 From: Danila Fedorin Date: Fri, 18 Aug 2017 14:26:33 -0700 Subject: [PATCH 5/7] Move number string parsing from the parser into the reducer. --- .../java/org/nwapw/abacus/parsing/ShuntingYardParser.java | 2 +- core/src/main/java/org/nwapw/abacus/tree/NumberReducer.java | 2 +- core/src/main/kotlin/org/nwapw/abacus/tree/NumberNode.kt | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/core/src/main/java/org/nwapw/abacus/parsing/ShuntingYardParser.java b/core/src/main/java/org/nwapw/abacus/parsing/ShuntingYardParser.java index af9936b..86684ce 100644 --- a/core/src/main/java/org/nwapw/abacus/parsing/ShuntingYardParser.java +++ b/core/src/main/java/org/nwapw/abacus/parsing/ShuntingYardParser.java @@ -143,7 +143,7 @@ public class ShuntingYardParser implements Parser>, PluginListe else return new UnaryNode(operator, applyTo); } } else if (matchType == TokenType.NUM) { - return new NumberNode(abacus.numberFromString(match.getContent())); + return new NumberNode(match.getContent()); } else if (matchType == TokenType.VARIABLE) { return new VariableNode(match.getContent()); } else if (matchType == TokenType.FUNCTION) { diff --git a/core/src/main/java/org/nwapw/abacus/tree/NumberReducer.java b/core/src/main/java/org/nwapw/abacus/tree/NumberReducer.java index 1cda9a5..4dae775 100644 --- a/core/src/main/java/org/nwapw/abacus/tree/NumberReducer.java +++ b/core/src/main/java/org/nwapw/abacus/tree/NumberReducer.java @@ -27,7 +27,7 @@ public class NumberReducer implements Reducer { @Override public NumberInterface reduceNode(TreeNode node, Object... children) { if (node instanceof NumberNode) { - return ((NumberNode) node).getNumber(); + return abacus.numberFromString(((NumberNode) node).getNumber()); } else if(node instanceof VariableNode) { return abacus.numberFromString("0"); } else if (node instanceof BinaryNode) { diff --git a/core/src/main/kotlin/org/nwapw/abacus/tree/NumberNode.kt b/core/src/main/kotlin/org/nwapw/abacus/tree/NumberNode.kt index 03b299d..de6597a 100644 --- a/core/src/main/kotlin/org/nwapw/abacus/tree/NumberNode.kt +++ b/core/src/main/kotlin/org/nwapw/abacus/tree/NumberNode.kt @@ -10,14 +10,14 @@ import org.nwapw.abacus.number.NumberInterface * * @number the number value of this node. */ -data class NumberNode(val number: NumberInterface) : TreeNode() { +data class NumberNode(val number: String) : TreeNode() { override fun reduce(reducer: Reducer): T? { return reducer.reduceNode(this) } override fun toString(): String { - return number.toString() + return number } } \ No newline at end of file From 50ede6460c2458aa17b1604f4609db585d1260e8 Mon Sep 17 00:00:00 2001 From: Danila Fedorin Date: Fri, 18 Aug 2017 15:57:48 -0700 Subject: [PATCH 6/7] Remove Abacus dependency from ShuntingYardParser. --- core/src/main/java/org/nwapw/abacus/Abacus.java | 2 +- .../org/nwapw/abacus/parsing/ShuntingYardParser.java | 12 ++---------- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/core/src/main/java/org/nwapw/abacus/Abacus.java b/core/src/main/java/org/nwapw/abacus/Abacus.java index 826f266..113bda8 100644 --- a/core/src/main/java/org/nwapw/abacus/Abacus.java +++ b/core/src/main/java/org/nwapw/abacus/Abacus.java @@ -53,7 +53,7 @@ public class Abacus { numberReducer = new NumberReducer(this); this.configuration = new Configuration(configuration); LexerTokenizer lexerTokenizer = new LexerTokenizer(); - ShuntingYardParser shuntingYardParser = new ShuntingYardParser(this); + ShuntingYardParser shuntingYardParser = new ShuntingYardParser(); treeBuilder = new TreeBuilder<>(lexerTokenizer, shuntingYardParser); pluginManager.addListener(shuntingYardParser); diff --git a/core/src/main/java/org/nwapw/abacus/parsing/ShuntingYardParser.java b/core/src/main/java/org/nwapw/abacus/parsing/ShuntingYardParser.java index 86684ce..c792463 100644 --- a/core/src/main/java/org/nwapw/abacus/parsing/ShuntingYardParser.java +++ b/core/src/main/java/org/nwapw/abacus/parsing/ShuntingYardParser.java @@ -1,6 +1,5 @@ package org.nwapw.abacus.parsing; -import org.nwapw.abacus.Abacus; import org.nwapw.abacus.function.Operator; import org.nwapw.abacus.function.OperatorAssociativity; import org.nwapw.abacus.function.OperatorType; @@ -17,10 +16,6 @@ import java.util.*; */ public class ShuntingYardParser implements Parser>, PluginListener { - /** - * The Abacus instance used to create number instances. - */ - private Abacus abacus; /** * Map of operator precedences, loaded from the plugin operators. */ @@ -35,12 +30,9 @@ public class ShuntingYardParser implements Parser>, PluginListe private Map typeMap; /** - * Creates a new Shunting Yard parser with the given Abacus instance. - * - * @param abacus the abacus instance. + * Creates a new Shunting Yard parser. */ - public ShuntingYardParser(Abacus abacus) { - this.abacus = abacus; + public ShuntingYardParser() { precedenceMap = new HashMap<>(); associativityMap = new HashMap<>(); typeMap = new HashMap<>(); From 553c7354c106e7c22cb14d2726624832fd0b9c2d Mon Sep 17 00:00:00 2001 From: Danila Fedorin Date: Fri, 18 Aug 2017 16:31:54 -0700 Subject: [PATCH 7/7] Account for the new string-only node structure. The output has to be the same as the user-provided input, as the tree isn't converted to numbers until evaluation. --- core/src/test/java/org/nwapw/abacus/tests/CalculationTests.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/test/java/org/nwapw/abacus/tests/CalculationTests.java b/core/src/test/java/org/nwapw/abacus/tests/CalculationTests.java index 766376c..b210226 100755 --- a/core/src/test/java/org/nwapw/abacus/tests/CalculationTests.java +++ b/core/src/test/java/org/nwapw/abacus/tests/CalculationTests.java @@ -101,7 +101,7 @@ public class CalculationTests { testOutput("2^50", "(2^50)", "112589990684262"); testOutput("7^(-sqrt2*17)", "(7^((sqrt(2)*17))`)", "4.81354609155297814551845300063563"); testEvalError("0^0", "(0^0)"); - testEvalError("(-13)^.9999", "((13)`^0.9999)"); + testEvalError("(-13)^.9999", "((13)`^.9999)"); } }