From 5228773b5ec789106e433a1c3d9d6d8777d4b95d Mon Sep 17 00:00:00 2001 From: Danila Fedorin Date: Fri, 28 Jul 2017 11:14:45 -0700 Subject: [PATCH] Implement unary operators. --- src/org/nwapw/abacus/function/Operator.java | 1 + .../nwapw/abacus/plugin/StandardPlugin.java | 4 +- src/org/nwapw/abacus/tree/NumberReducer.java | 5 ++ src/org/nwapw/abacus/tree/TreeBuilder.java | 22 ++++++-- .../nwapw/abacus/tree/UnaryPrefixNode.java | 54 +++++++++++++++++++ 5 files changed, 80 insertions(+), 6 deletions(-) create mode 100644 src/org/nwapw/abacus/tree/UnaryPrefixNode.java diff --git a/src/org/nwapw/abacus/function/Operator.java b/src/org/nwapw/abacus/function/Operator.java index c69f9d2..5b1d2b2 100644 --- a/src/org/nwapw/abacus/function/Operator.java +++ b/src/org/nwapw/abacus/function/Operator.java @@ -30,6 +30,7 @@ public class Operator { */ public Operator(OperatorAssociativity associativity, OperatorType operatorType, int precedence, Function function){ this.associativity = associativity; + this.type = operatorType; this.precedence = precedence; this.function = function; } diff --git a/src/org/nwapw/abacus/plugin/StandardPlugin.java b/src/org/nwapw/abacus/plugin/StandardPlugin.java index 4cd13b5..68a733e 100755 --- a/src/org/nwapw/abacus/plugin/StandardPlugin.java +++ b/src/org/nwapw/abacus/plugin/StandardPlugin.java @@ -89,7 +89,7 @@ public class StandardPlugin extends Plugin { } })); - registerFunction("!", new Function() { + registerOperator("!", new Operator(OperatorAssociativity.RIGHT, OperatorType.UNARY_POSTFIX, 0, new Function() { //private HashMap, ArrayList> storedList = new HashMap, ArrayList>(); @Override protected boolean matchesParams(NumberInterface[] params) { @@ -114,7 +114,7 @@ public class StandardPlugin extends Plugin { storedList.get(params[0].getClass()).add(NaiveNumber.ONE.promoteTo(params[0].getClass())); }*/ } - }); + })); registerFunction("abs", new Function() { @Override diff --git a/src/org/nwapw/abacus/tree/NumberReducer.java b/src/org/nwapw/abacus/tree/NumberReducer.java index 6e4bee8..f447589 100644 --- a/src/org/nwapw/abacus/tree/NumberReducer.java +++ b/src/org/nwapw/abacus/tree/NumberReducer.java @@ -33,6 +33,11 @@ public class NumberReducer implements Reducer { Function function = manager.operatorFor(((OpNode) node).getOperation()).getFunction(); if(function == null) return null; return function.apply(left, right); + } else if(node instanceof UnaryPrefixNode) { + NumberInterface child = (NumberInterface) children[0]; + Function functionn = manager.operatorFor(((UnaryPrefixNode) node).getOperation()).getFunction(); + if(functionn == null) return null; + return functionn.apply(child); } else if(node instanceof FunctionNode){ NumberInterface[] convertedChildren = new NumberInterface[children.length]; for(int i = 0; i < convertedChildren.length; i++){ diff --git a/src/org/nwapw/abacus/tree/TreeBuilder.java b/src/org/nwapw/abacus/tree/TreeBuilder.java index 520d3e9..eabc565 100644 --- a/src/org/nwapw/abacus/tree/TreeBuilder.java +++ b/src/org/nwapw/abacus/tree/TreeBuilder.java @@ -101,9 +101,15 @@ public class TreeBuilder { tokenStack.push(match); } else if(matchType == TokenType.OP){ String tokenString = source.substring(match.getFrom(), match.getTo()); + OperatorType type = typeMap.get(tokenString); int precedence = precedenceMap.get(tokenString); OperatorAssociativity associativity = associativityMap.get(tokenString); + if(type == OperatorType.UNARY_POSTFIX){ + output.add(match); + continue; + } + while(!tokenStack.empty()) { Match otherMatch = tokenStack.peek(); TokenType otherMatchType = otherMatch.getType(); @@ -151,10 +157,18 @@ public class TreeBuilder { Match match = matches.remove(0); TokenType matchType = match.getType(); if(matchType == TokenType.OP){ - TreeNode right = fromStringRecursive(source, matches); - TreeNode left = fromStringRecursive(source, matches); - if(left == null || right == null) return null; - else return new OpNode(source.substring(match.getFrom(), match.getTo()), left, right); + String operator = source.substring(match.getFrom(), match.getTo()); + OperatorType type = typeMap.get(operator); + if(type == OperatorType.BINARY_INFIX){ + TreeNode right = fromStringRecursive(source, matches); + TreeNode left = fromStringRecursive(source, matches); + if(left == null || right == null) return null; + else return new OpNode(operator, left, right); + } else { + TreeNode applyTo = fromStringRecursive(source, matches); + if(applyTo == null) return null; + else return new UnaryPrefixNode(operator, applyTo); + } } else if(matchType == TokenType.NUM){ return new NumberNode(Double.parseDouble(source.substring(match.getFrom(), match.getTo()))); } else if(matchType == TokenType.FUNCTION){ diff --git a/src/org/nwapw/abacus/tree/UnaryPrefixNode.java b/src/org/nwapw/abacus/tree/UnaryPrefixNode.java new file mode 100644 index 0000000..944e339 --- /dev/null +++ b/src/org/nwapw/abacus/tree/UnaryPrefixNode.java @@ -0,0 +1,54 @@ +package org.nwapw.abacus.tree; + +public class UnaryPrefixNode extends TreeNode { + + /** + * The operation this node will apply. + */ + private String operation; + /** + * The tree node to apply the operation to. + */ + private TreeNode applyTo; + + /** + * Creates a new node with the given operation and no child. + * @param operation the operation for this node. + */ + public UnaryPrefixNode(String operation){ + this(operation, null); + } + + /** + * Creates a new node with the given operation and child. + * @param operation the operation for this node. + * @param applyTo the node to apply the function to. + */ + public UnaryPrefixNode(String operation, TreeNode applyTo){ + this.operation = operation; + this.applyTo = applyTo; + } + + @Override + public T reduce(Reducer reducer) { + Object reducedChild = applyTo.reduce(reducer); + if(reducedChild == null) return null; + return reducer.reduceNode(this, reducedChild); + } + + /** + * Gets the operation of this node. + * @return the operation this node performs. + */ + public String getOperation() { + return operation; + } + + /** + * Gets the node to which this node's operation applies. + * @return the tree node to which the operation will be applied. + */ + public TreeNode getApplyTo() { + return applyTo; + } +}