From 31a4234d9bac3db864828ac1766a272d1e373121 Mon Sep 17 00:00:00 2001 From: Danila Fedorin Date: Wed, 2 Aug 2017 10:41:52 -0700 Subject: [PATCH 1/2] Rename nodes to more general names. --- .../java/org/nwapw/abacus/parsing/ShuntingYardParser.java | 4 ++-- .../abacus/tree/{BinaryInfixNode.java => BinaryNode.java} | 8 ++++---- src/main/java/org/nwapw/abacus/tree/NumberReducer.java | 8 ++++---- .../abacus/tree/{UnaryPrefixNode.java => UnaryNode.java} | 6 +++--- 4 files changed, 13 insertions(+), 13 deletions(-) rename src/main/java/org/nwapw/abacus/tree/{BinaryInfixNode.java => BinaryNode.java} (92%) rename src/main/java/org/nwapw/abacus/tree/{UnaryPrefixNode.java => UnaryNode.java} (89%) diff --git a/src/main/java/org/nwapw/abacus/parsing/ShuntingYardParser.java b/src/main/java/org/nwapw/abacus/parsing/ShuntingYardParser.java index e807344..92e7d61 100644 --- a/src/main/java/org/nwapw/abacus/parsing/ShuntingYardParser.java +++ b/src/main/java/org/nwapw/abacus/parsing/ShuntingYardParser.java @@ -127,11 +127,11 @@ public class ShuntingYardParser implements Parser>, PluginListe TreeNode right = constructRecursive(matches); TreeNode left = constructRecursive(matches); if (left == null || right == null) return null; - else return new BinaryInfixNode(operator, left, right); + else return new BinaryNode(operator, left, right); } else { TreeNode applyTo = constructRecursive(matches); if (applyTo == null) return null; - else return new UnaryPrefixNode(operator, applyTo); + else return new UnaryNode(operator, applyTo); } } else if (matchType == TokenType.NUM) { return new NumberNode(abacus.numberFromString(match.getContent())); diff --git a/src/main/java/org/nwapw/abacus/tree/BinaryInfixNode.java b/src/main/java/org/nwapw/abacus/tree/BinaryNode.java similarity index 92% rename from src/main/java/org/nwapw/abacus/tree/BinaryInfixNode.java rename to src/main/java/org/nwapw/abacus/tree/BinaryNode.java index 912c3ca..6ec7b80 100644 --- a/src/main/java/org/nwapw/abacus/tree/BinaryInfixNode.java +++ b/src/main/java/org/nwapw/abacus/tree/BinaryNode.java @@ -3,7 +3,7 @@ package org.nwapw.abacus.tree; /** * A tree node that represents an operation being applied to two operands. */ -public class BinaryInfixNode extends TreeNode { +public class BinaryNode extends TreeNode { /** * The operation being applied. @@ -18,7 +18,7 @@ public class BinaryInfixNode extends TreeNode { */ private TreeNode right; - private BinaryInfixNode() { + private BinaryNode() { } /** @@ -27,7 +27,7 @@ public class BinaryInfixNode extends TreeNode { * * @param operation the operation. */ - public BinaryInfixNode(String operation) { + public BinaryNode(String operation) { this(operation, null, null); } @@ -39,7 +39,7 @@ public class BinaryInfixNode extends TreeNode { * @param left the left node of the expression. * @param right the right node of the expression. */ - public BinaryInfixNode(String operation, TreeNode left, TreeNode right) { + public BinaryNode(String operation, TreeNode left, TreeNode right) { this.operation = operation; this.left = left; this.right = right; diff --git a/src/main/java/org/nwapw/abacus/tree/NumberReducer.java b/src/main/java/org/nwapw/abacus/tree/NumberReducer.java index 23460ed..8584231 100644 --- a/src/main/java/org/nwapw/abacus/tree/NumberReducer.java +++ b/src/main/java/org/nwapw/abacus/tree/NumberReducer.java @@ -28,15 +28,15 @@ public class NumberReducer implements Reducer { public NumberInterface reduceNode(TreeNode node, Object... children) { if (node instanceof NumberNode) { return ((NumberNode) node).getNumber(); - } else if (node instanceof BinaryInfixNode) { + } else if (node instanceof BinaryNode) { NumberInterface left = (NumberInterface) children[0]; NumberInterface right = (NumberInterface) children[1]; - Function function = abacus.getPluginManager().operatorFor(((BinaryInfixNode) node).getOperation()).getFunction(); + Function function = abacus.getPluginManager().operatorFor(((BinaryNode) node).getOperation()).getFunction(); if (function == null) return null; return function.apply(left, right); - } else if (node instanceof UnaryPrefixNode) { + } else if (node instanceof UnaryNode) { NumberInterface child = (NumberInterface) children[0]; - Function functionn = abacus.getPluginManager().operatorFor(((UnaryPrefixNode) node).getOperation()).getFunction(); + Function functionn = abacus.getPluginManager().operatorFor(((UnaryNode) node).getOperation()).getFunction(); if (functionn == null) return null; return functionn.apply(child); } else if (node instanceof FunctionNode) { diff --git a/src/main/java/org/nwapw/abacus/tree/UnaryPrefixNode.java b/src/main/java/org/nwapw/abacus/tree/UnaryNode.java similarity index 89% rename from src/main/java/org/nwapw/abacus/tree/UnaryPrefixNode.java rename to src/main/java/org/nwapw/abacus/tree/UnaryNode.java index 2c04203..298d25d 100644 --- a/src/main/java/org/nwapw/abacus/tree/UnaryPrefixNode.java +++ b/src/main/java/org/nwapw/abacus/tree/UnaryNode.java @@ -1,6 +1,6 @@ package org.nwapw.abacus.tree; -public class UnaryPrefixNode extends TreeNode { +public class UnaryNode extends TreeNode { /** * The operation this node will apply. @@ -16,7 +16,7 @@ public class UnaryPrefixNode extends TreeNode { * * @param operation the operation for this node. */ - public UnaryPrefixNode(String operation) { + public UnaryNode(String operation) { this(operation, null); } @@ -26,7 +26,7 @@ public class UnaryPrefixNode extends TreeNode { * @param operation the operation for this node. * @param applyTo the node to apply the function to. */ - public UnaryPrefixNode(String operation, TreeNode applyTo) { + public UnaryNode(String operation, TreeNode applyTo) { this.operation = operation; this.applyTo = applyTo; } From 046764eeca49ff08450a7a551fe4d03f83b28aae Mon Sep 17 00:00:00 2001 From: Danila Fedorin Date: Wed, 2 Aug 2017 11:26:59 -0700 Subject: [PATCH 2/2] Implement the negation operator. --- .../org/nwapw/abacus/function/OperatorType.java | 2 +- .../abacus/parsing/ShuntingYardParser.java | 17 +++++++++++++---- .../org/nwapw/abacus/plugin/StandardPlugin.java | 17 ++++++++++++++++- 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/nwapw/abacus/function/OperatorType.java b/src/main/java/org/nwapw/abacus/function/OperatorType.java index d003c07..9bb3aac 100644 --- a/src/main/java/org/nwapw/abacus/function/OperatorType.java +++ b/src/main/java/org/nwapw/abacus/function/OperatorType.java @@ -4,5 +4,5 @@ package org.nwapw.abacus.function; * The type of an operator, describing how it should behave. */ public enum OperatorType { - BINARY_INFIX, UNARY_POSTFIX + BINARY_INFIX, UNARY_POSTFIX, UNARY_PREFIX } diff --git a/src/main/java/org/nwapw/abacus/parsing/ShuntingYardParser.java b/src/main/java/org/nwapw/abacus/parsing/ShuntingYardParser.java index 92e7d61..598c1e8 100644 --- a/src/main/java/org/nwapw/abacus/parsing/ShuntingYardParser.java +++ b/src/main/java/org/nwapw/abacus/parsing/ShuntingYardParser.java @@ -55,9 +55,12 @@ public class ShuntingYardParser implements Parser>, PluginListe public List> intoPostfix(List> from) { ArrayList> output = new ArrayList<>(); Stack> tokenStack = new Stack<>(); + TokenType previousType; + TokenType matchType = null; while (!from.isEmpty()) { Match match = from.remove(0); - TokenType matchType = match.getType(); + previousType = matchType; + matchType = match.getType(); if (matchType == TokenType.NUM) { output.add(match); } else if (matchType == TokenType.FUNCTION) { @@ -74,7 +77,13 @@ public class ShuntingYardParser implements Parser>, PluginListe continue; } - while (!tokenStack.empty()) { + if(tokenString.equals("-") && (previousType == null || previousType == TokenType.OP || + previousType == TokenType.OPEN_PARENTH)){ + from.add(0, new Match<>("`", TokenType.OP)); + continue; + } + + while (!tokenStack.empty() && type == OperatorType.BINARY_INFIX) { Match otherMatch = tokenStack.peek(); TokenType otherMatchType = otherMatch.getType(); if (!(otherMatchType == TokenType.OP || otherMatchType == TokenType.FUNCTION)) break; @@ -103,8 +112,8 @@ public class ShuntingYardParser implements Parser>, PluginListe } while (!tokenStack.empty()) { Match match = tokenStack.peek(); - TokenType matchType = match.getType(); - if (!(matchType == TokenType.OP || matchType == TokenType.FUNCTION)) return null; + TokenType newMatchType = match.getType(); + if (!(newMatchType == TokenType.OP || newMatchType == TokenType.FUNCTION)) return null; output.add(tokenStack.pop()); } return output; diff --git a/src/main/java/org/nwapw/abacus/plugin/StandardPlugin.java b/src/main/java/org/nwapw/abacus/plugin/StandardPlugin.java index aeed916..2abf8b2 100755 --- a/src/main/java/org/nwapw/abacus/plugin/StandardPlugin.java +++ b/src/main/java/org/nwapw/abacus/plugin/StandardPlugin.java @@ -52,6 +52,20 @@ public class StandardPlugin extends Plugin { return params[0].subtract(params[1]); } }); + /** + * The negation operator, - + */ + public static final Operator OP_NEGATE = new Operator(OperatorAssociativity.LEFT, OperatorType.UNARY_PREFIX, 0, new Function() { + @Override + protected boolean matchesParams(NumberInterface[] params) { + return params.length == 1; + } + + @Override + protected NumberInterface applyInternal(NumberInterface[] params) { + return params[0].negate(); + } + }); /** * The multiplication operator, * */ @@ -317,6 +331,7 @@ public class StandardPlugin extends Plugin { registerOperator("+", OP_ADD); registerOperator("-", OP_SUBTRACT); + registerOperator("`", OP_NEGATE); registerOperator("*", OP_MULTIPLY); registerOperator("/", OP_DIVIDE); registerOperator("^", OP_CARET); @@ -335,7 +350,7 @@ public class StandardPlugin extends Plugin { public static NumberInterface factorial(Class numberClass, int n){ if(!factorialLists.containsKey(numberClass)){ - factorialLists.put(numberClass, new ArrayList()); + factorialLists.put(numberClass, new ArrayList<>()); factorialLists.get(numberClass).add(NaiveNumber.ONE.promoteTo(numberClass)); factorialLists.get(numberClass).add(NaiveNumber.ONE.promoteTo(numberClass)); }