diff options
| author | Benjamin J. Culkin <bjculkin@mix.wvu.edu> | 2017-09-09 21:46:16 -0300 |
|---|---|---|
| committer | Benjamin J. Culkin <bjculkin@mix.wvu.edu> | 2017-09-09 21:47:34 -0300 |
| commit | d766896972c9e9be4a9e0021ec5f4f0665901865 (patch) | |
| tree | 1f6473300ef86e0697d682360bea0d28fc144baa /BJC-Utils2/src/main/java/bjc/utils/parserutils/delims | |
| parent | 40f3a28569366c4357fbda11d2fff3b77686d84f (diff) | |
Update
Most of it is documentation changes.
The rest is more work on BlockReaders, as well as a simple command
language for configuring them.
Diffstat (limited to 'BJC-Utils2/src/main/java/bjc/utils/parserutils/delims')
3 files changed, 69 insertions, 38 deletions
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 85d4038..b1d8597 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 @@ -34,12 +34,20 @@ public class DelimiterGroup<T> { * */ public class OpenGroup { + /* + * The contents of this group. + */ private final Deque<ITree<T>> contents; + /* + * The contents of the current subgroup. + */ private IList<ITree<T>> currentGroup; + /* + * The token that opened the group, and any opening parameters. + */ private final T opener; - private final T[] params; /** @@ -80,14 +88,23 @@ public class DelimiterGroup<T> { * The characteristics for building the tree. */ public void markSubgroup(final T marker, final SequenceCharacteristics<T> chars) { + /* + * Add all of the contents to the subgroup. + */ final ITree<T> subgroupContents = new Tree<>(chars.contents); for (final ITree<T> itm : currentGroup) { subgroupContents.addChild(itm); } + /* + * Handle subordinate sub-groups. + */ while (!contents.isEmpty()) { final ITree<T> possibleSubordinate = contents.peek(); + /* + * Subordinate lower priority subgroups. + */ if (possibleSubordinate.getHead().equals(chars.subgroup)) { final T otherMarker = possibleSubordinate.getChild(1).getHead(); @@ -103,7 +120,6 @@ public class DelimiterGroup<T> { 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); currentGroup = new FunctionalList<>(); @@ -121,12 +137,19 @@ public class DelimiterGroup<T> { * @return This group as a tree. */ public ITree<T> toTree(final T closer, final SequenceCharacteristics<T> chars) { + /* + * Mark any implied subgroups. + */ if (impliedSubgroups.containsKey(closer)) { markSubgroup(impliedSubgroups.get(closer), chars); } final ITree<T> res = new Tree<>(chars.contents); + /* + * Add either the contents of the current group, + * or subgroups if they're their. + */ if (contents.isEmpty()) { currentGroup.forEach(res::addChild); } else { @@ -440,8 +463,7 @@ public class DelimiterGroup<T> { * The group opened by the marker. */ public void addOpener(final T opener, final T group) { - if (opener == null) - throw new NullPointerException("Opener must not be null"); + 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"); openDelimiters.put(opener, group); @@ -457,8 +479,7 @@ public class DelimiterGroup<T> { * The group opened by the marker. */ public void addNestedOpener(final T opener, final T group) { - if (opener == null) - throw new NullPointerException("Opener must not be null"); + 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"); nestedOpenDelimiters.put(opener, group); @@ -474,14 +495,10 @@ public class DelimiterGroup<T> { * The subgroup to imply. */ public void implySubgroup(final T closer, final T subgroup) { - if (closer == null) - throw new NullPointerException("Closer must not be null"); - else if (subgroup == null) - throw new NullPointerException("Subgroup must not be null"); - else if (!closingDelimiters.contains(closer)) - throw new IllegalArgumentException(String.format("No closing delimiter '%s' defined", closer)); - else if (!subgroups.containsKey(subgroup)) - throw new IllegalArgumentException(String.format("No subgroup '%s' defined", subgroup)); + if (closer == null) throw new NullPointerException("Closer must not be null"); + else if (subgroup == null) throw new NullPointerException("Subgroup must not be null"); + else if (!closingDelimiters.contains(closer)) throw new IllegalArgumentException(String.format("No closing delimiter '%s' defined", closer)); + else if (!subgroups.containsKey(subgroup)) throw new IllegalArgumentException(String.format("No subgroup '%s' defined", subgroup)); impliedSubgroups.put(closer, subgroup); } @@ -573,4 +590,4 @@ public class DelimiterGroup<T> { 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/RegexOpener.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/delims/RegexOpener.java index 98c1dc1..ee93b73 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 @@ -8,7 +8,7 @@ import bjc.utils.data.IPair; import bjc.utils.data.Pair; /** - * A predicated opener for use with {@link RegexOpener} + * A predicated opener for use with {@link RegexCloser} * * @author bjculkin * @@ -51,4 +51,4 @@ public class RegexOpener implements Function<String, IPair<String, String[]>> { return new Pair<>(null, null); } -}
\ No newline at end of file +} 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 48d85c1..ccfaffb 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 @@ -32,6 +32,9 @@ public class SequenceDelimiter<T> { */ private final Map<T, DelimiterGroup<T>> groups; + /* + * The initial group to start with. + */ private DelimiterGroup<T> initialGroup; /** @@ -49,14 +52,14 @@ public class SequenceDelimiter<T> { * following grammar while obeying the defined grouping rules. * * <pre> - * <tree> -> (<data> | <subgroup> | <group>)* - * <subgroup> -> <tree> <marker> - * <group> -> <open> <tree> <close> + * <tree> → (<data> | <subgroup> | <group>)* + * <subgroup> → <tree> <marker> + * <group> → <open> <tree> <close> * - * <data> -> STRING - * <open> -> STRING - * <close> -> STRING - * <marker> -> STRING + * <data> → STRING + * <open> → STRING + * <close> → STRING + * <marker> → STRING * </pre> * * @param chars @@ -92,9 +95,8 @@ public class SequenceDelimiter<T> { */ 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"); + if (initialGroup == null) throw new NullPointerException("Initial group must be specified."); + else if (chars == null) throw new NullPointerException("Sequence characteristics must not be null"); /* * The stack of opened and not yet closed groups. @@ -123,9 +125,15 @@ public class SequenceDelimiter<T> { */ final IMap<T, T> whoForbid = new PushdownMap<>(); + /* + * Process each member of the sequence. + */ for (int i = 0; i < seq.length; i++) { final T tok = seq[i]; + /* + * Check if this token could open a group. + */ final IPair<T, T[]> possibleOpenPar = groupStack.top().doesOpen(tok); T possibleOpen = possibleOpenPar.getLeft(); @@ -156,8 +164,6 @@ public class SequenceDelimiter<T> { * exclusions from all enclosing groups. */ if (isForbidden(groupStack, forbiddenDelimiters, possibleOpen)) { - final StringBuilder msgBuilder = new StringBuilder(); - T forbiddenBy; if (whoForbid.containsKey(tok)) { @@ -168,15 +174,9 @@ public class SequenceDelimiter<T> { final String ctxList = StringUtils.toEnglishList(groupStack.toArray(), "then"); - msgBuilder.append("Group '"); - msgBuilder.append(group); - msgBuilder.append("' can't be opened in this context."); - msgBuilder.append(" (forbidden by '"); - msgBuilder.append(forbiddenBy); - msgBuilder.append("')\nContext stack: "); - msgBuilder.append(ctxList); + final String fmt = "Group '%s' can't be opened in this context. (forbidden by '%s')\nContext Stack: %s"; - throw new DelimiterException(msgBuilder.toString()); + throw new DelimiterException(String.format(fmt, group, forbiddenBy, ctxList)); } /* @@ -244,8 +244,14 @@ public class SequenceDelimiter<T> { forbiddenDelimiters.drop(); } } else if (!groupStack.empty() && groupStack.top().marksSubgroup(tok)) { + /* + * Mark a subgroup. + */ groupStack.top().markSubgroup(tok, chars); } else { + /* + * Add an item to the group. + */ groupStack.top().addItem(new Tree<>(tok)); } } @@ -270,16 +276,24 @@ public class SequenceDelimiter<T> { msgBuilder.append(" to close it\nOpen groups: "); msgBuilder.append(ctxList); - throw new DelimiterException(msgBuilder.toString()); + final String fmt = "Unclosed group '%s'. Expected one of %s to close it.\nOpen groups: %n"; + + throw new DelimiterException(String.format(fmt, group.getName(), closingDelims, ctxList)); } return groupStack.pop().toTree(chars.root, chars); } + /* + * Check if a group is forbidden to open in a context. + */ private boolean isForbidden(final Stack<DelimiterGroup<T>.OpenGroup> groupStack, final Stack<Multiset<T>> forbiddenDelimiters, final T groupName) { boolean localForbid; + /* + * Check if a delimiter is locally forbidden. + */ if (groupStack.empty()) { localForbid = false; } else { |
