diff options
| author | bculkin2442 <bjculkin@mix.wvu.edu> | 2016-04-11 09:32:59 -0400 |
|---|---|---|
| committer | bculkin2442 <bjculkin@mix.wvu.edu> | 2016-04-11 09:32:59 -0400 |
| commit | f9283a20abd9eaed0b0436bc54c60576233121f4 (patch) | |
| tree | cec1323fb3faf1a4dcee2394a114b821c2366166 /BJC-Utils2/src/main | |
| parent | 275a627719fc2231b16caea41130ff09f0f2b6a1 (diff) | |
Added new method to pairs and holders
Diffstat (limited to 'BJC-Utils2/src/main')
10 files changed, 221 insertions, 54 deletions
diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/GenHolder.java b/BJC-Utils2/src/main/java/bjc/utils/data/GenHolder.java index e042554..bd87f07 100644 --- a/BJC-Utils2/src/main/java/bjc/utils/data/GenHolder.java +++ b/BJC-Utils2/src/main/java/bjc/utils/data/GenHolder.java @@ -105,4 +105,9 @@ public class GenHolder<T> implements IHolder<T> { return heldValue.toString(); } + + @Override + public <E> IHolder<E> bind(Function<T, IHolder<E>> binder) { + return binder.apply(heldValue); + } } diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/IHolder.java b/BJC-Utils2/src/main/java/bjc/utils/data/IHolder.java index 6290d5f..a4f4013 100644 --- a/BJC-Utils2/src/main/java/bjc/utils/data/IHolder.java +++ b/BJC-Utils2/src/main/java/bjc/utils/data/IHolder.java @@ -56,4 +56,15 @@ public interface IHolder<T> { * @return The mapped value outside of a GenHolder */ public <E> E unwrap(Function<T, E> unwrapper); + + /** + * Bind the value in this holder to a new value + * + * @param <E> + * The new type of the held value + * @param binder + * The function to do the binding with + * @return The bound value + */ + public <E> IHolder<E> bind(Function<T, IHolder<E>> binder); }
\ No newline at end of file diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/IPair.java b/BJC-Utils2/src/main/java/bjc/utils/data/IPair.java index e2ee6a4..a20ff36 100644 --- a/BJC-Utils2/src/main/java/bjc/utils/data/IPair.java +++ b/BJC-Utils2/src/main/java/bjc/utils/data/IPair.java @@ -14,7 +14,7 @@ import java.util.function.Function; * @param <R> * The type stored in the right side of the pair */ -public interface IPair<L, R> { +public interface IPair<L, R> { /** * Create a new pair by applying the given functions to the left/right. @@ -35,6 +35,22 @@ public interface IPair<L, R> { Function<R, R2> rightTransformer); /** + * Apply a function to the two internal values that returns a new pair. + * + * Is a monadic bind. + * + * @param <L2> + * The new left pair type + * @param <R2> + * The new right pair type + * @param binder + * The function to use as a bind + * @return The new pair + */ + public <L2, R2> IPair<L2, R2> + bind(BiFunction<L, R, IPair<L2, R2>> binder); + + /** * Execute an action with the values of this pair. Has no effect on the * internal contents * diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/Pair.java b/BJC-Utils2/src/main/java/bjc/utils/data/Pair.java index f721a9a..d0397f7 100644 --- a/BJC-Utils2/src/main/java/bjc/utils/data/Pair.java +++ b/BJC-Utils2/src/main/java/bjc/utils/data/Pair.java @@ -97,4 +97,10 @@ public class Pair<L, R> implements IPair<L, R> { public String toString() { return "pair[l=" + leftValue.toString() + ", r=" + rightValue.toString() + "]"; } + + @Override + public <L2, R2> IPair<L2, R2> + bind(BiFunction<L, R, IPair<L2, R2>> binder) { + return binder.apply(leftValue, rightValue); + } } diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/lazy/LazyHolder.java b/BJC-Utils2/src/main/java/bjc/utils/data/lazy/LazyHolder.java index 2ad8dbf..9f9dc4a 100644 --- a/BJC-Utils2/src/main/java/bjc/utils/data/lazy/LazyHolder.java +++ b/BJC-Utils2/src/main/java/bjc/utils/data/lazy/LazyHolder.java @@ -21,34 +21,100 @@ import bjc.utils.funcdata.IFunctionalList; * The type of the data being held */ public class LazyHolder<T> implements IHolder<T>, ILazy { - private final class LazyHolderSupplier<NewT> + private static final class LazyHolderHolder<T2> + implements IHolder<T2> { + private Supplier<IHolder<T2>> holderSource; + + private IHolder<T2> holder; + + private IFunctionalList<Function<T2, T2>> actions = new FunctionalList<>(); + + public LazyHolderHolder(Supplier<IHolder<T2>> source) { + + holderSource = source; + } + + @Override + public void doWith(Consumer<T2> action) { + actions.add((val) -> { + action.accept(val); + + return val; + }); + } + + @Override + public <NewT> IHolder<NewT> map(Function<T2, NewT> transformer) { + // TODO implement me + throw new UnsupportedOperationException( + "Mapping is not yet supported on bound holders"); + } + + @Override + public IHolder<T2> transform(Function<T2, T2> transformer) { + actions.add(transformer); + + return this; + } + + @Override + public <E> E unwrap(Function<T2, E> unwrapper) { + if (holder == null) { + holder = holderSource.get(); + } + + if (!actions.isEmpty()) { + actions.forEach((transform) -> { + holder.transform(transform); + }); + } + + return holder.unwrap(unwrapper); + } + + @Override + public <E> IHolder<E> bind(Function<T2, IHolder<E>> binder) { + return new LazyHolderHolder<>(() -> { + return binder.apply(unwrap((val) -> val)); + }); + } + + } + + private static final class LazyHolderSupplier<NewT, T2> implements Supplier<NewT> { - private IFunctionalList<Function<T, T>> pendingActions; - private Function<T, NewT> pendingTransform; + private IFunctionalList<Function<T2, T2>> pendingActions; + private Function<T2, NewT> pendingTransform; + + private T2 heldValue; + private Supplier<T2> heldSource; - public LazyHolderSupplier(IFunctionalList<Function<T, T>> actons, - Function<T, NewT> transform) { + public LazyHolderSupplier(IFunctionalList<Function<T2, T2>> actons, + Function<T2, NewT> transform, T2 heldValue, + Supplier<T2> heldSource) { // Resolve latent bug I just realized. After a map, adding new // actions to the original holder could've resulted in changes // to all unactualized mapped values from that holder pendingActions = new FunctionalList<>(); - for (Function<T, T> action : actons.toIterable()) { + for (Function<T2, T2> action : actons.toIterable()) { pendingActions.add(action); } this.pendingTransform = transform; + this.heldValue = heldValue; + this.heldSource = heldSource; } @Override public NewT get() { if (heldValue == null) { return pendingActions.reduceAux(heldSource.get(), - Function<T, T>::apply, pendingTransform::apply); + Function<T2, T2>::apply, pendingTransform::apply); } return pendingActions.reduceAux(heldValue, - Function<T, T>::apply, pendingTransform::apply); + Function<T2, T2>::apply, pendingTransform::apply); } } @@ -114,8 +180,8 @@ public class LazyHolder<T> implements IHolder<T>, ILazy { } // Don't actually map until we need to - return new LazyHolder<>( - new LazyHolderSupplier<>(actions, transform)); + return new LazyHolder<>(new LazyHolderSupplier<>(actions, + transform, heldValue, heldSource)); } @Override @@ -179,4 +245,11 @@ public class LazyHolder<T> implements IHolder<T>, ILazy { heldValue = action.apply(heldValue); }); } + + @Override + public <T2> IHolder<T2> bind(Function<T, IHolder<T2>> binder) { + return new LazyHolderHolder<>(() -> { + return binder.apply(unwrap((val) -> val)); + }); + } }
\ No newline at end of file diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/lazy/LazyPair.java b/BJC-Utils2/src/main/java/bjc/utils/data/lazy/LazyPair.java index e08c8fb..7ba7ee7 100644 --- a/BJC-Utils2/src/main/java/bjc/utils/data/lazy/LazyPair.java +++ b/BJC-Utils2/src/main/java/bjc/utils/data/lazy/LazyPair.java @@ -98,9 +98,9 @@ public class LazyPair<L, R> implements IPair<L, R>, ILazy { throw new NullPointerException("Transforms must be non-null"); } - IHolder<IPair<L2, R2>> newPair = - delegatePair.map((currentPair) -> currentPair - .apply(leftTransform, rightTransform)); + IHolder<IPair<L2, R2>> newPair = delegatePair + .map((currentPair) -> currentPair.apply(leftTransform, + rightTransform)); return new LazyPair<>(newPair, materialized, true); } @@ -169,4 +169,17 @@ public class LazyPair<L, R> implements IPair<L, R>, ILazy { materialized = true; pendingActions = false; } + + @Override + public <L2, R2> IPair<L2, R2> bind( + BiFunction<L, R, IPair<L2, R2>> binder) { + // TODO Auto-generated method stub + IHolder<IPair<L2, R2>> newDelegate = delegatePair + .map((pairVal) -> { + return pairVal.bind(binder); + }); + + return new LazyPair<>(newDelegate, isMaterialized(), + hasPendingActions()); + } }
\ No newline at end of file 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 a73292c..ac36d15 100644 --- a/BJC-Utils2/src/main/java/bjc/utils/funcutils/StringUtils.java +++ b/BJC-Utils2/src/main/java/bjc/utils/funcutils/StringUtils.java @@ -37,4 +37,24 @@ public class StringUtils { return input.matches("\\A(?:" + regex + ")+\\Z"); } + /** + * Checks if the given expression contains the specified operator in a + * situation that indicates its use as an infix operator. + * + * @param expression + * The expression to check + * @param operator + * The operator to see if it is contained + * @return Whether or not the given expression contains the specified + * operator as a infix operator + */ + public static boolean containsInfixOperator(String expression, + String operator) { + // Bit annoying to have to use a full class name, but what are you + // going to do? + return org.apache.commons.lang3.StringUtils + .countMatches(expression, operator) == 1 + && !expression.equalsIgnoreCase(operator) + && !expression.startsWith(operator); + } } diff --git a/BJC-Utils2/src/main/java/bjc/utils/gen/WeightedGrammar.java b/BJC-Utils2/src/main/java/bjc/utils/gen/WeightedGrammar.java index 37f31b0..8d31576 100644 --- a/BJC-Utils2/src/main/java/bjc/utils/gen/WeightedGrammar.java +++ b/BJC-Utils2/src/main/java/bjc/utils/gen/WeightedGrammar.java @@ -368,16 +368,19 @@ public class WeightedGrammar<E> { newRule.add(newCase); } - newRule.forEach( - (list) -> newResults - .add(new Pair<>( - pair.merge((left, right) -> left) - + additionalProbability, - list))); + newRule.forEach((list) -> { + Integer currentProb = pair.merge((left, right) -> left); + + newResults.add(new Pair<>( + currentProb + additionalProbability, list)); + }); }); - newResults.forEach((pair) -> pair - .doWith((left, right) -> addCase(ruleName, left, right))); + newResults.forEach((pair) -> { + pair.doWith((left, right) -> { + addCase(ruleName, left, right); + }); + }); } /** diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/AST.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/AST.java index 88b4862..b6c4d8c 100644 --- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/AST.java +++ b/BJC-Utils2/src/main/java/bjc/utils/parserutils/AST.java @@ -361,4 +361,26 @@ public class AST<T> { action.accept(token); } } + + /** + * Change the type of nodes in the tree without changing the structure + * + * @param <E> + * 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 <E> AST<E> rebuildTree(Function<T, E> nodeTransform, + Function<T, E> operatorTransform) { + return collapse((leafNode) -> { + E transformedNode = nodeTransform.apply(leafNode); + return new AST<>(transformedNode); + }, (operator) -> (AST<E> newLeft, AST<E> 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 46e4da4..68ec70e 100644 --- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/TreeConstructor.java +++ b/BJC-Utils2/src/main/java/bjc/utils/parserutils/TreeConstructor.java @@ -28,40 +28,38 @@ public class TreeConstructor { } @Override - public IPair<Deque<AST<T>>, AST<T>> - apply(IPair<Deque<AST<T>>, AST<T>> pair) { - Deque<AST<T>> queuedASTs = - pair.merge((queue, currentAST) -> queue); - - AST<T> mergedAST = pair.merge((queue, currentAST) -> { - AST<T> newAST; - - if (isSpecialOperator.test(element)) { - newAST = handleSpecialOperator.apply(queue); - } else { - if (queue.size() < 2) { - throw new IllegalStateException( - "Attempted to parse binary operator without enough operands.\n" - + "Problem operator is " - + element - + "\nPossible operand is: \n\t" - + queue.peek()); - } - - AST<T> rightAST = queue.pop(); - AST<T> leftAST = queue.pop(); - - newAST = new AST<>(element, leftAST, rightAST); + public IPair<Deque<AST<T>>, AST<T>> apply( + IPair<Deque<AST<T>>, AST<T>> pair) { + return pair.bind((queuedASTs, currentAST) -> { + return handleOperator(queuedASTs); + }); + } + + private IPair<Deque<AST<T>>, AST<T>> handleOperator( + Deque<AST<T>> queuedASTs) { + AST<T> newAST; + + if (isSpecialOperator.test(element)) { + newAST = handleSpecialOperator.apply(queuedASTs); + } else { + if (queuedASTs.size() < 2) { + throw new IllegalStateException( + "Attempted to parse binary operator without enough operands.\n" + + "Problem operator is " + + element + + "\nPossible operand is: \n\t" + + queuedASTs.peek()); } - queue.push(newAST); - return newAST; - }); + AST<T> rightAST = queuedASTs.pop(); + AST<T> leftAST = queuedASTs.pop(); + + newAST = new AST<>(element, leftAST, rightAST); + } - Pair<Deque<AST<T>>, AST<T>> newPair = - new Pair<>(queuedASTs, mergedAST); + queuedASTs.push(newAST); - return newPair; + return new Pair<>(queuedASTs, newAST); } } @@ -162,8 +160,8 @@ public class TreeConstructor { "Special operator determiner must not be null"); } - GenHolder<IPair<Deque<AST<T>>, AST<T>>> initialState = - new GenHolder<>(new Pair<>(new LinkedList<>(), null)); + GenHolder<IPair<Deque<AST<T>>, AST<T>>> initialState = new GenHolder<>( + new Pair<>(new LinkedList<>(), null)); tokens.forEach( new TokenTransformer<>(initialState, operatorPredicate, |
