From b4f5f98c0aa7fc892e96771ff2df729e61c21f74 Mon Sep 17 00:00:00 2001 From: bculkin2442 Date: Mon, 18 Apr 2016 19:56:32 -0400 Subject: Minor code changes --- .../bjc/utils/examples/parsing/ShuntTester.java | 2 +- .../utils/examples/parsing/TreeConstructTest.java | 122 ++++++++-- .../java/bjc/utils/funcdata/FunctionalList.java | 40 ++-- .../java/bjc/utils/funcdata/IFunctionalList.java | 24 +- .../src/main/java/bjc/utils/funcdata/ITree.java | 148 ++++++------ .../src/main/java/bjc/utils/funcdata/Tree.java | 265 +++++++++++---------- .../main/java/bjc/utils/funcutils/StringUtils.java | 6 + .../java/bjc/utils/parserutils/ShuntingYard.java | 30 +-- .../bjc/utils/parserutils/TokenTransformer.java | 14 +- .../bjc/utils/parserutils/TreeConstructor.java | 2 +- 10 files changed, 381 insertions(+), 272 deletions(-) diff --git a/BJC-Utils2/src/examples/java/bjc/utils/examples/parsing/ShuntTester.java b/BJC-Utils2/src/examples/java/bjc/utils/examples/parsing/ShuntTester.java index 1af5e30..6c1374e 100644 --- a/BJC-Utils2/src/examples/java/bjc/utils/examples/parsing/ShuntTester.java +++ b/BJC-Utils2/src/examples/java/bjc/utils/examples/parsing/ShuntTester.java @@ -25,7 +25,7 @@ public class ShuntTester { System.out.print("Enter a expression to shunt: "); String line = inputSource.nextLine(); - ShuntingYard yard = new ShuntingYard<>(); + ShuntingYard yard = new ShuntingYard<>(true); IFunctionalList shuntedTokens = yard.postfix(new FunctionalStringTokenizer(line) diff --git a/BJC-Utils2/src/examples/java/bjc/utils/examples/parsing/TreeConstructTest.java b/BJC-Utils2/src/examples/java/bjc/utils/examples/parsing/TreeConstructTest.java index ef081d2..320c4a4 100644 --- a/BJC-Utils2/src/examples/java/bjc/utils/examples/parsing/TreeConstructTest.java +++ b/BJC-Utils2/src/examples/java/bjc/utils/examples/parsing/TreeConstructTest.java @@ -1,11 +1,21 @@ package bjc.utils.examples.parsing; +import java.util.Deque; +import java.util.LinkedList; import java.util.Scanner; +import java.util.function.Function; import java.util.function.Predicate; +import bjc.utils.data.IPair; +import bjc.utils.data.Pair; +import bjc.utils.funcdata.FunctionalMap; import bjc.utils.funcdata.FunctionalStringTokenizer; import bjc.utils.funcdata.IFunctionalList; +import bjc.utils.funcdata.IFunctionalMap; import bjc.utils.funcdata.ITree; +import bjc.utils.funcdata.Tree; +import bjc.utils.funcutils.ListUtils; +import bjc.utils.funcutils.StringUtils; import bjc.utils.parserutils.ShuntingYard; import bjc.utils.parserutils.TreeConstructor; @@ -16,41 +26,115 @@ import bjc.utils.parserutils.TreeConstructor; * */ public class TreeConstructTest { + private static final class OperatorPicker + implements Predicate { + @Override + public boolean test(String token) { + if (StringUtils.containsOnly(token, "\\[")) { + return true; + } else if (StringUtils.containsOnly(token, "\\]")) { + return true; + } + + switch (token) { + case "+": + case "-": + case "*": + case "/": + return true; + default: + return false; + } + } + } + /** * Main method * * @param args * Unused CLI args */ + @SuppressWarnings("resource") public static void main(String[] args) { Scanner inputSource = new Scanner(System.in); System.out.print("Enter a expression to parse: "); String line = inputSource.nextLine(); - ShuntingYard yard = new ShuntingYard<>(); + IFunctionalList tokens = + new FunctionalStringTokenizer(line).toList(); + + ShuntingYard yard = new ShuntingYard<>(true); + + Deque> ops = new LinkedList<>(); + + ops.add(new Pair<>("+", "\\+")); + ops.add(new Pair<>("-", "-")); + ops.add(new Pair<>("*", "\\*")); + ops.add(new Pair<>("/", "/")); + ops.add(new Pair<>(":=", ":=")); + ops.add(new Pair<>("=>", "=>")); + + IFunctionalList semiExpandedTokens = + ListUtils.splitTokens(tokens, ops); + + ops = new LinkedList<>(); + + ops.add(new Pair<>("(", "\\(")); + ops.add(new Pair<>(")", "\\)")); + ops.add(new Pair<>("[", "\\[")); + ops.add(new Pair<>("]", "\\]")); + + IFunctionalList fullyExpandedTokens = + ListUtils.deAffixTokens(semiExpandedTokens, ops); + + fullyExpandedTokens.removeIf((strang) -> strang.equals("")); - IFunctionalList shuntedTokens = yard - .postfix(new FunctionalStringTokenizer(line) - .toList((strang) -> strang), (s) -> s); + IFunctionalList shuntedTokens = + yard.postfix(fullyExpandedTokens, (token) -> token); System.out.println("Shunted: " + shuntedTokens.toString()); - ITree constructedTree = TreeConstructor - .constructTree(shuntedTokens, new Predicate() { - @Override - public boolean test(String token) { - switch (token) { - case "+": - case "-": - case "*": - case "/": - return true; - default: - return false; - } - } - }, (operator) -> false, null); + Predicate specialPicker = (operator) -> { + if (StringUtils.containsOnly(operator, "\\[")) { + return true; + } else if (StringUtils.containsOnly(operator, "\\]")) { + return true; + } + + return false; + }; + + IFunctionalMap>, ITree>> operators = + new FunctionalMap<>(); + + operators.put("[", (queuedTrees) -> { + return null; + }); + + operators.put("[", (queuedTrees) -> { + Tree openTree = new Tree<>("["); + + queuedTrees.push(openTree); + + return openTree; + }); + + operators.put("]", (queuedTrees) -> { + ITree arrayTree = new Tree<>("[]"); + + while (!queuedTrees.peek().getHead().equals("[")) { + arrayTree.addChild(queuedTrees.pop()); + } + + queuedTrees.push(arrayTree); + + return arrayTree; + }); + + ITree constructedTree = TreeConstructor.constructTree( + shuntedTokens, new OperatorPicker(), specialPicker, + operators::get); System.out.println("AST: " + constructedTree.toString()); diff --git a/BJC-Utils2/src/main/java/bjc/utils/funcdata/FunctionalList.java b/BJC-Utils2/src/main/java/bjc/utils/funcdata/FunctionalList.java index 70d04cc..735c664 100644 --- a/BJC-Utils2/src/main/java/bjc/utils/funcdata/FunctionalList.java +++ b/BJC-Utils2/src/main/java/bjc/utils/funcdata/FunctionalList.java @@ -182,8 +182,8 @@ public class FunctionalList implements Cloneable, IFunctionalList { // Get the iterator for the other list Iterator rightIterator = rightList.toIterable().iterator(); - for (Iterator leftIterator = wrappedList - .iterator(); leftIterator.hasNext() + for (Iterator leftIterator = + wrappedList.iterator(); leftIterator.hasNext() && rightIterator.hasNext();) { // Add the transformed items to the result list E leftVal = leftIterator.next(); @@ -228,18 +228,18 @@ public class FunctionalList implements Cloneable, IFunctionalList { * Function) */ @Override - public IFunctionalList flatMap( - Function> elementExpander) { + public IFunctionalList + flatMap(Function> elementExpander) { if (elementExpander == null) { throw new NullPointerException("Expander must not be null"); } - IFunctionalList returnedList = new FunctionalList<>( - this.wrappedList.size()); + IFunctionalList returnedList = + new FunctionalList<>(this.wrappedList.size()); forEach(element -> { - IFunctionalList expandedElement = elementExpander - .apply(element); + IFunctionalList expandedElement = + elementExpander.apply(element); if (expandedElement == null) { throw new NullPointerException( @@ -370,8 +370,8 @@ public class FunctionalList implements Cloneable, IFunctionalList { throw new NullPointerException("Transformer must be not null"); } - IFunctionalList returnedList = new FunctionalList<>( - this.wrappedList.size()); + IFunctionalList returnedList = + new FunctionalList<>(this.wrappedList.size()); forEach(element -> { // Add the transformed item to the result @@ -388,8 +388,8 @@ public class FunctionalList implements Cloneable, IFunctionalList { * IFunctionalList) */ @Override - public IFunctionalList> pairWith( - IFunctionalList rightList) { + public IFunctionalList> + pairWith(IFunctionalList rightList) { return combineWith(rightList, Pair::new); } @@ -399,8 +399,8 @@ public class FunctionalList implements Cloneable, IFunctionalList { * @see bjc.utils.funcdata.IFunctionalList#partition(int) */ @Override - public IFunctionalList> partition( - int numberPerPartition) { + public IFunctionalList> + partition(int numberPerPartition) { if (numberPerPartition < 1 || numberPerPartition > wrappedList.size()) { throw new IllegalArgumentException("" + numberPerPartition @@ -408,11 +408,12 @@ public class FunctionalList implements Cloneable, IFunctionalList { + wrappedList.size()); } - IFunctionalList> returnedList = new FunctionalList<>(); + IFunctionalList> returnedList = + new FunctionalList<>(); // The current partition being filled - IHolder> currentPartition = new Identity<>( - new FunctionalList<>()); + IHolder> currentPartition = + new Identity<>(new FunctionalList<>()); this.forEach((element) -> { if (isPartitionFull(numberPerPartition, currentPartition)) { @@ -595,4 +596,9 @@ public class FunctionalList implements Cloneable, IFunctionalList { public IFunctionalList tail() { return new FunctionalList<>(wrappedList.subList(1, getSize())); } + + @Override + public void reverse() { + Collections.reverse(wrappedList); + } } \ No newline at end of file diff --git a/BJC-Utils2/src/main/java/bjc/utils/funcdata/IFunctionalList.java b/BJC-Utils2/src/main/java/bjc/utils/funcdata/IFunctionalList.java index f22df57..2c5d2ae 100644 --- a/BJC-Utils2/src/main/java/bjc/utils/funcdata/IFunctionalList.java +++ b/BJC-Utils2/src/main/java/bjc/utils/funcdata/IFunctionalList.java @@ -172,8 +172,8 @@ public interface IFunctionalList { * The predicate to match by * @return A list containing all elements that match the predicate */ - IFunctionalList getMatching( - Predicate matchPredicate); + IFunctionalList + getMatching(Predicate matchPredicate); /** * Retrieve the size of the wrapped list @@ -200,8 +200,8 @@ public interface IFunctionalList { * The function to apply to each element in the list * @return A new list containing the mapped elements of this list. */ - IFunctionalList map( - Function elementTransformer); + IFunctionalList + map(Function elementTransformer); /** * Zip two lists into a list of pairs @@ -214,8 +214,8 @@ public interface IFunctionalList { * @return A list containing pairs of this element and the specified * list */ - IFunctionalList> pairWith( - IFunctionalList rightList); + IFunctionalList> + pairWith(IFunctionalList rightList); /** * Partition this list into a list of sublists @@ -224,8 +224,8 @@ public interface IFunctionalList { * The size of elements to put into each one of the sublists * @return A list partitioned into partitions of size nPerPart */ - IFunctionalList> partition( - int numberPerPartition); + IFunctionalList> + partition(int numberPerPartition); /** * Prepend an item to the list @@ -325,10 +325,16 @@ public interface IFunctionalList { * @return An iterable view onto the list */ Iterable toIterable(); - + /** * Get the tail of this list (the list without the first element + * * @return The list without the first element */ public IFunctionalList tail(); + + /** + * Reverse the contents of this list in place + */ + void reverse(); } \ No newline at end of file diff --git a/BJC-Utils2/src/main/java/bjc/utils/funcdata/ITree.java b/BJC-Utils2/src/main/java/bjc/utils/funcdata/ITree.java index bbcefd3..866471c 100644 --- a/BJC-Utils2/src/main/java/bjc/utils/funcdata/ITree.java +++ b/BJC-Utils2/src/main/java/bjc/utils/funcdata/ITree.java @@ -24,43 +24,6 @@ public interface ITree { */ public void addChild(ITree child); - /** - * Transform the value that is the head of this node - * - * @param - * The type of the transformed value - * @param transformer - * The function to use to transform the value - * @return The transformed value - */ - public TransformedType transformHead( - Function transformer); - - /** - * Get a count of the number of direct children this node has - * - * @return The number of direct children this node has - */ - public int getChildrenCount(); - - /** - * Transform one of this nodes children - * - * @param - * The type of the transformed value - * @param childNo - * The number of the child to transform - * @param transformer - * The function to use to transform the value - * @return The transformed value - * - * @throws IllegalArgumentException - * if the childNo is out of bounds (0 <= childNo <= - * childCount()) - */ - public TransformedType transformChild(int childNo, - Function, TransformedType> transformer); - /** * Collapse a tree into a single version * @@ -83,6 +46,14 @@ public interface ITree { Function, NewType>> nodeCollapser, Function resultTransformer); + /** + * Execute a given action for each of this tree's children + * + * @param action + * The action to execute for each child + */ + void doForChildren(Consumer> action); + /** * Expand the nodes of a tree into trees, and then merge the contents * of those trees into a single tree @@ -95,38 +66,31 @@ public interface ITree { Function> mapper); /** - * Transform some of the nodes in this tree + * Get the specified child of this tree * - * @param nodePicker - * The predicate to use to pick nodes to transform - * @param transformer - * The function to use to transform picked nodes + * @param childNo + * The number of the child to get + * @return The specified child of this tree */ - public void selectiveTransform(Predicate nodePicker, - UnaryOperator transformer); + default ITree getChild(int childNo) { + return transformChild(childNo, (child) -> child); + } /** - * Transform the tree into a tree with a different type of token + * Get a count of the number of direct children this node has * - * @param - * The type of the new tree - * @param transformer - * The function to use to transform tokens - * @return A tree with the token types transformed + * @return The number of direct children this node has */ - public ITree - transformTree(Function transformer); + public int getChildrenCount(); /** - * Perform an action on each part of the tree + * Get the data stored in this node * - * @param linearizationMethod - * The way to traverse the tree - * @param action - * The action to perform on each tree node + * @return The data stored in this node */ - public void traverse(TreeLinearizationMethod linearizationMethod, - Consumer action); + default ContainedType getHead() { + return transformHead((head) -> head); + } /** * Rebuild the tree with the same structure, but different nodes @@ -143,6 +107,17 @@ public interface ITree { Function leafTransformer, Function operatorTransformer); + /** + * Transform some of the nodes in this tree + * + * @param nodePicker + * The predicate to use to pick nodes to transform + * @param transformer + * The function to use to transform picked nodes + */ + public void selectiveTransform(Predicate nodePicker, + UnaryOperator transformer); + /** * Do a top-down transform of the tree * @@ -157,22 +132,55 @@ public interface ITree { UnaryOperator> transformer); /** - * Get the specified child of this tree + * Transform one of this nodes children * + * @param + * The type of the transformed value * @param childNo - * The number of the child to get - * @return The specified child of this tree + * The number of the child to transform + * @param transformer + * The function to use to transform the value + * @return The transformed value + * + * @throws IllegalArgumentException + * if the childNo is out of bounds (0 <= childNo <= + * childCount()) */ - default ITree getChild(int childNo) { - return transformChild(childNo, (child) -> child); - } + public TransformedType transformChild(int childNo, + Function, TransformedType> transformer); /** - * Get the data stored in this node + * Transform the value that is the head of this node * - * @return The data stored in this node + * @param + * The type of the transformed value + * @param transformer + * The function to use to transform the value + * @return The transformed value */ - default ContainedType getHead() { - return transformHead((head) -> head); - } + public TransformedType transformHead( + Function transformer); + + /** + * Transform the tree into a tree with a different type of token + * + * @param + * The type of the new tree + * @param transformer + * The function to use to transform tokens + * @return A tree with the token types transformed + */ + public ITree + transformTree(Function transformer); + + /** + * Perform an action on each part of the tree + * + * @param linearizationMethod + * The way to traverse the tree + * @param action + * The action to perform on each tree node + */ + public void traverse(TreeLinearizationMethod linearizationMethod, + Consumer action); } diff --git a/BJC-Utils2/src/main/java/bjc/utils/funcdata/Tree.java b/BJC-Utils2/src/main/java/bjc/utils/funcdata/Tree.java index cd43df7..b56ff48 100644 --- a/BJC-Utils2/src/main/java/bjc/utils/funcdata/Tree.java +++ b/BJC-Utils2/src/main/java/bjc/utils/funcdata/Tree.java @@ -21,7 +21,7 @@ public class Tree implements ITree { private boolean hasChildren; - private int childCount; + private int childCount = 0; /** * Create a new leaf node in a tree @@ -43,21 +43,15 @@ public class Tree implements ITree { * @param childrn * A list of children for this node */ - @SafeVarargs - public Tree(ContainedType leafToken, ITree... childrn) { + public Tree(ContainedType leafToken, + IFunctionalList> childrn) { data = leafToken; hasChildren = true; - childCount = 0; - - children = new FunctionalList<>(); - - for (ITree child : childrn) { - children.add(child); + childCount = childrn.getSize(); - childCount++; - } + children = childrn; } /** @@ -68,15 +62,21 @@ public class Tree implements ITree { * @param childrn * A list of children for this node */ - public Tree(ContainedType leafToken, - IFunctionalList> childrn) { + @SafeVarargs + public Tree(ContainedType leafToken, ITree... childrn) { data = leafToken; hasChildren = true; - childCount = childrn.getSize(); + childCount = 0; - children = childrn; + children = new FunctionalList<>(); + + for (ITree child : childrn) { + children.add(child); + + childCount++; + } } @Override @@ -92,28 +92,6 @@ public class Tree implements ITree { children.add(child); } - @Override - public TransformedType transformHead( - Function transformer) { - return transformer.apply(data); - } - - @Override - public int getChildrenCount() { - return childCount; - } - - @Override - public TransformedType transformChild(int childNo, - Function, TransformedType> transformer) { - if (childNo < 0 || childNo > (childCount - 1)) { - throw new IllegalArgumentException( - "Child index #" + childNo + " is invalid"); - } - - return transformer.apply(children.getByIndex(childNo)); - } - @Override public ReturnedType collapse( Function leafTransform, @@ -124,23 +102,9 @@ public class Tree implements ITree { .apply(internalCollapse(leafTransform, nodeCollapser)); } - protected NewType internalCollapse( - Function leafTransform, - Function, NewType>> nodeCollapser) { - if (hasChildren) { - Function, NewType> nodeTransformer = - nodeCollapser.apply(data); - - IFunctionalList collapsedChildren = - children.map((child) -> { - return child.collapse(leafTransform, nodeCollapser, - (subTreeVal) -> subTreeVal); - }); - - return nodeTransformer.apply(collapsedChildren); - } - - return leafTransform.apply(data); + @Override + public void doForChildren(Consumer> action) { + children.forEach(action); } @Override @@ -159,68 +123,44 @@ public class Tree implements ITree { } @Override - public void selectiveTransform(Predicate nodePicker, - UnaryOperator transformer) { - if (hasChildren) { - children.forEach((child) -> child - .selectiveTransform(nodePicker, transformer)); - } else { - data = transformer.apply(data); - } + public int getChildrenCount() { + return childCount; } - @Override - public ITree transformTree( - Function transformer) { + protected NewType internalCollapse( + Function leafTransform, + Function, NewType>> nodeCollapser) { if (hasChildren) { - IFunctionalList> transformedChildren = - children.map( - (child) -> child.transformTree(transformer)); + Function, NewType> nodeTransformer = + nodeCollapser.apply(data); - return new Tree<>(transformer.apply(data), - transformedChildren); + IFunctionalList collapsedChildren = + children.map((child) -> { + return child.collapse(leafTransform, nodeCollapser, + (subTreeVal) -> subTreeVal); + }); + + return nodeTransformer.apply(collapsedChildren); } - return new Tree<>(transformer.apply(data)); + return leafTransform.apply(data); } - @Override - public void traverse(TreeLinearizationMethod linearizationMethod, - Consumer action) { - if (hasChildren) { - switch (linearizationMethod) { - case INORDER: - if (childCount != 2) { - throw new IllegalArgumentException( - "Can only do in-order traversal for binary trees."); - } - - children.getByIndex(0).traverse(linearizationMethod, - action); - - action.accept(data); - - children.getByIndex(1).traverse(linearizationMethod, - action); - break; - case POSTORDER: - children.forEach((child) -> child - .traverse(linearizationMethod, action)); - - action.accept(data); - break; - case PREORDER: - action.accept(data); + protected void internalToString(StringBuilder builder, int indentLevel, + boolean initial) { + if (!initial) { + StringUtils.indentNLevels(builder, indentLevel); + } - children.forEach((child) -> child - .traverse(linearizationMethod, action)); - break; - default: - break; + builder.append("Node: "); + builder.append(data == null ? "(null)" : data.toString()); + builder.append("\n"); - } - } else { - action.accept(data); + if (hasChildren) { + children.forEach((child) -> { + ((Tree) child).internalToString(builder, + indentLevel + 2, false); + }); } } @@ -243,31 +183,13 @@ public class Tree implements ITree { } @Override - public String toString() { - StringBuilder builder = new StringBuilder(); - - internalToString(builder, 1, true); - - builder.deleteCharAt(builder.length() - 1); - - return builder.toString(); - } - - protected void internalToString(StringBuilder builder, int indentLevel, - boolean initial) { - if (!initial) { - StringUtils.indentNLevels(builder, indentLevel); - } - - builder.append("Node: "); - builder.append(data == null ? "(null)" : data.toString()); - builder.append("\n"); - + public void selectiveTransform(Predicate nodePicker, + UnaryOperator transformer) { if (hasChildren) { - children.forEach((child) -> { - ((Tree) child).internalToString(builder, - indentLevel + 2, false); - }); + children.forEach((child) -> child + .selectiveTransform(nodePicker, transformer)); + } else { + data = transformer.apply(data); } } @@ -312,4 +234,87 @@ public class Tree implements ITree { } } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + + internalToString(builder, 1, true); + + builder.deleteCharAt(builder.length() - 1); + + return builder.toString(); + } + + @Override + public TransformedType transformChild(int childNo, + Function, TransformedType> transformer) { + if (childNo < 0 || childNo > (childCount - 1)) { + throw new IllegalArgumentException( + "Child index #" + childNo + " is invalid"); + } + + return transformer.apply(children.getByIndex(childNo)); + } + + @Override + public TransformedType transformHead( + Function transformer) { + return transformer.apply(data); + } + + @Override + public ITree transformTree( + Function transformer) { + if (hasChildren) { + IFunctionalList> transformedChildren = + children.map( + (child) -> child.transformTree(transformer)); + + return new Tree<>(transformer.apply(data), + transformedChildren); + } + + return new Tree<>(transformer.apply(data)); + } + + @Override + public void traverse(TreeLinearizationMethod linearizationMethod, + Consumer action) { + if (hasChildren) { + switch (linearizationMethod) { + case INORDER: + if (childCount != 2) { + throw new IllegalArgumentException( + "Can only do in-order traversal for binary trees."); + } + + children.getByIndex(0).traverse(linearizationMethod, + action); + + action.accept(data); + + children.getByIndex(1).traverse(linearizationMethod, + action); + break; + case POSTORDER: + children.forEach((child) -> child + .traverse(linearizationMethod, action)); + + action.accept(data); + break; + case PREORDER: + action.accept(data); + + children.forEach((child) -> child + .traverse(linearizationMethod, action)); + break; + default: + break; + + } + } else { + action.accept(data); + } + } } diff --git a/BJC-Utils2/src/main/java/bjc/utils/funcutils/StringUtils.java b/BJC-Utils2/src/main/java/bjc/utils/funcutils/StringUtils.java index c58a42b..1d1838e 100644 --- a/BJC-Utils2/src/main/java/bjc/utils/funcutils/StringUtils.java +++ b/BJC-Utils2/src/main/java/bjc/utils/funcutils/StringUtils.java @@ -1,5 +1,7 @@ package bjc.utils.funcutils; +import java.util.Deque; + /** * Utility methods for operations on strings * @@ -71,4 +73,8 @@ public class StringUtils { builder.append("\t"); } } + + public static String printDeque(Deque queuedTrees) { + return queuedTrees.isEmpty() ? "(none)" : queuedTrees.toString(); + } } diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/ShuntingYard.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/ShuntingYard.java index 9c7618b..0e34b97 100644 --- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/ShuntingYard.java +++ b/BJC-Utils2/src/main/java/bjc/utils/parserutils/ShuntingYard.java @@ -87,7 +87,9 @@ public class ShuntingYard { stack.push(token); } else if (StringUtils.containsOnly(token, "\\)")) { // Handle groups of parenthesis for multiple nesting levels - while (stack.peek().equals(token.replace(')', '('))) { + String swappedToken = token.replace(')', '('); + + while (!stack.peek().equals(swappedToken)) { output.add(transform.apply(stack.pop())); } @@ -98,21 +100,6 @@ public class ShuntingYard { } } - private static boolean shouldConfigureBasicOperators = true; - - /** - * Set whether the shunter should configure the four basic math - * operators - * - * @param configureBasicOperators - * Whether or not the four basic math operators should be - * configured - */ - public static void setBasicOperatorConfiguration( - boolean configureBasicOperators) { - shouldConfigureBasicOperators = configureBasicOperators; - } - /** * Holds all the shuntable operations */ @@ -120,11 +107,12 @@ public class ShuntingYard { /** * Create a new shunting yard with a default set of operators + * @param configureBasics Whether or not basic math operators should be provided */ - public ShuntingYard() { + public ShuntingYard(boolean configureBasics) { operators = new FunctionalMap<>(); - if (shouldConfigureBasicOperators) { + if (configureBasics) { operators.put("+", Operator.ADD); operators.put("-", Operator.SUBTRACT); operators.put("*", Operator.MULTIPLY); @@ -165,11 +153,15 @@ public class ShuntingYard { String rightOperator) { boolean operatorExists = operators.containsKey(rightOperator); + if (!operatorExists) { + return false; + } + boolean hasHigherPrecedence = operators.get(rightOperator).getPrecedence() >= operators .get(leftOperator).getPrecedence(); - return (operatorExists && hasHigherPrecedence); + return hasHigherPrecedence; } /** diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/TokenTransformer.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/TokenTransformer.java index 4db5e76..c88763f 100644 --- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/TokenTransformer.java +++ b/BJC-Utils2/src/main/java/bjc/utils/parserutils/TokenTransformer.java @@ -11,6 +11,7 @@ import bjc.utils.data.IPair; import bjc.utils.data.Pair; import bjc.utils.funcdata.ITree; import bjc.utils.funcdata.Tree; +import bjc.utils.funcutils.StringUtils; final class TokenTransformer implements Consumer { private final class OperatorHandler @@ -34,7 +35,8 @@ final class TokenTransformer implements Consumer { ITree newAST; if (isSpecialOperator.test(element)) { - newAST = handleSpecialOperator.apply(queuedASTs); + newAST = handleSpecialOperator.apply(element) + .apply(queuedASTs); } else { if (queuedASTs.size() < 2) { throw new IllegalStateException( @@ -56,15 +58,15 @@ final class TokenTransformer implements Consumer { } } - private IHolder>, ITree>> initialState; - private Predicate operatorPredicate; - private Predicate isSpecialOperator; - private Function>, ITree> handleSpecialOperator; + private IHolder>, ITree>> initialState; + private Predicate operatorPredicate; + private Predicate isSpecialOperator; + private Function>, ITree>> handleSpecialOperator; public TokenTransformer( IHolder>, ITree>> initialState, Predicate operatorPredicate, Predicate isSpecialOperator, - Function>, ITree> handleSpecialOperator) { + Function>, ITree>> handleSpecialOperator) { this.initialState = initialState; this.operatorPredicate = operatorPredicate; this.isSpecialOperator = isSpecialOperator; diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/TreeConstructor.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/TreeConstructor.java index efd0394..152d4d9 100644 --- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/TreeConstructor.java +++ b/BJC-Utils2/src/main/java/bjc/utils/parserutils/TreeConstructor.java @@ -65,7 +65,7 @@ public class TreeConstructor { */ public static ITree constructTree(IFunctionalList tokens, Predicate operatorPredicate, Predicate isSpecialOperator, - Function>, ITree> handleSpecialOperator) { + Function>, ITree>> handleSpecialOperator) { if (tokens == null) { throw new NullPointerException("Tokens must not be null"); } else if (operatorPredicate == null) { -- cgit v1.2.3