summaryrefslogtreecommitdiff
path: root/clformat/src/main/java/bjc/utils/ioutils
diff options
context:
space:
mode:
authorbculkin2442 <bjculkin@mix.wvu.edu>2020-01-04 11:08:25 -0500
committerbculkin2442 <bjculkin@mix.wvu.edu>2020-01-04 11:08:25 -0500
commit91f845e3856aae95a4b41c1dd02b3b45d023e8de (patch)
treeae6bde48be4158f21fd21dd8db049473d5a5dd8b /clformat/src/main/java/bjc/utils/ioutils
parent84a32fd486070f941a7d1d1952408d58cc3d6fcf (diff)
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.
Diffstat (limited to 'clformat/src/main/java/bjc/utils/ioutils')
-rw-r--r--clformat/src/main/java/bjc/utils/ioutils/format/CLTokenizer.java76
-rw-r--r--clformat/src/main/java/bjc/utils/ioutils/format/ClauseDecree.java70
-rw-r--r--clformat/src/main/java/bjc/utils/ioutils/format/Decree.java15
-rw-r--r--clformat/src/main/java/bjc/utils/ioutils/format/GroupDecree.java77
4 files changed, 233 insertions, 5 deletions
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<Decree> {
@@ -29,7 +28,7 @@ public class CLTokenizer implements Iterator<Decree> {
}
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<Decree> {
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<Decree> 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<ClauseDecree> 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);
+ }
+}