From 91f845e3856aae95a4b41c1dd02b3b45d023e8de Mon Sep 17 00:00:00 2001 From: bculkin2442 Date: Sat, 4 Jan 2020 11:08:25 -0500 Subject: Begin refactoring of group decree parsing This begins the refactoring of how 'group' decrees (like ~{, and ~[) are parsed. This commit contains the infrastructure for doing so, but none of the actual group decrees have been changed yet to use it. --- .../java/bjc/utils/ioutils/format/CLTokenizer.java | 76 +++++++++++++++++++-- .../bjc/utils/ioutils/format/ClauseDecree.java | 70 ++++++++++++++++++++ .../main/java/bjc/utils/ioutils/format/Decree.java | 15 +++++ .../java/bjc/utils/ioutils/format/GroupDecree.java | 77 ++++++++++++++++++++++ 4 files changed, 233 insertions(+), 5 deletions(-) create mode 100644 clformat/src/main/java/bjc/utils/ioutils/format/ClauseDecree.java create mode 100644 clformat/src/main/java/bjc/utils/ioutils/format/GroupDecree.java (limited to 'clformat/src/main/java/bjc/utils') diff --git a/clformat/src/main/java/bjc/utils/ioutils/format/CLTokenizer.java b/clformat/src/main/java/bjc/utils/ioutils/format/CLTokenizer.java index 7c76696..f19fcf8 100644 --- a/clformat/src/main/java/bjc/utils/ioutils/format/CLTokenizer.java +++ b/clformat/src/main/java/bjc/utils/ioutils/format/CLTokenizer.java @@ -1,10 +1,9 @@ package bjc.utils.ioutils.format; -import java.util.Iterator; -import java.util.Map; -import java.util.regex.Matcher; +import java.util.*; +import java.util.regex.*; -import bjc.utils.ioutils.SimpleProperties; +import bjc.utils.ioutils.*; import bjc.utils.ioutils.format.directives.*; public class CLTokenizer implements Iterator { @@ -29,7 +28,7 @@ public class CLTokenizer implements Iterator { } private Decree getNext() { - if (!hasNext()) return null; + if (!hasNext()) throw new NoSuchElementException("No possible decrees remaining"); if (dir != null) { Decree tmp = dir; @@ -82,4 +81,71 @@ public class CLTokenizer implements Iterator { return new Decree(sb.toString()); } + + /** + * Read in a group decree. + * + * @param openedWith + * The decree that started the group. + * + * @param desiredClosing + * The name of the decree that will close the group. + * + * @param clauseSep + * The name of the decree that will separate clauses in the group. Pass 'null' if this group + * doesn't have separate clauses. + * + * @return A group decree with the given properties. + */ + public GroupDecree nextGroup(Decree openedWith, String desiredClosing, String clauseSep) { + GroupDecree newGroup = new GroupDecree(); + + if (!hasNext()) throw new NoSuchElementException("No decrees available"); + + ClauseDecree curClause = new ClauseDecree(); + + int nestingLevel = 1; + + do { + Decree curDecree = next(); + + // @TODO handle nesting & such + if (curDecree.isLiteral) { + curClause.addChild(curDecree); + } else if (nestingLevel == 1) { + // Clauses can only be ended at neutral nesting + if (curDecree.isNamed(desiredClosing)) { + newGroup.addChild(curClause); + newGroup.closing = curDecree; + + break; + } else if (clauseSep != null && curDecree.isNamed(clauseSep)) { + curClause.terminator = curDecree; + newGroup.addChild(curClause); + + curClause = new ClauseDecree(); + } else { + curClause.addChild(curDecree); + } + } else if (curDecree.isNamed(openedWith.name)) { + // Nest one level deeper + nestingLevel += 1; + + curClause.addChild(curDecree); + } else if (curDecree.isNamed(desiredClosing)) { + // Unnest + nestingLevel -= 1; + } else { + curClause.addChild(curDecree); + } + } while (hasNext()); + + if (newGroup.closing == null) { + String msg = String.format("Did not find closing directive for group (wanted %s)", desiredClosing); + + throw new NoSuchElementException(msg); + } + + return newGroup; + } } diff --git a/clformat/src/main/java/bjc/utils/ioutils/format/ClauseDecree.java b/clformat/src/main/java/bjc/utils/ioutils/format/ClauseDecree.java new file mode 100644 index 0000000..2c34a0d --- /dev/null +++ b/clformat/src/main/java/bjc/utils/ioutils/format/ClauseDecree.java @@ -0,0 +1,70 @@ +package bjc.utils.ioutils.format; + +import java.util.*; + +/** + * A decree that represents a single clause in a {@link GroupDecree}. + * + * Has a list of decrees for a body, and then a single decree as the 'terminator' if this was a + * terminated clause. + * + * @author Ben Culkin + */ +public class ClauseDecree { + /** + * The decrees that make up the body of this clause. + */ + public List body; + + /** + * The decree that terminated this clause. + */ + public Decree terminator; + + /** + * Create a new blank clause decree. + * + */ + public ClauseDecree() { + body = new ArrayList<>(); + } + + /** + * Create a new clause decree with specific contents. + * + * @param children + * The decrees to form the body of the clause. + */ + public ClauseDecree(Decree... children) { + this(); + + for (Decree child : children) { + body.add(child); + } + } + + /** + * Create a new clause with both a body and a terminator. + * + * @param term + * The decree that terminates the clause. + * + * @param children + * The decrees that form the body of the clause. + */ + public ClauseDecree(Decree term, Decree... children) { + this(children); + + this.terminator = term; + } + + /** + * Add a decree to this clause. + * + * @param child + * The decree to add to this clause. + */ + public void addChild(Decree child) { + body.add(child); + } +} diff --git a/clformat/src/main/java/bjc/utils/ioutils/format/Decree.java b/clformat/src/main/java/bjc/utils/ioutils/format/Decree.java index ce1f04d..a4bc005 100644 --- a/clformat/src/main/java/bjc/utils/ioutils/format/Decree.java +++ b/clformat/src/main/java/bjc/utils/ioutils/format/Decree.java @@ -103,4 +103,19 @@ public class Decree { this.isLiteral = isUser; } + + /** + * Check if this decree is a non-literal, with a particular name. + * + * @param nam + * The name to see if we have. + * + * @return Whether or not the provided name equals our name. + */ + public boolean isNamed(String nam) { + // Literals don't have a meaningful name + if (isLiteral) return false; + + return name.equals(nam); + } } diff --git a/clformat/src/main/java/bjc/utils/ioutils/format/GroupDecree.java b/clformat/src/main/java/bjc/utils/ioutils/format/GroupDecree.java new file mode 100644 index 0000000..0680a15 --- /dev/null +++ b/clformat/src/main/java/bjc/utils/ioutils/format/GroupDecree.java @@ -0,0 +1,77 @@ +package bjc.utils.ioutils.format; + +import java.util.*; + +/** + * Represents an enclosed group of decrees. + * + * This is used for all of the decrees that take another format string as part of their body. + * + * @author Ben Culkin + */ +public class GroupDecree { + /** + * The decree that opened this group. + */ + public Decree opening; + + /** + * The decree that closed this group. + */ + public Decree closing; + + /** + * The clauses that make up the body of this group. + */ + public List body; + + /** + * Create a new group decree with no values. + */ + public GroupDecree() { + body = new ArrayList<>(); + } + + /** + * Create a new group decree with a given body. + * + * @param children + * The decrees that form the body of the group. + */ + public GroupDecree(ClauseDecree... children) { + this(); + + for (ClauseDecree child : children) { + body.add(child); + } + } + + /** + * Create a new group decree with all of the fields filled out. + * + * @param opening + * The decree opening the group. + * + * @param closing + * The decree closing the group. + * + * @param children + * The decree making up the body of the group. + */ + public GroupDecree(Decree opening, Decree closing, ClauseDecree... children) { + this(children); + + this.opening = opening; + this.closing = closing; + } + + /** + * Add a decree to this group. + * + * @param child + * The decree to add to the group. + */ + public void addChild(ClauseDecree child) { + body.add(child); + } +} -- cgit v1.2.3