From a5850915df72f5968fd1b281eb9e455d50c580ee Mon Sep 17 00:00:00 2001 From: bculkin2442 Date: Wed, 13 Apr 2016 23:15:28 -0400 Subject: Fixed examples using trees --- .../src/main/java/bjc/utils/parserutils/AST.java | 386 --------------------- .../bjc/utils/parserutils/TreeConstructor.java | 44 +-- 2 files changed, 23 insertions(+), 407 deletions(-) delete mode 100644 BJC-Utils2/src/main/java/bjc/utils/parserutils/AST.java (limited to 'BJC-Utils2/src/main/java/bjc') diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/AST.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/AST.java deleted file mode 100644 index 4625807..0000000 --- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/AST.java +++ /dev/null @@ -1,386 +0,0 @@ -package bjc.utils.parserutils; - -import java.util.function.BinaryOperator; -import java.util.function.Consumer; -import java.util.function.Function; -import java.util.function.Predicate; -import java.util.function.UnaryOperator; - -import bjc.utils.funcdata.bst.TreeLinearizationMethod; - -/** - * A simple binary tree meant for use as an AST - * - * @author ben - * - * @param - * The type of token in this AST - */ -public class AST { - /** - * Indent a string n levels - * - * @param builder - * The string to indent - * @param levels - * The number of levels to indent - */ - protected static void indentNLevels(StringBuilder builder, - int levels) { - for (int i = 0; i <= levels; i++) { - builder.append("\t"); - } - } - - private AST left; - private AST right; - - private T token; - - /** - * Create a new leaf AST node - * - * @param tokn - * The token in this node - */ - public AST(T tokn) { - token = tokn; - - left = null; - right = null; - } - - /** - * Create a new AST node with the specified data and children - * - * @param tokn - * The token in this node - * @param lft - * The left child of this AST - * @param rght - * The right child of this AST - */ - public AST(T tokn, AST lft, AST rght) { - token = tokn; - - left = lft; - right = rght; - } - - /** - * Apply an action to the head node of this AST - * - * @param - * The type of the returned value - * @param headAction - * The action to apply to the head node - * @return The result of applying the action - */ - public E applyToHead(Function headAction) { - if (headAction == null) { - throw new NullPointerException("Action must not be null"); - } - - return headAction.apply(token); - } - - /** - * Apply an action to the left side of this AST - * - * @param - * The type of the returned value - * @param leftAction - * The action to apply to the left side - * @return The result of applying the action - */ - public E applyToLeft(Function, E> leftAction) { - if (leftAction == null) { - throw new NullPointerException("Action must not be null"); - } - - return leftAction.apply(left); - } - - /** - * Apply an action to the right side of this AST - * - * @param - * The type of the returned value - * @param rightAction - * The action to apply to the right side - * @return The result of applying the action - */ - public E applyToRight(Function, E> rightAction) { - if (rightAction == null) { - throw new NullPointerException("Action must not be null"); - } - - return rightAction.apply(right); - } - - /** - * Collapse this tree into a single node - * - * @param - * The final value of the collapsed tree - * @param - * - * @param tokenTransformer - * The function to transform nodes into data - * @param nodeTransformer - * A map of functions for operator collapsing - * @param resultTransformer - * The function for transforming the result - * @return The collapsed value of the tree - */ - @SuppressWarnings("unchecked") - public E collapse(Function tokenTransformer, - Function> nodeTransformer, - Function resultTransformer) { - if (tokenTransformer == null) { - throw new NullPointerException( - "Token transformer must not be null"); - } else if (nodeTransformer == null) { - throw new NullPointerException( - "Node transformer must not be null"); - } - - if (resultTransformer != null) { - return resultTransformer.apply( - internalCollapse(tokenTransformer, nodeTransformer)); - } - - // This is valid because if the user passes null as the last - // parameter, E will be inferred as Object, but will actually - // be T2 - return (E) internalCollapse(tokenTransformer, nodeTransformer); - } - - private T2 collapseBranches(Function tokenTransformer, - Function> nodeTransformer) { - T2 leftCollapsed; - - if (left == null) { - leftCollapsed = null; - } else { - leftCollapsed = left.internalCollapse(tokenTransformer, - nodeTransformer); - } - - T2 rightCollapsed; - - if (right == null) { - rightCollapsed = null; - } else { - rightCollapsed = right.internalCollapse(tokenTransformer, - nodeTransformer); - } - - return nodeTransformer.apply(token).apply(leftCollapsed, - rightCollapsed); - } - - /** - * Expand the nodes in an AST - * - * This is actually equivalent to converting the tree into an ordered - * list, doing a flatMap, and then reconstructing the tree - * - * @param expander - * The function to use for expanding nodes - * @return The expanded AST - */ - public AST flatMapTree(Function> expander) { - if (expander == null) { - throw new NullPointerException("Expander must not be null"); - } - - return collapse(expander, (operator) -> (leftAST, rightAST) -> { - return new AST<>(operator, leftAST, rightAST); - }, null); - } - - /* - * Internal recursive collapser - */ - protected T2 internalCollapse(Function tokenTransformer, - Function> nodeTransformer) { - if (left == null && right == null) { - return tokenTransformer.apply(token); - } - - return collapseBranches(tokenTransformer, nodeTransformer); - } - - /** - * Internal version of toString for proper rendering - * - * @param builder - * The string rendering being built - * @param indentLevel - * The current level to indent the tree - */ - protected void internalToString(StringBuilder builder, - int indentLevel) { - indentNLevels(builder, indentLevel); - - if (left == null && right == null) { - builder.append("Node: "); - builder.append(token.toString()); - builder.append("\n"); - } else { - builder.append("Node: "); - builder.append(token.toString()); - builder.append("\n"); - - if (left != null) { - left.internalToString(builder, indentLevel + 2); - } else { - indentNLevels(builder, indentLevel + 2); - builder.append("No left node\n"); - } - if (right != null) { - right.internalToString(builder, indentLevel + 2); - } else { - indentNLevels(builder, indentLevel + 2); - builder.append("No right node\n"); - } - } - } - - /** - * Execute a transform on selective nodes of the tree - * - * @param transformerPredicate - * The predicate to pick nodes to transform - * @param transformer - * The thing to use to transform the nodes - */ - public void selectiveTransform(Predicate transformerPredicate, - UnaryOperator transformer) { - if (transformerPredicate == null) { - throw new NullPointerException("Predicate must not be null"); - } else if (transformer == null) { - throw new NullPointerException("Transformer must not be null"); - } - - if (transformerPredicate.test(token)) { - token = transformer.apply(token); - } - - if (left != null) { - left.selectiveTransform(transformerPredicate, transformer); - } - - if (right != null) { - right.selectiveTransform(transformerPredicate, transformer); - } - } - - @Override - public String toString() { - StringBuilder builder = new StringBuilder(); - - internalToString(builder, -1); - - builder.deleteCharAt(builder.length() - 1); - - return builder.toString(); - } - - /** - * Transmute the tokens in an AST into a different sort of token - * - * @param - * The type of the transformed tokens - * - * @param tokenTransformer - * The transform to run on the tokens - * @return The AST with transformed tokens - */ - public AST transmuteAST(Function tokenTransformer) { - if (tokenTransformer == null) { - throw new NullPointerException("Transformer must not be null"); - } - - AST leftBranch = null; - AST rightBranch = null; - - if (left != null) { - leftBranch = left.transmuteAST(tokenTransformer); - } - - if (right != null) { - rightBranch = right.transmuteAST(tokenTransformer); - } - - return new AST<>(tokenTransformer.apply(token), leftBranch, - rightBranch); - } - - /** - * Traverse an AST - * - * @param linearizationMethod - * The way to traverse the tree - * @param action - * The function to call on each traversed element - */ - public void traverse(TreeLinearizationMethod linearizationMethod, - Consumer action) { - if (linearizationMethod == null) { - throw new NullPointerException( - "Linearization method must not be null"); - } else if (action == null) { - throw new NullPointerException("Action must not be null"); - } - - if (left != null && right != null) { - switch (linearizationMethod) { - case INORDER: - left.traverse(linearizationMethod, action); - action.accept(token); - right.traverse(linearizationMethod, action); - break; - case POSTORDER: - left.traverse(linearizationMethod, action); - right.traverse(linearizationMethod, action); - action.accept(token); - break; - case PREORDER: - action.accept(token); - left.traverse(linearizationMethod, action); - right.traverse(linearizationMethod, action); - break; - default: - throw new IllegalArgumentException( - "Got a invalid tree linearizer " - + linearizationMethod + ". WAT"); - } - } else { - action.accept(token); - } - } - - /** - * Change the type of nodes in the tree without changing the structure - * - * @param - * The new node type - * @param nodeTransform - * The transform to apply to leaf nodes - * @param operatorTransform - * The transform to apply to operator nodes - * @return An AST with the node types transformed - */ - public AST rebuildTree(Function nodeTransform, - Function operatorTransform) { - return collapse((leafNode) -> { - E transformedNode = nodeTransform.apply(leafNode); - return new AST<>(transformedNode); - }, (operator) -> (AST newLeft, AST newRight) -> { - return new AST<>(operatorTransform.apply(operator), newLeft, - newRight); - }, (resultValue) -> resultValue); - } -} 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 088430b..52299bb 100644 --- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/TreeConstructor.java +++ b/BJC-Utils2/src/main/java/bjc/utils/parserutils/TreeConstructor.java @@ -12,6 +12,8 @@ import bjc.utils.data.experimental.IPair; import bjc.utils.data.experimental.Identity; import bjc.utils.data.experimental.Pair; import bjc.utils.funcdata.IFunctionalList; +import bjc.utils.funcdata.ITree; +import bjc.utils.funcdata.Tree; /** * Creates a parse tree from a postfix expression @@ -21,8 +23,8 @@ import bjc.utils.funcdata.IFunctionalList; */ public class TreeConstructor { private static final class TokenTransformer implements Consumer { - private final class OperatorHandler - implements UnaryOperator>, AST>> { + private final class OperatorHandler implements + UnaryOperator>, ITree>> { private T element; public OperatorHandler(T element) { @@ -30,16 +32,16 @@ public class TreeConstructor { } @Override - public IPair>, AST> apply( - IPair>, AST> pair) { + public IPair>, ITree> apply( + IPair>, ITree> pair) { return pair.bind((queuedASTs, currentAST) -> { return handleOperator(queuedASTs); }); } - private IPair>, AST> handleOperator( - Deque> queuedASTs) { - AST newAST; + private IPair>, ITree> handleOperator( + Deque> queuedASTs) { + ITree newAST; if (isSpecialOperator.test(element)) { newAST = handleSpecialOperator.apply(queuedASTs); @@ -52,10 +54,10 @@ public class TreeConstructor { + queuedASTs.peek()); } - AST rightAST = queuedASTs.pop(); - AST leftAST = queuedASTs.pop(); + ITree rightAST = queuedASTs.pop(); + ITree leftAST = queuedASTs.pop(); - newAST = new AST<>(element, leftAST, rightAST); + newAST = new Tree<>(element, leftAST, rightAST); } queuedASTs.push(newAST); @@ -64,16 +66,16 @@ public class TreeConstructor { } } - private IHolder>, AST>> initialState; - private Predicate operatorPredicate; - private Predicate isSpecialOperator; - private Function>, AST> handleSpecialOperator; + private IHolder>, ITree>> initialState; + private Predicate operatorPredicate; + private Predicate isSpecialOperator; + private Function>, ITree> handleSpecialOperator; public TokenTransformer( - IHolder>, AST>> initialState, + IHolder>, ITree>> initialState, Predicate operatorPredicate, Predicate isSpecialOperator, - Function>, AST> handleSpecialOperator) { + Function>, ITree> handleSpecialOperator) { this.initialState = initialState; this.operatorPredicate = operatorPredicate; this.isSpecialOperator = isSpecialOperator; @@ -85,7 +87,7 @@ public class TreeConstructor { if (operatorPredicate.test(element)) { initialState.transform(new OperatorHandler(element)); } else { - AST newAST = new AST<>(element); + ITree newAST = new Tree<>(element); initialState.doWith((pair) -> { pair.doWith((queue, currentAST) -> { @@ -116,7 +118,7 @@ public class TreeConstructor { * operator * @return A AST from the expression */ - public static AST constructTree(IFunctionalList tokens, + public static ITree constructTree(IFunctionalList tokens, Predicate operatorPredicate) { return constructTree(tokens, operatorPredicate, (op) -> false, null); @@ -146,9 +148,9 @@ public class TreeConstructor { * interface. Maybe there's a better way to express how that * works */ - public static AST constructTree(IFunctionalList tokens, + public static ITree constructTree(IFunctionalList tokens, Predicate operatorPredicate, Predicate isSpecialOperator, - Function>, AST> handleSpecialOperator) { + Function>, ITree> handleSpecialOperator) { if (tokens == null) { throw new NullPointerException("Tokens must not be null"); } else if (operatorPredicate == null) { @@ -159,7 +161,7 @@ public class TreeConstructor { "Special operator determiner must not be null"); } - IHolder>, AST>> initialState = new Identity<>( + IHolder>, ITree>> initialState = new Identity<>( new Pair<>(new LinkedList<>(), null)); tokens.forEach( -- cgit v1.2.3