diff options
Diffstat (limited to 'BJC-Utils2/src/main/java/bjc/utils/parserutils/delims')
7 files changed, 260 insertions, 272 deletions
diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/delims/DelimiterException.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/delims/DelimiterException.java index 3aba434..071afb4 100644 --- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/delims/DelimiterException.java +++ b/BJC-Utils2/src/main/java/bjc/utils/parserutils/delims/DelimiterException.java @@ -5,12 +5,17 @@ package bjc.utils.parserutils.delims; */ public class DelimiterException extends RuntimeException { /** + * + */ + private static final long serialVersionUID = 2079514406049040888L; + + /** * Create a new generic delimiter exception. - * + * * @param res * The reason for this exception. */ - public DelimiterException(String res) { + public DelimiterException(final String res) { super(res); } }
\ No newline at end of file diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/delims/DelimiterGroup.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/delims/DelimiterGroup.java index db6ae8c..85d4038 100644 --- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/delims/DelimiterGroup.java +++ b/BJC-Utils2/src/main/java/bjc/utils/parserutils/delims/DelimiterGroup.java @@ -1,12 +1,5 @@ package bjc.utils.parserutils.delims; -import bjc.utils.data.IPair; -import bjc.utils.data.ITree; -import bjc.utils.data.Pair; -import bjc.utils.data.Tree; -import bjc.utils.funcdata.FunctionalList; -import bjc.utils.funcdata.IList; - import java.util.Arrays; import java.util.Deque; import java.util.HashMap; @@ -18,9 +11,16 @@ import java.util.Set; import java.util.function.BiPredicate; import java.util.function.Function; +import bjc.utils.data.IPair; +import bjc.utils.data.ITree; +import bjc.utils.data.Pair; +import bjc.utils.data.Tree; +import bjc.utils.funcdata.FunctionalList; +import bjc.utils.funcdata.IList; + /** * Represents a possible delimiter group to match. - * + * * @author EVE * * @param <T> @@ -29,29 +29,29 @@ import java.util.function.Function; public class DelimiterGroup<T> { /** * Represents an instance of a delimiter group. - * + * * @author EVE * */ public class OpenGroup { - private Deque<ITree<T>> contents; + private final Deque<ITree<T>> contents; private IList<ITree<T>> currentGroup; - private T opener; + private final T opener; - private T[] params; + private final T[] params; /** * Create a new instance of a delimiter group. - * + * * @param open * The item that opened this group. - * + * * @param parms * Any parameters from the opener. */ - public OpenGroup(T open, T[] parms) { + public OpenGroup(final T open, final T[] parms) { opener = open; params = parms; @@ -62,36 +62,36 @@ public class DelimiterGroup<T> { /** * Add an item to this group instance. - * + * * @param itm * The item to add to this group instance. */ - public void addItem(ITree<T> itm) { + public void addItem(final ITree<T> itm) { currentGroup.add(itm); } /** * Mark a subgroup. - * + * * @param marker * The item that indicated this subgroup. - * + * * @param chars * The characteristics for building the tree. */ - public void markSubgroup(T marker, SequenceCharacteristics<T> chars) { - ITree<T> subgroupContents = new Tree<>(chars.contents); - for(ITree<T> itm : currentGroup) { + public void markSubgroup(final T marker, final SequenceCharacteristics<T> chars) { + final ITree<T> subgroupContents = new Tree<>(chars.contents); + for (final ITree<T> itm : currentGroup) { subgroupContents.addChild(itm); } - while(!contents.isEmpty()) { - ITree<T> possibleSubordinate = contents.peek(); + while (!contents.isEmpty()) { + final ITree<T> possibleSubordinate = contents.peek(); - if(possibleSubordinate.getHead().equals(chars.subgroup)) { - T otherMarker = possibleSubordinate.getChild(1).getHead(); + if (possibleSubordinate.getHead().equals(chars.subgroup)) { + final T otherMarker = possibleSubordinate.getChild(1).getHead(); - if(subgroups.get(marker) > subgroups.get(otherMarker)) { + if (subgroups.get(marker) > subgroups.get(otherMarker)) { subgroupContents.prependChild(contents.pop()); } else { break; @@ -101,7 +101,7 @@ public class DelimiterGroup<T> { } } - Tree<T> subgroup = new Tree<>(chars.subgroup, subgroupContents, new Tree<>(marker)); + final Tree<T> subgroup = new Tree<>(chars.subgroup, subgroupContents, new Tree<>(marker)); //System.out.println("\tTRACE: generated subgroup\n" + subgroup + "\n\n"); contents.push(subgroup); @@ -111,26 +111,26 @@ public class DelimiterGroup<T> { /** * Convert this group into a tree. - * + * * @param closer * The item that closed this group. - * + * * @param chars * The characteristics for building the tree. - * + * * @return This group as a tree. */ - public ITree<T> toTree(T closer, SequenceCharacteristics<T> chars) { - if(impliedSubgroups.containsKey(closer)) { + public ITree<T> toTree(final T closer, final SequenceCharacteristics<T> chars) { + if (impliedSubgroups.containsKey(closer)) { markSubgroup(impliedSubgroups.get(closer), chars); } - ITree<T> res = new Tree<>(chars.contents); + final ITree<T> res = new Tree<>(chars.contents); - if(contents.isEmpty()) { + if (contents.isEmpty()) { currentGroup.forEach(res::addChild); } else { - while(!contents.isEmpty()) { + while (!contents.isEmpty()) { res.prependChild(contents.poll()); } @@ -142,7 +142,7 @@ public class DelimiterGroup<T> { @Override public String toString() { - StringBuilder builder = new StringBuilder(); + final StringBuilder builder = new StringBuilder(); builder.append("OpenGroup [contents="); builder.append(contents); @@ -157,34 +157,30 @@ public class DelimiterGroup<T> { /** * Check if a group is excluded at the top level of this group. - * + * * @param groupName * The group to check. - * + * * @return Whether or not the provided group is excluded. */ - public boolean excludes(T groupName) { + public boolean excludes(final T groupName) { return topLevelExclusions.contains(groupName); } /** * Check if the provided delimiter would close this group. - * + * * @param del * The string to check as a closing delimiter. - * + * * @return Whether or not the provided delimiter closes this * group. */ - public boolean isClosing(T del) { - if(closingDelimiters.contains(del)) { - return true; - } + public boolean isClosing(final T del) { + if (closingDelimiters.contains(del)) return true; - for(BiPredicate<T, T[]> pred : predClosers) { - if(pred.test(del, params)) { - return true; - } + for (final BiPredicate<T, T[]> pred : predClosers) { + if (pred.test(del, params)) return true; } return closingDelimiters.contains(del); @@ -192,7 +188,7 @@ public class DelimiterGroup<T> { /** * Get the name of the group this is an instance of. - * + * * @return The name of the group this is an instance of. */ public T getName() { @@ -201,7 +197,7 @@ public class DelimiterGroup<T> { /** * Get the groups that aren't allowed at all in this group. - * + * * @return The groups that aren't allowed at all in this group. */ public Set<T> getNestingExclusions() { @@ -211,7 +207,7 @@ public class DelimiterGroup<T> { /** * Get the groups that are allowed to open anywhere inside this * group. - * + * * @return The groups allowed to open anywhere inside this * group. */ @@ -221,36 +217,32 @@ public class DelimiterGroup<T> { /** * Checks if a given token marks a subgroup. - * + * * @param tok * The token to check. - * + * * @return Whether or not the token marks a subgroup. */ - public boolean marksSubgroup(T tok) { + public boolean marksSubgroup(final T tok) { return subgroups.containsKey(tok); } /** * Checks if a given token opens a group. - * + * * @param marker * The token to check. - * + * * @return The name of the group T opens, or null if it doesn't * open one. */ - public IPair<T, T[]> doesOpen(T marker) { - if(openDelimiters.containsKey(marker)) { - return new Pair<>(openDelimiters.get(marker), null); - } + public IPair<T, T[]> doesOpen(final T marker) { + if (openDelimiters.containsKey(marker)) return new Pair<>(openDelimiters.get(marker), null); - for(Function<T, IPair<T, T[]>> pred : predOpeners) { - IPair<T, T[]> par = pred.apply(marker); + for (final Function<T, IPair<T, T[]>> pred : predOpeners) { + final IPair<T, T[]> par = pred.apply(marker); - if(par.getLeft() != null) { - return par; - } + if (par.getLeft() != null) return par; } return new Pair<>(null, null); @@ -258,7 +250,7 @@ public class DelimiterGroup<T> { /** * Check if this group starts a new nesting scope. - * + * * @return Whether this group starts a new nesting scope. */ public boolean isForgetful() { @@ -274,48 +266,48 @@ public class DelimiterGroup<T> { /* * The delimiters that open groups at the top level of this group. */ - private Map<T, T> openDelimiters; + private final Map<T, T> openDelimiters; /* * The delimiters that open groups inside of this group. */ - private Map<T, T> nestedOpenDelimiters; + private final Map<T, T> nestedOpenDelimiters; /* * The delimiters that close this group. */ - private Set<T> closingDelimiters; + private final Set<T> closingDelimiters; /* * The groups that can't occur in the top level of this group. */ - private Set<T> topLevelExclusions; + private final Set<T> topLevelExclusions; /* * The groups that can't occur anywhere inside this group. */ - private Set<T> groupExclusions; + private final Set<T> groupExclusions; /* * Mapping from sub-group delimiters, to any sub-groups enclosed in * them. */ - private Map<T, Integer> subgroups; + private final Map<T, Integer> subgroups; /* * Subgroups implied by a particular closing delimiter */ - private Map<T, T> impliedSubgroups; + private final Map<T, T> impliedSubgroups; /* * Allows more complex openings */ - private List<Function<T, IPair<T, T[]>>> predOpeners; + private final List<Function<T, IPair<T, T[]>>> predOpeners; /* * Allow more complex closings */ - private List<BiPredicate<T, T[]>> predClosers; + private final List<BiPredicate<T, T[]>> predClosers; /* * Whether or not this group starts a new nesting set. @@ -324,12 +316,12 @@ public class DelimiterGroup<T> { /** * Create a new empty delimiter group. - * + * * @param name * The name of the delimiter group */ - public DelimiterGroup(T name) { - if(name == null) throw new NullPointerException("Group name must not be null"); + public DelimiterGroup(final T name) { + if (name == null) throw new NullPointerException("Group name must not be null"); groupName = name; @@ -350,25 +342,25 @@ public class DelimiterGroup<T> { /** * Adds one or more delimiters that close this group. - * + * * @param closers * Delimiters that close this group. */ @SafeVarargs - public final void addClosing(T... closers) { - List<T> closerList = Arrays.asList(closers); + public final void addClosing(final T... closers) { + final List<T> closerList = Arrays.asList(closers); - for(T closer : closerList) { - if(closer == null) { + for (final T closer : closerList) { + if (closer == null) throw new NullPointerException("Closing delimiter must not be null"); - } else if(closer.equals("")) { + else if (closer.equals("")) /* * We can do this because equals works on * arbitrary objects, not just those of the same * type. */ throw new IllegalArgumentException("Empty string is not a valid exclusion"); - } else { + else { closingDelimiters.add(closer); } } @@ -377,23 +369,23 @@ public class DelimiterGroup<T> { /** * Adds one or more groups that cannot occur in the top level of this * group. - * + * * @param exclusions * The groups forbidden in the top level of this group. */ @SafeVarargs - public final void addTopLevelForbid(T... exclusions) { - for(T exclusion : exclusions) { - if(exclusion == null) { + public final void addTopLevelForbid(final T... exclusions) { + for (final T exclusion : exclusions) { + if (exclusion == null) throw new NullPointerException("Exclusion must not be null"); - } else if(exclusion.equals("")) { + else if (exclusion.equals("")) /* * We can do this because equals works on * arbitrary objects, not just those of the same * type. */ throw new IllegalArgumentException("Empty string is not a valid exclusion"); - } else { + else { topLevelExclusions.add(exclusion); } } @@ -401,23 +393,23 @@ public class DelimiterGroup<T> { /** * Adds one or more groups that cannot occur at all in this group. - * + * * @param exclusions * The groups forbidden inside this group. */ @SafeVarargs - public final void addGroupForbid(T... exclusions) { - for(T exclusion : exclusions) { - if(exclusion == null) { + public final void addGroupForbid(final T... exclusions) { + for (final T exclusion : exclusions) { + if (exclusion == null) throw new NullPointerException("Exclusion must not be null"); - } else if(exclusion.equals("")) { + else if (exclusion.equals("")) /* * We can do this because equals works on * arbitrary objects, not just those of the same * type. */ throw new IllegalArgumentException("Empty string is not a valid exclusion"); - } else { + else { groupExclusions.add(exclusion); } } @@ -425,85 +417,78 @@ public class DelimiterGroup<T> { /** * Adds sub-group markers to this group. - * + * * @param subgroup * The token to mark a sub-group. - * + * * @param priority * The priority of this sub-group. */ - public void addSubgroup(T subgroup, int priority) { - if(subgroup == null) { - throw new NullPointerException("Subgroup marker must not be null"); - } + public void addSubgroup(final T subgroup, final int priority) { + if (subgroup == null) throw new NullPointerException("Subgroup marker must not be null"); subgroups.put(subgroup, priority); } /** * Adds a marker that opens a group at the top level of this group. - * + * * @param opener * The marker that opens the group. - * + * * @param group * The group opened by the marker. */ - public void addOpener(T opener, T group) { - if(opener == null) { + public void addOpener(final T opener, final T group) { + if (opener == null) throw new NullPointerException("Opener must not be null"); - } else if(group == null) { - throw new NullPointerException("Group to open must not be null"); - } + else if (group == null) throw new NullPointerException("Group to open must not be null"); openDelimiters.put(opener, group); } /** * Adds a marker that opens a group inside of this group. - * + * * @param opener * The marker that opens the group. - * + * * @param group * The group opened by the marker. */ - public void addNestedOpener(T opener, T group) { - if(opener == null) { + public void addNestedOpener(final T opener, final T group) { + if (opener == null) throw new NullPointerException("Opener must not be null"); - } else if(group == null) { - throw new NullPointerException("Group to open must not be null"); - } + else if (group == null) throw new NullPointerException("Group to open must not be null"); nestedOpenDelimiters.put(opener, group); } /** * Mark a closing delimiter as implying a subgroup. - * + * * @param closer * The closing delimiter. - * + * * @param subgroup * The subgroup to imply. */ - public void implySubgroup(T closer, T subgroup) { - if(closer == null) { + public void implySubgroup(final T closer, final T subgroup) { + if (closer == null) throw new NullPointerException("Closer must not be null"); - } else if(subgroup == null) { + else if (subgroup == null) throw new NullPointerException("Subgroup must not be null"); - } else if(!closingDelimiters.contains(closer)) { + else if (!closingDelimiters.contains(closer)) throw new IllegalArgumentException(String.format("No closing delimiter '%s' defined", closer)); - } else if(!subgroups.containsKey(subgroup)) { + else if (!subgroups.containsKey(subgroup)) throw new IllegalArgumentException(String.format("No subgroup '%s' defined", subgroup)); - } impliedSubgroups.put(closer, subgroup); } @Override public String toString() { - StringBuilder builder = new StringBuilder(); + final StringBuilder builder = new StringBuilder(); builder.append("("); @@ -512,26 +497,26 @@ public class DelimiterGroup<T> { builder.append("], "); builder.append("closingDelimiters=["); - for(T closer : closingDelimiters) { + for (final T closer : closingDelimiters) { builder.append(closer + ","); } builder.deleteCharAt(builder.length() - 1); builder.append("]"); - if(topLevelExclusions != null && !topLevelExclusions.isEmpty()) { + if (topLevelExclusions != null && !topLevelExclusions.isEmpty()) { builder.append(", "); builder.append("topLevelExclusions=["); - for(T exclusion : topLevelExclusions) { + for (final T exclusion : topLevelExclusions) { builder.append(exclusion + ","); } builder.deleteCharAt(builder.length() - 1); builder.append("]"); } - if(groupExclusions != null && !groupExclusions.isEmpty()) { + if (groupExclusions != null && !groupExclusions.isEmpty()) { builder.append(", "); builder.append("groupExclusions=["); - for(T exclusion : groupExclusions) { + for (final T exclusion : groupExclusions) { builder.append(exclusion + ","); } builder.deleteCharAt(builder.length() - 1); @@ -545,47 +530,47 @@ public class DelimiterGroup<T> { /** * Open an instance of this group. - * + * * @param opener * The item that opened this group. - * + * * @param parms * The parameters that opened this group - * + * * @return An opened instance of this group. */ - public OpenGroup open(T opener, T[] parms) { + public OpenGroup open(final T opener, final T[] parms) { return new OpenGroup(opener, parms); } /** * Adds a predicated opener to the top level of this group. - * + * * @param pred * The predicate that defines the opener and its * parameters. */ - public void addPredOpener(Function<T, IPair<T, T[]>> pred) { + public void addPredOpener(final Function<T, IPair<T, T[]>> pred) { predOpeners.add(pred); } /** * Adds a predicated closer to the top level of this group. - * + * * @param pred * The predicate that defines the closer. */ - public void addPredCloser(BiPredicate<T, T[]> pred) { + public void addPredCloser(final BiPredicate<T, T[]> pred) { predClosers.add(pred); } /** * Set whether or not this group starts a new nesting set. - * + * * @param forgetful * Whether this group starts a new nesting set. */ - public void setForgetful(boolean forgetful) { + public void setForgetful(final boolean forgetful) { this.forgetful = forgetful; } }
\ No newline at end of file diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/delims/RegexCloser.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/delims/RegexCloser.java index dc94686..4b29949 100644 --- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/delims/RegexCloser.java +++ b/BJC-Utils2/src/main/java/bjc/utils/parserutils/delims/RegexCloser.java @@ -4,29 +4,29 @@ import java.util.function.BiPredicate; /** * A predicated closer for use with {@link RegexOpener}. - * + * * @author bjculkin * */ public class RegexCloser implements BiPredicate<String, String[]> { - private String rep; + private final String rep; /** * Create a new regex closer. - * + * * @param closer * The format string to use for closing. */ - public RegexCloser(String closer) { + public RegexCloser(final String closer) { rep = closer; } @Override - public boolean test(String closer, String[] params) { + public boolean test(final String closer, final String[] params) { /* * Confirm passing an array instead of a single var-arg. */ - String work = String.format(rep, (Object[]) params); + final String work = String.format(rep, (Object[]) params); return work.equals(closer); } diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/delims/RegexOpener.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/delims/RegexOpener.java index 7b4aac0..98c1dc1 100644 --- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/delims/RegexOpener.java +++ b/BJC-Utils2/src/main/java/bjc/utils/parserutils/delims/RegexOpener.java @@ -1,46 +1,46 @@ package bjc.utils.parserutils.delims; -import bjc.utils.data.IPair; -import bjc.utils.data.Pair; - import java.util.function.Function; import java.util.regex.Matcher; import java.util.regex.Pattern; +import bjc.utils.data.IPair; +import bjc.utils.data.Pair; + /** * A predicated opener for use with {@link RegexOpener} - * + * * @author bjculkin * */ public class RegexOpener implements Function<String, IPair<String, String[]>> { - private String name; + private final String name; - private Pattern patt; + private final Pattern patt; /** * Create a new regex opener. - * + * * @param groupName * The name of the opened group. - * + * * @param groupRegex * The regex that matches the opener. */ - public RegexOpener(String groupName, String groupRegex) { + public RegexOpener(final String groupName, final String groupRegex) { name = groupName; patt = Pattern.compile(groupRegex); } @Override - public IPair<String, String[]> apply(String str) { - Matcher m = patt.matcher(str); + public IPair<String, String[]> apply(final String str) { + final Matcher m = patt.matcher(str); if (m.matches()) { - int numGroups = m.groupCount(); + final int numGroups = m.groupCount(); - String[] parms = new String[numGroups + 1]; + final String[] parms = new String[numGroups + 1]; for (int i = 0; i <= numGroups; i++) { parms[i] = m.group(i); diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/delims/SequenceCharacteristics.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/delims/SequenceCharacteristics.java index 5dcda2d..882b4c5 100644 --- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/delims/SequenceCharacteristics.java +++ b/BJC-Utils2/src/main/java/bjc/utils/parserutils/delims/SequenceCharacteristics.java @@ -2,7 +2,7 @@ package bjc.utils.parserutils.delims; /** * Marks the parameters for building a sequence tree. - * + * * @author EVE * * @param <T> @@ -27,7 +27,7 @@ public class SequenceCharacteristics<T> { /** * Create a new set of parameters for building a tree. - * + * * @param root * The root marker. * @param contents @@ -35,7 +35,7 @@ public class SequenceCharacteristics<T> { * @param subgroup * The subgroup marker. */ - public SequenceCharacteristics(T root, T contents, T subgroup) { + public SequenceCharacteristics(final T root, final T contents, final T subgroup) { this.root = root; this.contents = contents; this.subgroup = subgroup; @@ -46,39 +46,39 @@ public class SequenceCharacteristics<T> { final int prime = 31; int result = 1; - result = prime * result + ((contents == null) ? 0 : contents.hashCode()); - result = prime * result + ((root == null) ? 0 : root.hashCode()); - result = prime * result + ((subgroup == null) ? 0 : subgroup.hashCode()); + result = prime * result + (contents == null ? 0 : contents.hashCode()); + result = prime * result + (root == null ? 0 : root.hashCode()); + result = prime * result + (subgroup == null ? 0 : subgroup.hashCode()); return result; } @Override - public boolean equals(Object obj) { - if(this == obj) return true; - if(obj == null) return false; - if(!(obj instanceof SequenceCharacteristics)) return false; + public boolean equals(final Object obj) { + if (this == obj) return true; + if (obj == null) return false; + if (!(obj instanceof SequenceCharacteristics)) return false; - SequenceCharacteristics<?> other = (SequenceCharacteristics<?>) obj; + final SequenceCharacteristics<?> other = (SequenceCharacteristics<?>) obj; - if(contents == null) { - if(other.contents != null) return false; - } else if(!contents.equals(other.contents)) return false; + if (contents == null) { + if (other.contents != null) return false; + } else if (!contents.equals(other.contents)) return false; - if(root == null) { - if(other.root != null) return false; - } else if(!root.equals(other.root)) return false; + if (root == null) { + if (other.root != null) return false; + } else if (!root.equals(other.root)) return false; - if(subgroup == null) { - if(other.subgroup != null) return false; - } else if(!subgroup.equals(other.subgroup)) return false; + if (subgroup == null) { + if (other.subgroup != null) return false; + } else if (!subgroup.equals(other.subgroup)) return false; return true; } @Override public String toString() { - StringBuilder builder = new StringBuilder(); + final StringBuilder builder = new StringBuilder(); builder.append("SequenceCharacteristics [root="); builder.append(root == null ? "(null)" : root); diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/delims/SequenceDelimiter.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/delims/SequenceDelimiter.java index e723123..48d85c1 100644 --- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/delims/SequenceDelimiter.java +++ b/BJC-Utils2/src/main/java/bjc/utils/parserutils/delims/SequenceDelimiter.java @@ -1,5 +1,14 @@ package bjc.utils.parserutils.delims; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; + +import com.google.common.collect.HashMultimap; +import com.google.common.collect.HashMultiset; +import com.google.common.collect.Multimap; +import com.google.common.collect.Multiset; + import bjc.utils.data.IPair; import bjc.utils.data.ITree; import bjc.utils.data.Tree; @@ -9,18 +18,9 @@ import bjc.utils.esodata.Stack; import bjc.utils.funcdata.IMap; import bjc.utils.funcutils.StringUtils; -import com.google.common.collect.HashMultimap; -import com.google.common.collect.HashMultiset; -import com.google.common.collect.Multimap; -import com.google.common.collect.Multiset; - -import java.util.HashMap; -import java.util.Map; -import java.util.Map.Entry; - /** * Convert linear sequences into trees that represent group structure. - * + * * @author EVE * * @param <T> @@ -30,7 +30,7 @@ public class SequenceDelimiter<T> { /* * Mapping from group names to actual groups. */ - private Map<T, DelimiterGroup<T>> groups; + private final Map<T, DelimiterGroup<T>> groups; private DelimiterGroup<T> initialGroup; @@ -44,64 +44,62 @@ public class SequenceDelimiter<T> { /** * Convert a linear sequence into a tree that matches the delimiter * structure. - * + * * Essentially, creates a parse tree of the expression against the * following grammar while obeying the defined grouping rules. - * + * * <pre> * <tree> -> (<data> | <subgroup> | <group>)* * <subgroup> -> <tree> <marker> * <group> -> <open> <tree> <close> - * + * * <data> -> STRING * <open> -> STRING * <close> -> STRING * <marker> -> STRING * </pre> - * + * * @param chars * The parameters on how to mark certain portions of the * tree. * @param seq * The sequence to delimit. - * + * * @return The sequence as a tree that matches its group structure. Each * node in the tree is either a data node, a subgroup node, or a * group node. - * + * * A data node is a leaf node whose data is the string it * represents. - * + * * A subgroup node is a node with two children, and the name of * the sub-group as its label. The first child is the contents * of the sub-group, and the second is the marker that started * the subgroup. The marker is a leaf node labeled with its * contents, and the contents contains a recursive tree. - * + * * A group node is a node with three children, and the name of * the group as its label. The first child is the opening * delimiter, the second is the group contents, and the third is * the closing delimiter. The delimiters are leaf nodes labeled * with their contents, while the group node contains a * recursive tree. - * + * * @throws DelimiterException * Thrown if something went wrong during sequence * delimitation. - * + * */ - public ITree<T> delimitSequence(SequenceCharacteristics<T> chars, @SuppressWarnings("unchecked") T... seq) - throws DelimiterException { - if(initialGroup == null) { + public ITree<T> delimitSequence(final SequenceCharacteristics<T> chars, + @SuppressWarnings("unchecked") final T... seq) throws DelimiterException { + if (initialGroup == null) throw new NullPointerException("Initial group must be specified."); - } else if(chars == null) { - throw new NullPointerException("Sequence characteristics must not be null"); - } + else if (chars == null) throw new NullPointerException("Sequence characteristics must not be null"); /* * The stack of opened and not yet closed groups. */ - Stack<DelimiterGroup<T>.OpenGroup> groupStack = new SimpleStack<>(); + final Stack<DelimiterGroup<T>.OpenGroup> groupStack = new SimpleStack<>(); /* * Open initial group. @@ -111,34 +109,34 @@ public class SequenceDelimiter<T> { /* * Groups that aren't allowed to be opened at the moment. */ - Stack<Multiset<T>> forbiddenDelimiters = new SimpleStack<>(); + final Stack<Multiset<T>> forbiddenDelimiters = new SimpleStack<>(); forbiddenDelimiters.push(HashMultiset.create()); /* * Groups that are allowed to be opened at the moment. */ - Stack<Multimap<T, T>> allowedDelimiters = new SimpleStack<>(); + final Stack<Multimap<T, T>> allowedDelimiters = new SimpleStack<>(); allowedDelimiters.push(HashMultimap.create()); /* * Map of who forbid what for debugging purposes. */ - IMap<T, T> whoForbid = new PushdownMap<>(); + final IMap<T, T> whoForbid = new PushdownMap<>(); - for(int i = 0; i < seq.length; i++) { - T tok = seq[i]; + for (int i = 0; i < seq.length; i++) { + final T tok = seq[i]; - IPair<T, T[]> possibleOpenPar = groupStack.top().doesOpen(tok); + final IPair<T, T[]> possibleOpenPar = groupStack.top().doesOpen(tok); T possibleOpen = possibleOpenPar.getLeft(); - if(possibleOpen == null) { + if (possibleOpen == null) { /* * Handle nested openers. - * + * * Local openers take priority over nested ones * if they overlap. */ - if(allowedDelimiters.top().containsKey(tok)) { + if (allowedDelimiters.top().containsKey(tok)) { possibleOpen = allowedDelimiters.top().get(tok).iterator().next(); } } @@ -146,29 +144,29 @@ public class SequenceDelimiter<T> { /* * If we have an opening delimiter, handle it. */ - if(possibleOpen != null) { - DelimiterGroup<T> group = groups.get(possibleOpen); + if (possibleOpen != null) { + final DelimiterGroup<T> group = groups.get(possibleOpen); /* * Error on groups that can't open in this * context. - * + * * This means groups that can't occur at the * top-level of this group, as well as nested * exclusions from all enclosing groups. */ - if(isForbidden(groupStack, forbiddenDelimiters, possibleOpen)) { - StringBuilder msgBuilder = new StringBuilder(); + if (isForbidden(groupStack, forbiddenDelimiters, possibleOpen)) { + final StringBuilder msgBuilder = new StringBuilder(); T forbiddenBy; - if(whoForbid.containsKey(tok)) { + if (whoForbid.containsKey(tok)) { forbiddenBy = whoForbid.get(tok); } else { forbiddenBy = groupStack.top().getName(); } - String ctxList = StringUtils.toEnglishList(groupStack.toArray(), "then"); + final String ctxList = StringUtils.toEnglishList(groupStack.toArray(), "then"); msgBuilder.append("Group '"); msgBuilder.append(group); @@ -184,13 +182,13 @@ public class SequenceDelimiter<T> { /* * Add an open group. */ - DelimiterGroup<T>.OpenGroup open = group.open(tok, possibleOpenPar.getRight()); + final DelimiterGroup<T>.OpenGroup open = group.open(tok, possibleOpenPar.getRight()); groupStack.push(open); /* * Handle 'forgetful' groups that reset nesting */ - if(open.isForgetful()) { + if (open.isForgetful()) { allowedDelimiters.push(HashMultimap.create()); forbiddenDelimiters.push(HashMultiset.create()); } @@ -198,33 +196,33 @@ public class SequenceDelimiter<T> { /* * Add the nested opens from this group. */ - Multimap<T, T> currentAllowed = allowedDelimiters.top(); - for(Entry<T, T> opener : open.getNestingOpeners().entrySet()) { + final Multimap<T, T> currentAllowed = allowedDelimiters.top(); + for (final Entry<T, T> opener : open.getNestingOpeners().entrySet()) { currentAllowed.put(opener.getKey(), opener.getValue()); } /* * Add the nested exclusions from this group */ - Multiset<T> currentForbidden = forbiddenDelimiters.top(); - for(T exclusion : open.getNestingExclusions()) { + final Multiset<T> currentForbidden = forbiddenDelimiters.top(); + for (final T exclusion : open.getNestingExclusions()) { currentForbidden.add(exclusion); whoForbid.put(exclusion, possibleOpen); } - } else if(!groupStack.empty() && groupStack.top().isClosing(tok)) { + } else if (!groupStack.empty() && groupStack.top().isClosing(tok)) { /* * Close the group. */ - DelimiterGroup<T>.OpenGroup closed = groupStack.pop(); + final DelimiterGroup<T>.OpenGroup closed = groupStack.pop(); groupStack.top().addItem(closed.toTree(tok, chars)); /* * Remove nested exclusions from this group. */ - Multiset<T> currentForbidden = forbiddenDelimiters.top(); - for(T excludedGroup : closed.getNestingExclusions()) { + final Multiset<T> currentForbidden = forbiddenDelimiters.top(); + for (final T excludedGroup : closed.getNestingExclusions()) { currentForbidden.remove(excludedGroup); whoForbid.remove(excludedGroup); @@ -233,19 +231,19 @@ public class SequenceDelimiter<T> { /* * Remove the nested opens from this group. */ - Multimap<T, T> currentAllowed = allowedDelimiters.top(); - for(Entry<T, T> closer : closed.getNestingOpeners().entrySet()) { + final Multimap<T, T> currentAllowed = allowedDelimiters.top(); + for (final Entry<T, T> closer : closed.getNestingOpeners().entrySet()) { currentAllowed.remove(closer.getKey(), closer.getValue()); } /* * Handle 'forgetful' groups that reset nesting. */ - if(closed.isForgetful()) { + if (closed.isForgetful()) { allowedDelimiters.drop(); forbiddenDelimiters.drop(); } - } else if(!groupStack.empty() && groupStack.top().marksSubgroup(tok)) { + } else if (!groupStack.empty() && groupStack.top().marksSubgroup(tok)) { groupStack.top().markSubgroup(tok, chars); } else { groupStack.top().addItem(new Tree<>(tok)); @@ -255,14 +253,15 @@ public class SequenceDelimiter<T> { /* * Error if not all groups were closed. */ - if(groupStack.size() > 1) { - DelimiterGroup<T>.OpenGroup group = groupStack.top(); + if (groupStack.size() > 1) { + final DelimiterGroup<T>.OpenGroup group = groupStack.top(); - StringBuilder msgBuilder = new StringBuilder(); + final StringBuilder msgBuilder = new StringBuilder(); - String closingDelims = StringUtils.toEnglishList(group.getNestingExclusions().toArray(), false); + final String closingDelims = StringUtils.toEnglishList(group.getNestingExclusions().toArray(), + false); - String ctxList = StringUtils.toEnglishList(groupStack.toArray(), "then"); + final String ctxList = StringUtils.toEnglishList(groupStack.toArray(), "then"); msgBuilder.append("Unclosed group '"); msgBuilder.append(group.getName()); @@ -277,35 +276,34 @@ public class SequenceDelimiter<T> { return groupStack.pop().toTree(chars.root, chars); } - private boolean isForbidden(Stack<DelimiterGroup<T>.OpenGroup> groupStack, - Stack<Multiset<T>> forbiddenDelimiters, T groupName) { + private boolean isForbidden(final Stack<DelimiterGroup<T>.OpenGroup> groupStack, + final Stack<Multiset<T>> forbiddenDelimiters, final T groupName) { boolean localForbid; - if(groupStack.empty()) + if (groupStack.empty()) { localForbid = false; - else + } else { localForbid = groupStack.top().excludes(groupName); + } return localForbid || forbiddenDelimiters.top().contains(groupName); } /** * Add a delimiter group. - * + * * @param group * The delimiter group. */ - public void addGroup(DelimiterGroup<T> group) { - if(group == null) { - throw new NullPointerException("Group must not be null"); - } + public void addGroup(final DelimiterGroup<T> group) { + if (group == null) throw new NullPointerException("Group must not be null"); groups.put(group.groupName, group); } /** * Creates and adds a delimiter group using the provided settings. - * + * * @param openers * The tokens that open this group * @param groupName @@ -313,31 +311,31 @@ public class SequenceDelimiter<T> { * @param closers * The tokens that close this group */ - public void addGroup(T[] openers, T groupName, @SuppressWarnings("unchecked") T... closers) { - DelimiterGroup<T> group = new DelimiterGroup<>(groupName); + public void addGroup(final T[] openers, final T groupName, @SuppressWarnings("unchecked") final T... closers) { + final DelimiterGroup<T> group = new DelimiterGroup<>(groupName); group.addClosing(closers); addGroup(group); - for(T open : openers) { + for (final T open : openers) { group.addOpener(open, groupName); } } @Override public String toString() { - StringBuilder builder = new StringBuilder(); + final StringBuilder builder = new StringBuilder(); builder.append("SequenceDelimiter ["); - if(groups != null) { + if (groups != null) { builder.append("groups="); builder.append(groups); builder.append(","); } - if(initialGroup != null) { + if (initialGroup != null) { builder.append("initialGroup="); builder.append(initialGroup); } @@ -349,11 +347,11 @@ public class SequenceDelimiter<T> { /** * Set the initial group of this delimiter. - * + * * @param initialGroup * The initial group of this delimiter. */ - public void setInitialGroup(DelimiterGroup<T> initialGroup) { + public void setInitialGroup(final DelimiterGroup<T> initialGroup) { this.initialGroup = initialGroup; } } diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/delims/StringDelimiter.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/delims/StringDelimiter.java index 6db1c98..e3eeea5 100644 --- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/delims/StringDelimiter.java +++ b/BJC-Utils2/src/main/java/bjc/utils/parserutils/delims/StringDelimiter.java @@ -4,7 +4,7 @@ import bjc.utils.data.ITree; /** * A sequence delimiter specialized for strings. - * + * * @author EVE * */ @@ -14,18 +14,18 @@ public class StringDelimiter extends SequenceDelimiter<String> { * Override of * {@link SequenceDelimiter#delimitSequence(SequenceCharacteristics, Object...)} * for ease of use for strings. - * + * * @param seq * The sequence to delimit. - * + * * @return The sequence as a tree. - * + * * @throws DelimiterException * if something went wrong with delimiting the sequence. - * + * * @see SequenceDelimiter */ - public ITree<String> delimitSequence(String... seq) throws DelimiterException { + public ITree<String> delimitSequence(final String... seq) throws DelimiterException { return super.delimitSequence(new SequenceCharacteristics<>("root", "contents", "subgroup"), seq); } } |
