summaryrefslogtreecommitdiff
path: root/base/src/main/java/bjc/utils/ioutils/format
diff options
context:
space:
mode:
authorBenjamin J. Culkin <bjculkin@mix.wvu.edu>2018-09-16 21:12:35 -0300
committerBenjamin J. Culkin <bjculkin@mix.wvu.edu>2018-09-16 21:12:35 -0300
commit2f96f49c2d2c8679841c790e9dd7d9f1b6f3fed1 (patch)
tree23cfb315743bbb5c1c8fa749e75aba8a54e3a2f7 /base/src/main/java/bjc/utils/ioutils/format
parent92c56c5918a0858aad32cc9ee0fb3eee99ebd007 (diff)
Large update
A large update, this contains much debugging of the CL FORMAT routines, as well as a few other minor changes.
Diffstat (limited to 'base/src/main/java/bjc/utils/ioutils/format')
-rw-r--r--base/src/main/java/bjc/utils/ioutils/format/CLFormatter.java208
-rw-r--r--base/src/main/java/bjc/utils/ioutils/format/CLModifiers.java35
-rw-r--r--base/src/main/java/bjc/utils/ioutils/format/CLParameters.java57
-rw-r--r--base/src/main/java/bjc/utils/ioutils/format/directives/AestheticDirective.java1
-rw-r--r--base/src/main/java/bjc/utils/ioutils/format/directives/CaseDirective.java117
-rw-r--r--base/src/main/java/bjc/utils/ioutils/format/directives/ConditionalDirective.java134
-rw-r--r--base/src/main/java/bjc/utils/ioutils/format/directives/Directive.java32
-rw-r--r--base/src/main/java/bjc/utils/ioutils/format/directives/EscapeDirective.java15
-rw-r--r--base/src/main/java/bjc/utils/ioutils/format/directives/GeneralNumberDirective.java6
-rw-r--r--base/src/main/java/bjc/utils/ioutils/format/directives/IterationDirective.java42
-rw-r--r--base/src/main/java/bjc/utils/ioutils/format/directives/NumberDirective.java10
-rw-r--r--base/src/main/java/bjc/utils/ioutils/format/directives/RecursiveDirective.java49
-rw-r--r--base/src/main/java/bjc/utils/ioutils/format/directives/TabulateDirective.java2
13 files changed, 522 insertions, 186 deletions
diff --git a/base/src/main/java/bjc/utils/ioutils/format/CLFormatter.java b/base/src/main/java/bjc/utils/ioutils/format/CLFormatter.java
index 1605a75..9e01ca6 100644
--- a/base/src/main/java/bjc/utils/ioutils/format/CLFormatter.java
+++ b/base/src/main/java/bjc/utils/ioutils/format/CLFormatter.java
@@ -24,33 +24,33 @@ import static bjc.utils.misc.PropertyDB.getRegex;
*
*/
public class CLFormatter {
- private static final String prefixParam = getRegex("clFormatPrefix");
-
- private static final String formatMod = getRegex("clFormatModifier");
-
- private static final String prefixList = applyFormat("delimSeparatedList", prefixParam, ",");
-
+ private static final String prefixParam = getRegex("clFormatPrefix");
+ private static final String formatMod = getRegex("clFormatModifier");
private static final String directiveName = getRegex("clFormatName");
- private static final String formatDirective = applyFormat("clFormatDirective", prefixList, formatMod,
- directiveName);
+ private static final String prefixList = applyFormat("delimSeparatedList", prefixParam, ",");
+ private static final String formatDirective = applyFormat("clFormatDirective", prefixList, formatMod, directiveName);
+
private static final Pattern pFormatDirective = Pattern.compile(formatDirective);
private static Map<String, Directive> builtinDirectives;
-
- private Map<String, Directive> extraDirectives;
+ private Map<String, Directive> extraDirectives;
static {
builtinDirectives = new HashMap<>();
builtinDirectives.put("A", new AestheticDirective());
+ // @NOTE 9/6/18
+ //
+ // This is just an alias, not the actual S directive
+ builtinDirectives.put("S", new AestheticDirective());
builtinDirectives.put("C", new CharacterDirective());
- builtinDirectives.put("B", new NumberDirective(-1, 2));
- builtinDirectives.put("O", new NumberDirective(-1, 8));
- builtinDirectives.put("D", new NumberDirective(-1, 10));
- builtinDirectives.put("X", new NumberDirective(-1, 16));
+ builtinDirectives.put("B", new NumberDirective(-1, 2, 'B'));
+ builtinDirectives.put("O", new NumberDirective(-1, 8, 'O'));
+ builtinDirectives.put("D", new NumberDirective(-1, 10, 'D'));
+ builtinDirectives.put("X", new NumberDirective(-1, 16, 'X'));
builtinDirectives.put("R", new RadixDirective());
@@ -58,13 +58,15 @@ public class CLFormatter {
builtinDirectives.put("%", new LiteralDirective("\n", '%'));
builtinDirectives.put("|", new LiteralDirective("\f", '|'));
- builtinDirectives.put("~", new LiteralDirective("~", '~'));
+ builtinDirectives.put("~", new LiteralDirective("~", '~'));
+ builtinDirectives.put("?", new RecursiveDirective());
builtinDirectives.put("*", new GotoDirective());
builtinDirectives.put("^", new EscapeDirective());
builtinDirectives.put("[", new ConditionalDirective());
builtinDirectives.put("{", new IterationDirective());
+ builtinDirectives.put("(", new CaseDirective());
builtinDirectives.put("T", new TabulateDirective());
}
@@ -103,7 +105,7 @@ public class CLFormatter {
/* Put the parameters where we can easily handle them. */
Tape<Object> tParams = new SingleTape<>(params);
- doFormatString(format, rw, tParams);
+ doFormatString(format, rw, tParams, true);
return rw.toString();
}
@@ -123,7 +125,7 @@ public class CLFormatter {
/* Put the parameters where we can easily handle them. */
Tape<Object> tParams = new SingleTape<>(params);
- doFormatString(format, rw, tParams);
+ doFormatString(format, rw, tParams, true);
return rw.toString();
}
@@ -141,7 +143,7 @@ public class CLFormatter {
/* Put the parameters where we can easily handle them. */
Tape<Object> tParams = new SingleTape<>(params);
- doFormatString(format, rw, tParams);
+ doFormatString(format, rw, tParams, true);
}
/**
@@ -159,7 +161,7 @@ public class CLFormatter {
/* Put the parameters where we can easily handle them. */
Tape<Object> tParams = new SingleTape<>(params);
- doFormatString(format, rw, tParams);
+ doFormatString(format, rw, tParams, true);
}
/**
@@ -175,7 +177,7 @@ public class CLFormatter {
* @param tParams
* The parameters to use.
*/
- public void doFormatString(String format, ReportWriter rw, Tape<Object> tParams) throws IOException {
+ public void doFormatString(String format, ReportWriter rw, Tape<Object> tParams, boolean isToplevel) throws IOException {
Matcher dirMatcher = pFormatDirective.matcher(format);
// We need this StringBuffer to use appendReplacement and stuff
@@ -185,90 +187,96 @@ public class CLFormatter {
// ourselves.
StringBuffer sb = new StringBuffer();
- while(dirMatcher.find()) {
- dirMatcher.appendReplacement(sb, "");
- rw.writeBuffer(sb);
-
- String dirName = dirMatcher.group("name");
- String dirFunc = dirMatcher.group("funcname");
- String dirMods = dirMatcher.group("modifiers");
- String dirParams = dirMatcher.group("params");
-
- if(dirMods == null) dirMods = "";
- if(dirParams == null) dirParams = "";
-
- String[] splitPars = dirParams.split("(?<!'),");
- CLParameters arrParams = CLParameters.fromDirective(splitPars, tParams);
-
- CLModifiers mods = CLModifiers.fromString(dirMods);
-
- Object item = tParams.item();
- if(dirName == null && dirFunc != null) {
- /*
- * @TODO implement user-called functions.
- */
- continue;
- }
-
- if(extraDirectives.containsKey(dirName)) {
- extraDirectives.get(dirName).format(rw, item, mods, arrParams, tParams, dirMatcher,
- this);
-
- continue;
+ boolean doTail = true;
+ try {
+ while(dirMatcher.find()) {
+ dirMatcher.appendReplacement(sb, "");
+ rw.writeBuffer(sb);
+
+ String dirName = dirMatcher.group("name");
+ String dirFunc = dirMatcher.group("funcname");
+ String dirMods = dirMatcher.group("modifiers");
+ String dirParams = dirMatcher.group("params");
+
+ if(dirMods == null) dirMods = "";
+ if(dirParams == null) dirParams = "";
+
+ CLParameters arrParams = CLParameters.fromDirective(dirParams, tParams);
+
+ CLModifiers mods = CLModifiers.fromString(dirMods);
+
+ Object item = tParams.item();
+
+ if(dirName == null && dirFunc != null) {
+ /*
+ * @TODO implement user-called functions.
+ */
+ continue;
+ }
+
+ if(extraDirectives.containsKey(dirName)) {
+ extraDirectives.get(dirName).format(rw, item, mods, arrParams, tParams, dirMatcher,
+ this);
+
+ continue;
+ }
+
+ if(builtinDirectives.containsKey(dirName)) {
+ // System.err.printf("Executing directive %s (%s) (%d to %d) from string %s\n", dirName, dirMatcher.group(), dirMatcher.start(), dirMatcher.end(), format);
+
+ builtinDirectives.get(dirName).format(rw,
+ item, mods, arrParams, tParams, dirMatcher, this);
+
+ continue;
+ }
+
+ if(dirName == null) dirName = "<null>";
+
+ switch(dirName) {
+ case "]":
+ throw new IllegalArgumentException("Found conditional-end outside of conditional.");
+ case ";":
+ throw new IllegalArgumentException(
+ "Found seperator outside of block.");
+ case "}":
+ throw new IllegalArgumentException("Found iteration-end outside of iteration");
+ case "<":
+ case ">":
+ throw new IllegalArgumentException("Layout-control directives aren't implemented yet.");
+ case "F":
+ case "E":
+ case "G":
+ case "$":
+ /* @TODO implement floating point directives. */
+ throw new IllegalArgumentException("Floating-point directives aren't implemented yet.");
+ case "W":
+ /*
+ * @TODO figure out if we want to implement
+ * someting for these directives instead of
+ * punting.
+ */
+ throw new IllegalArgumentException("S and W aren't implemented. Use A instead");
+ case "P":
+ throw new IllegalArgumentException("These directives aren't implemented yet");
+ case ")":
+ throw new IllegalArgumentException("Case-conversion end outside of case conversion");
+ case "\n":
+ /*
+ * Ignored newline.
+ */
+ break;
+ default:
+ String msg = String.format("Unknown format directive '%s'", dirName);
+ throw new IllegalArgumentException(msg);
+ }
}
+ } catch (EscapeException eex) {
+ if (!isToplevel) throw eex;
- if(builtinDirectives.containsKey(dirName)) {
- builtinDirectives.get(dirName).format(rw, item, mods, arrParams, tParams, dirMatcher,
- this);
-
- continue;
- }
-
- if(dirName == null) dirName = "<null>";
-
- switch(dirName) {
- case "]":
- throw new IllegalArgumentException("Found conditional-end outside of conditional.");
- case ";":
- throw new IllegalArgumentException(
- "Found seperator outside of block.");
- case "}":
- throw new IllegalArgumentException("Found iteration-end outside of iteration");
- case "<":
- case ">":
- throw new IllegalArgumentException("Layout-control directives aren't implemented yet.");
- case "F":
- case "E":
- case "G":
- case "$":
- /* @TODO implement floating point directives. */
- throw new IllegalArgumentException("Floating-point directives aren't implemented yet.");
- case "S":
- case "W":
- /*
- * @TODO figure out if we want to implement
- * someting for these directives instead of
- * punting.
- */
- throw new IllegalArgumentException("S and W aren't implemented. Use A instead");
- case "?":
- case "(":
- case "P":
- throw new IllegalArgumentException("These directives aren't implemented yet");
- case ")":
- throw new IllegalArgumentException("Case-conversion end outside of case conversion");
- case "\n":
- /*
- * Ignored newline.
- */
- break;
- default:
- String msg = String.format("Unknown format directive '%s'", dirName);
- throw new UnknownFormatConversionException(msg);
- }
+ doTail = false;
}
- dirMatcher.appendTail(sb);
+ if (doTail) dirMatcher.appendTail(sb);
rw.writeBuffer(sb);
}
}
diff --git a/base/src/main/java/bjc/utils/ioutils/format/CLModifiers.java b/base/src/main/java/bjc/utils/ioutils/format/CLModifiers.java
index 0625ff8..68127b6 100644
--- a/base/src/main/java/bjc/utils/ioutils/format/CLModifiers.java
+++ b/base/src/main/java/bjc/utils/ioutils/format/CLModifiers.java
@@ -15,6 +15,14 @@ public class CLModifiers {
* Whether the colon mod is on.
*/
public final boolean colonMod;
+ /**
+ * Whether the dollar mod is on.
+ */
+ public final boolean dollarMod;
+ /**
+ * Whether the star mod is on.
+ */
+ public final boolean starMod;
/**
* Create a new set of CL modifiers.
@@ -23,10 +31,14 @@ public class CLModifiers {
* The state of the at mod.
* @param colon
* The state of the colon mod.
+ * @param dollar
+ * The state of the dollar mod.
*/
- public CLModifiers(boolean at, boolean colon) {
- atMod = at;
- colonMod = colon;
+ public CLModifiers(boolean at, boolean colon, boolean dollar, boolean star) {
+ atMod = at;
+ colonMod = colon;
+ dollarMod = dollar;
+ starMod = star;
}
/**
@@ -37,13 +49,18 @@ public class CLModifiers {
* @return A set of modifiers matching the string.
*/
public static CLModifiers fromString(String modString) {
- boolean atMod = false;
- boolean colonMod = false;
+ boolean atMod = false;
+ boolean colonMod = false;
+ boolean dollarMod = false;
+ boolean starMod = false;
+
if(modString != null) {
- atMod = modString.contains("@");
- colonMod = modString.contains(":");
+ atMod = modString.contains("@");
+ colonMod = modString.contains(":");
+ dollarMod = modString.contains("$");
+ starMod = modString.contains("*");
}
- return new CLModifiers(atMod, colonMod);
+ return new CLModifiers(atMod, colonMod, dollarMod, starMod);
}
-} \ No newline at end of file
+}
diff --git a/base/src/main/java/bjc/utils/ioutils/format/CLParameters.java b/base/src/main/java/bjc/utils/ioutils/format/CLParameters.java
index 2588446..bde7a7d 100644
--- a/base/src/main/java/bjc/utils/ioutils/format/CLParameters.java
+++ b/base/src/main/java/bjc/utils/ioutils/format/CLParameters.java
@@ -44,10 +44,33 @@ public class CLParameters {
*
* @return A set of CL parameters.
*/
- public static CLParameters fromDirective(String[] params, Tape<Object> dirParams) {
+ public static CLParameters fromDirective(String unsplit, Tape<Object> dirParams) {
+ List<String> lParams = new ArrayList<>();
+ StringBuilder currParm = new StringBuilder();
+
+ char prevChar = ' ';
+
+ for (int i = 0; i < unsplit.length(); i++) {
+ char c = unsplit.charAt(i);
+
+ if (c == ',' && prevChar != '\'') {
+ lParams.add(currParm.toString());
+
+ currParm = new StringBuilder();
+ } else {
+ currParm.append(c);
+ }
+
+ prevChar = c;
+ }
+ lParams.add(currParm.toString());
+
List<String> parameters = new ArrayList<>();
- for(String param : params) {
+ if (lParams.size() == 1 && lParams.get(0).equals(""))
+ return new CLParameters(parameters.toArray(new String[0]));
+
+ for(String param : lParams) {
if(param.equalsIgnoreCase("V")) {
Object par = dirParams.item();
boolean succ = dirParams.right();
@@ -73,7 +96,9 @@ public class CLParameters {
throw new IllegalArgumentException(
"Incorrect type of parameter for V inline parameter");
}
- } else if(param.equals("#")) {
+ } else if (param.equals("#")) {
+ parameters.add(Integer.toString(dirParams.size() - dirParams.position()));
+ } else if (param.equals("%")) {
parameters.add(Integer.toString(dirParams.position()));
} else {
parameters.add(param);
@@ -119,9 +144,14 @@ public class CLParameters {
public char getChar(int idx, String paramName, char directive) {
String param = params[idx];
+ if (param.length() == 1) {
+ // Punt in the case we have a slightly malformed issue
+ return param.charAt(0);
+ }
+
if(!param.startsWith("'")) {
throw new IllegalArgumentException(
- String.format("Invalid %s %s to %c directive", paramName, param, directive));
+ String.format("Invalid %s \"%s\" to %c directive", paramName, param, directive));
}
return param.charAt(1);
@@ -166,7 +196,7 @@ public class CLParameters {
try {
return Integer.parseInt(param);
} catch(NumberFormatException nfex) {
- String msg = String.format("Invalid %s %s to %c directive", paramName, param, directive);
+ String msg = String.format("Invalid %s \"%s\" to %c directive", paramName, param, directive);
IllegalArgumentException iaex = new IllegalArgumentException(msg);
iaex.initCause(nfex);
@@ -174,4 +204,21 @@ public class CLParameters {
throw iaex;
}
}
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder("[");
+
+ for (int i = 0; i < params.length; i++) {
+ if (i != 0) sb.append(", ");
+
+ sb.append("\"");
+ sb.append(params[i]);
+ sb.append("\"");
+ }
+
+ sb.append("]");
+
+ return sb.toString();
+ }
}
diff --git a/base/src/main/java/bjc/utils/ioutils/format/directives/AestheticDirective.java b/base/src/main/java/bjc/utils/ioutils/format/directives/AestheticDirective.java
index 4276f40..9bad6d7 100644
--- a/base/src/main/java/bjc/utils/ioutils/format/directives/AestheticDirective.java
+++ b/base/src/main/java/bjc/utils/ioutils/format/directives/AestheticDirective.java
@@ -21,6 +21,7 @@ public class AestheticDirective implements Directive {
@Override
public void format(ReportWriter rw, Object item, CLModifiers mods, CLParameters params, Tape<Object> tParams,
Matcher dirMatcher, CLFormatter fmt) throws IOException {
+ // System.err.printf("Aesthetic directive with item \"%s\" and params: %s\n", item, tParams);
CLFormatter.checkItem(item, 'A');
int mincol = 0, colinc = 1, minpad = 0;
diff --git a/base/src/main/java/bjc/utils/ioutils/format/directives/CaseDirective.java b/base/src/main/java/bjc/utils/ioutils/format/directives/CaseDirective.java
new file mode 100644
index 0000000..728bb43
--- /dev/null
+++ b/base/src/main/java/bjc/utils/ioutils/format/directives/CaseDirective.java
@@ -0,0 +1,117 @@
+
+package bjc.utils.ioutils.format.directives;
+
+import bjc.utils.esodata.Tape;
+import bjc.utils.ioutils.format.*;
+import bjc.utils.ioutils.ReportWriter;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.IllegalFormatConversionException;
+import java.util.List;
+import java.util.logging.Logger;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class CaseDirective implements Directive {
+ private static final Pattern wordPattern = Pattern.compile("(\\w+)(\\b*)");
+
+ @Override
+ public void format(ReportWriter rw, Object item, CLModifiers mods, CLParameters params, Tape<Object> tParams,
+ Matcher dirMatcher, CLFormatter fmt) throws IOException {
+ StringBuffer condBody = new StringBuffer();
+
+ int nestLevel = 1;
+
+ while (dirMatcher.find()) {
+ /* Process a list of clauses. */
+ String dirName = dirMatcher.group("name");
+
+ if (dirName != null) {
+ /* Append everything up to this directive. */
+ dirMatcher.appendReplacement(condBody, "");
+
+ if (dirName.equals("(")) {
+ if (nestLevel > 0) {
+ condBody.append(dirMatcher.group());
+ }
+
+ nestLevel += 1;
+ } else if (Directive.isOpening(dirName)) {
+ nestLevel += 1;
+
+ condBody.append(dirMatcher.group());
+ } else if (dirName.equals(")")) {
+ nestLevel = Math.max(0, nestLevel - 1);
+
+ /* End the iteration. */
+ if (nestLevel == 0) break;
+ } else if (Directive.isClosing(dirName)) {
+ nestLevel = Math.max(0, nestLevel - 1);
+ } else {
+ /* Not a special directive. */
+ condBody.append(dirMatcher.group());
+ }
+ }
+ }
+
+ String frmt = condBody.toString();
+
+ ReportWriter nrw = rw.duplicate(new StringWriter());
+
+ fmt.doFormatString(frmt, nrw, tParams, false);
+
+ String strang = nrw.toString();
+
+ if (mods.colonMod && mods.atMod) {
+ strang = strang.toUpperCase();
+ } else if (mods.colonMod) {
+ Matcher mat = wordPattern.matcher(strang);
+
+ StringBuffer sb = new StringBuffer();
+ while(!mat.find()) {
+ mat.appendReplacement(sb, "");
+
+ String word = mat.group(1);
+
+ word = word.substring(0, 1).toUpperCase() + word.substring(1);
+
+ sb.append(word);
+ sb.append(mat.group(2));
+ }
+
+ mat.appendTail(sb);
+
+ strang = sb.toString();
+ } else if (mods.atMod) {
+ Matcher mat = wordPattern.matcher(strang);
+
+ StringBuffer sb = new StringBuffer();
+ boolean doCap = true;
+ while(!mat.find()) {
+ mat.appendReplacement(sb, "");
+
+ String word = mat.group(1);
+
+ if (doCap) {
+ doCap = false;
+
+ word = word.substring(0, 1).toUpperCase() + word.substring(1);
+ }
+
+ sb.append(word);
+ sb.append(mat.group(2));
+ }
+
+ mat.appendTail(sb);
+
+ strang = sb.toString();
+
+ } else {
+ strang = strang.toLowerCase();
+ }
+
+ rw.write(strang);
+ }
+}
diff --git a/base/src/main/java/bjc/utils/ioutils/format/directives/ConditionalDirective.java b/base/src/main/java/bjc/utils/ioutils/format/directives/ConditionalDirective.java
index 71d9e7d..ed0b39b 100644
--- a/base/src/main/java/bjc/utils/ioutils/format/directives/ConditionalDirective.java
+++ b/base/src/main/java/bjc/utils/ioutils/format/directives/ConditionalDirective.java
@@ -8,6 +8,7 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.IllegalFormatConversionException;
import java.util.List;
+import java.util.logging.Logger;
import java.util.regex.Matcher;
/**
@@ -17,6 +18,7 @@ import java.util.regex.Matcher;
*
*/
public class ConditionalDirective implements Directive {
+ private static Logger LOG = Logger.getLogger(ConditionalDirective.class.getName());
@Override
public void format(ReportWriter rw, Object item, CLModifiers mods, CLParameters arrParams,
@@ -24,42 +26,75 @@ public class ConditionalDirective implements Directive {
StringBuffer condBody = new StringBuffer();
List<String> clauses = new ArrayList<>();
- String defClause = null;
+
+ String defClause = null;
boolean isDefault = false;
+ int nestLevel = 1;
+
while (dirMatcher.find()) {
/* Process a list of clauses. */
String dirName = dirMatcher.group("name");
String dirMods = dirMatcher.group("modifiers");
+ //System.err.printf("Found conditional directive %s with %s mods and level %d\n", dirName, dirMods, nestLevel);
if (dirName != null) {
/* Append everything up to this directive. */
dirMatcher.appendReplacement(condBody, "");
- if (dirName.equals("]")) {
- /* End the conditional. */
- String clause = condBody.toString();
- if (isDefault) {
- defClause = clause;
- } else {
+ if (dirName.equals("[")) {
+ if (nestLevel > 0) {
+ condBody.append(dirMatcher.group());
+ }
+ nestLevel += 1;
+ } else if (Directive.isOpening(dirName)) {
+ nestLevel += 1;
+
+ condBody.append(dirMatcher.group());
+ } else if (dirName.equals("]")) {
+ nestLevel = Math.max(0, nestLevel - 1);
+
+ if (nestLevel == 0) {
+ /* End the conditional. */
+ String clause = condBody.toString();
+ // System.err.printf("Found clause \"%s]\"\n", clause);
+ condBody = new StringBuffer();
+
+ if (isDefault) {
+ defClause = clause;
+ }
clauses.add(clause);
+
+ break;
+ } else {
+ /* Not a special directive. */
+ condBody.append(dirMatcher.group());
}
+ } else if (Directive.isClosing(dirName)) {
+ nestLevel = Math.max(0, nestLevel - 1);
- break;
+ condBody.append(dirMatcher.group());
} else if (dirName.equals(";")) {
- /* End the clause. */
- String clause = condBody.toString();
- if (isDefault) {
- defClause = clause;
- } else {
+ if (nestLevel == 1) {
+ /* End the clause. */
+ String clause = condBody.toString();
+ // System.err.printf("Found clause \"%s;\"\n", clause);
+ condBody = new StringBuffer();
+
+ if (isDefault) {
+ defClause = clause;
+ }
clauses.add(clause);
- }
- /*
- * Mark the next clause as the default.
- */
- if (dirMods.contains(":")) {
- isDefault = true;
+ /*
+ * Mark the next clause as the default.
+ */
+ if (dirMods.contains(":")) {
+ isDefault = true;
+ }
+ } else {
+ /* Not a special directive. */
+ condBody.append(dirMatcher.group());
}
} else {
/* Not a special directive. */
@@ -67,18 +102,21 @@ public class ConditionalDirective implements Directive {
}
}
}
+
+ if (mods.starMod && clauses.size() > 0) defClause = clauses.get(0);
- Object par = formatParams.item();
try {
if (mods.colonMod) {
formatParams.right();
- if (par == null) {
- throw new IllegalArgumentException("No parameter provided for [ directive.");
- } else if (!(par instanceof Boolean)) {
- throw new IllegalFormatConversionException('[', par.getClass());
+ boolean res = false;
+ if (item == null) {
+ //throw new IllegalArgumentException("No parameter provided for [ directive.");
+ } else if (!(item instanceof Boolean)) {
+ throw new IllegalFormatConversionException('[', item.getClass());
+ } else {
+ res = (Boolean) item;
}
- boolean res = (Boolean) par;
String frmt;
if (res)
@@ -86,17 +124,21 @@ public class ConditionalDirective implements Directive {
else
frmt = clauses.get(0);
- fmt.doFormatString(frmt, rw, formatParams);
+ fmt.doFormatString(frmt, rw, formatParams, false);
} else if (mods.atMod) {
- if (par == null) {
- throw new IllegalArgumentException("No parameter provided for [ directive.");
- } else if (!(par instanceof Boolean)) {
- throw new IllegalFormatConversionException('[', par.getClass());
+ boolean res = false;
+ if (item == null) {
+ // throw new IllegalArgumentException("No parameter provided for [ directive.");
+ } else if (item instanceof Integer) {
+ if ((Integer)item != 0) res = true;
+ } else if (item instanceof Boolean) {
+ res = (Boolean) item;
+ } else {
+ throw new IllegalFormatConversionException('[', item.getClass());
}
- boolean res = (Boolean) par;
if (res) {
- fmt.doFormatString(clauses.get(0), rw, formatParams);
+ fmt.doFormatString(clauses.get(0), rw, formatParams, false);
} else {
formatParams.right();
}
@@ -105,21 +147,33 @@ public class ConditionalDirective implements Directive {
if (arrParams.length() >= 1) {
res = arrParams.getInt(0, "conditional choice", '[');
} else {
- if (par == null) {
+ if (item == null) {
throw new IllegalArgumentException("No parameter provided for [ directive.");
- } else if (!(par instanceof Number)) {
- throw new IllegalFormatConversionException('[', par.getClass());
+ } else if (!(item instanceof Number)) {
+ throw new IllegalFormatConversionException('[', item.getClass());
}
- res = ((Number) par).intValue();
+ res = ((Number) item).intValue();
formatParams.right();
}
- if (res < 0 || res > clauses.size()) {
- if (defClause != null)
- fmt.doFormatString(defClause, rw, formatParams);
+ if (mods.dollarMod) res -= 1;
+
+ // System.err.printf("Attempting selection of clause %d of %d (%s) (default %s)\n",
+ // res, clauses.size(), clauses, defClause);
+ if (clauses.size() == 0 || res < 0 || res >= clauses.size()) {
+ // System.err.printf("Selecting default clause (res %d, max %d): %s\n", res, clauses.size(), defClause);
+ // int clauseNo = 0;
+ // for (String clause : clauses) {
+ // System.err.printf("... clause %d: %s\n", ++clauseNo, clause);
+ // }
+
+ if (defClause != null) fmt.doFormatString(defClause, rw, formatParams, false);
} else {
- fmt.doFormatString(clauses.get(res), rw, formatParams);
+ String frmt = clauses.get(res);
+
+ // System.out.printf("Selecting clause %d of %d (params %s): %s\n", res, clauses.size(), formatParams, frmt);
+ fmt.doFormatString(frmt, rw, formatParams, false);
}
}
} catch (EscapeException eex) {
diff --git a/base/src/main/java/bjc/utils/ioutils/format/directives/Directive.java b/base/src/main/java/bjc/utils/ioutils/format/directives/Directive.java
index ad9c34c..61abfc1 100644
--- a/base/src/main/java/bjc/utils/ioutils/format/directives/Directive.java
+++ b/base/src/main/java/bjc/utils/ioutils/format/directives/Directive.java
@@ -37,4 +37,36 @@ public interface Directive {
*/
public void format(ReportWriter rw, Object item, CLModifiers mods, CLParameters arrParams, Tape<Object> tParams,
Matcher dirMatcher, CLFormatter fmt) throws IOException;
+
+ public static boolean isOpening(String str) {
+ return isOpening(str.charAt(0));
+ }
+
+ public static boolean isOpening(char dir) {
+ switch(dir) {
+ case '(':
+ case '<':
+ case '[':
+ case '{':
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ public static boolean isClosing(String str) {
+ return isClosing(str.charAt(0));
+ }
+
+ public static boolean isClosing(char dir) {
+ switch(dir) {
+ case ')':
+ case '>':
+ case ']':
+ case '}':
+ return true;
+ default:
+ return false;
+ }
+ }
}
diff --git a/base/src/main/java/bjc/utils/ioutils/format/directives/EscapeDirective.java b/base/src/main/java/bjc/utils/ioutils/format/directives/EscapeDirective.java
index 5badff0..74488ed 100644
--- a/base/src/main/java/bjc/utils/ioutils/format/directives/EscapeDirective.java
+++ b/base/src/main/java/bjc/utils/ioutils/format/directives/EscapeDirective.java
@@ -21,28 +21,35 @@ public class EscapeDirective implements Directive {
Tape<Object> formatParams, Matcher dirMatcher, CLFormatter fmt) {
boolean shouldExit;
+ if (mods.dollarMod) formatParams.right();
+
switch(params.length()) {
case 0:
- shouldExit = formatParams.size() == 0;
+ shouldExit = formatParams.atEnd();
break;
case 1:
int num = params.getInt(0, "condition count", '^');
+
shouldExit = num == 0;
break;
case 2:
- int left = params.getInt(0, "left-hand condition", '^');
+ int left = params.getInt(0, "left-hand condition", '^');
int right = params.getInt(1, "right-hand condition", '^');
+
shouldExit = left == right;
break;
case 3:
default:
- int low = params.getInt(0, "lower-bound condition", '^');
- int mid = params.getInt(1, "interval condition", '^');
+ int low = params.getInt(0, "lower-bound condition", '^');
+ int mid = params.getInt(1, "interval condition", '^');
int high = params.getInt(2, "upper-bound condition", '^');
+
shouldExit = (low <= mid) && (mid <= high);
break;
}
+ if (mods.dollarMod) formatParams.left();
+
/* At negates it. */
if(mods.atMod) shouldExit = !shouldExit;
diff --git a/base/src/main/java/bjc/utils/ioutils/format/directives/GeneralNumberDirective.java b/base/src/main/java/bjc/utils/ioutils/format/directives/GeneralNumberDirective.java
index ccf01d8..3eb741e 100644
--- a/base/src/main/java/bjc/utils/ioutils/format/directives/GeneralNumberDirective.java
+++ b/base/src/main/java/bjc/utils/ioutils/format/directives/GeneralNumberDirective.java
@@ -38,10 +38,10 @@ public abstract class GeneralNumberDirective implements Directive {
*/
int commaInterval = 0;
char commaChar = ',';
- if (params.length() >= (argidx + 3)) {
- commaChar = params.getCharDefault((argidx + 3), "comma character", 'R', ' ');
- }
if (params.length() >= (argidx + 4)) {
+ commaChar = params.getCharDefault((argidx + 3), "comma character", 'R', ',');
+ }
+ if (params.length() >= (argidx + 5)) {
commaInterval = params.getIntDefault((argidx + 4), "comma interval", 'R', 0);
}
diff --git a/base/src/main/java/bjc/utils/ioutils/format/directives/IterationDirective.java b/base/src/main/java/bjc/utils/ioutils/format/directives/IterationDirective.java
index 97e392e..2ce6309 100644
--- a/base/src/main/java/bjc/utils/ioutils/format/directives/IterationDirective.java
+++ b/base/src/main/java/bjc/utils/ioutils/format/directives/IterationDirective.java
@@ -36,18 +36,18 @@ public class IterationDirective implements Directive {
dirMatcher.appendReplacement(condBody, "");
if (dirName.equals("}")) {
- /* End the iteration. */
break;
+ } else {
+ /* Not a special directive. */
+ condBody.append(dirMatcher.group());
}
-
- /* Not a special directive. */
- condBody.append(dirMatcher.group());
}
}
String frmt = condBody.toString();
Object iter = item;
+ // System.err.printf("Iteration format \"%s\" (iter %s)\n", frmt, item);
if (frmt.equals("")) {
/* Grab an argument. */
if (!(item instanceof String)) {
@@ -86,25 +86,29 @@ public class IterationDirective implements Directive {
Tape<Object> nParams = new SingleTape<>(nitr);
try {
- fmt.doFormatString(frmt, rw, nParams);
+ fmt.doFormatString(frmt, rw, nParams, false);
} catch (EscapeException eex) {
if (eex.endIteration) {
- if (tParams.atEnd()) throw eex;
+ if (tParams.atEnd()) {
+ throw eex;
+ }
}
}
- iter = tParams.right();
+ tParams.right();
+ iter = tParams.item();
} while (tParams.position() < tParams.size());
} catch (EscapeException eex) {
}
} else if (mods.atMod) {
try {
- while (tParams.position() < tParams.size()) {
- if (numItr > maxItr) break;
- numItr += 1;
+ while (!tParams.atEnd()) {
+ // System.err.printf("Iterating with format \"%s\"\n", frmt);
+ if (numItr > maxItr) break;
+ numItr += 1;
- fmt.doFormatString(frmt, rw, tParams);
- }
+ fmt.doFormatString(frmt, rw, tParams, false);
+ }
} catch (EscapeException eex) {
if (eex.endIteration)
throw new UnsupportedOperationException("Colon mod not allowed on escape marker without colon mod on iteration");
@@ -133,13 +137,12 @@ public class IterationDirective implements Directive {
Tape<Object> nParams = new SingleTape<>(nitr);
try {
- fmt.doFormatString(frmt, rw, nParams);
+ fmt.doFormatString(frmt, rw, nParams, false);
} catch (EscapeException eex) {
if(eex.endIteration && !itr.hasNext()) throw eex;
}
}
- }
- catch (EscapeException eex) {
+ } catch (EscapeException eex) {
}
} else {
if (!(item instanceof Iterable<?>)) {
@@ -149,16 +152,13 @@ public class IterationDirective implements Directive {
try {
@SuppressWarnings("unchecked")
Iterable<Object> itr = (Iterable<Object>) item;
-
Tape<Object> nParams = new SingleTape<>(itr);
- while (nParams.position() < nParams.size()) {
- if (numItr > maxItr)
- break;
+ while (!nParams.atEnd()) {
+ if (numItr > maxItr) break;
numItr += 1;
- fmt.doFormatString(frmt, rw, nParams);
-
+ fmt.doFormatString(frmt, rw, nParams, false);
}
} catch (EscapeException eex) {
if (eex.endIteration)
diff --git a/base/src/main/java/bjc/utils/ioutils/format/directives/NumberDirective.java b/base/src/main/java/bjc/utils/ioutils/format/directives/NumberDirective.java
index 763665d..88b3e7e 100644
--- a/base/src/main/java/bjc/utils/ioutils/format/directives/NumberDirective.java
+++ b/base/src/main/java/bjc/utils/ioutils/format/directives/NumberDirective.java
@@ -26,21 +26,25 @@ public class NumberDirective extends GeneralNumberDirective {
* @param radix
* The radix of the number to use.
*/
- public NumberDirective(int argidx, int radix) {
+ public NumberDirective(int argidx, int radix, char directive) {
this.argidx = argidx;
this.radix = radix;
+
+ this.directive = directive;
}
private int argidx;
private int radix;
+ private char directive;
+
@Override
public void format(ReportWriter rw, Object item, CLModifiers mods, CLParameters params, Tape<Object> tParams,
Matcher dirMatcher, CLFormatter fmt) throws IOException {
- CLFormatter.checkItem(item, 'B');
+ CLFormatter.checkItem(item, directive);
if (!(item instanceof Number)) {
- throw new IllegalFormatConversionException('B', item.getClass());
+ throw new IllegalFormatConversionException(directive, item.getClass());
}
long val = ((Number) item).longValue();
diff --git a/base/src/main/java/bjc/utils/ioutils/format/directives/RecursiveDirective.java b/base/src/main/java/bjc/utils/ioutils/format/directives/RecursiveDirective.java
new file mode 100644
index 0000000..44a25ad
--- /dev/null
+++ b/base/src/main/java/bjc/utils/ioutils/format/directives/RecursiveDirective.java
@@ -0,0 +1,49 @@
+package bjc.utils.ioutils.format.directives;
+
+import bjc.utils.esodata.SingleTape;
+import bjc.utils.esodata.Tape;
+import bjc.utils.ioutils.format.*;
+import bjc.utils.ioutils.ReportWriter;
+import java.util.IllegalFormatConversionException;
+
+import java.io.IOException;
+import java.util.regex.Matcher;
+
+public class RecursiveDirective implements Directive {
+ public void format(ReportWriter rw, Object arg, CLModifiers mods, CLParameters params, Tape<Object> tParams,
+ Matcher dirMatcher, CLFormatter fmt) throws IOException {
+ tParams.right();
+
+ CLFormatter.checkItem(arg, '?');
+
+ if (mods.atMod) {
+ if (!(arg instanceof String))
+ throw new IllegalFormatConversionException('?', arg.getClass());
+
+ try {
+ fmt.doFormatString((String)arg, rw, tParams, true);
+ } catch (EscapeException eex) {
+ if (eex.endIteration)
+ throw new UnsupportedOperationException("Colon mod not allowed on escape marker without colon mod on iteration");
+ }
+ } else {
+ if (tParams.atEnd())
+ throw new IllegalArgumentException("? directive requires two format parameters");
+
+ Object o = tParams.item();
+ tParams.right();
+
+ if (!(o instanceof Iterable))
+ throw new IllegalFormatConversionException('?', o.getClass());
+
+ Iterable<Object> itb = (Iterable<Object>)o;
+ Tape<Object> newParams = new SingleTape<>(itb);
+
+ try {
+ fmt.doFormatString((String)arg, rw, newParams, true);
+ } catch (EscapeException eex) {
+ throw new UnsupportedOperationException("Colon mod not allowed on escape marker without colon mod on iteration");
+ }
+ }
+ }
+}
diff --git a/base/src/main/java/bjc/utils/ioutils/format/directives/TabulateDirective.java b/base/src/main/java/bjc/utils/ioutils/format/directives/TabulateDirective.java
index 7775904..d9136f2 100644
--- a/base/src/main/java/bjc/utils/ioutils/format/directives/TabulateDirective.java
+++ b/base/src/main/java/bjc/utils/ioutils/format/directives/TabulateDirective.java
@@ -14,7 +14,7 @@ public class TabulateDirective implements Directive {
// Unsupported feature.
//
// I can't really make out what this is supposed to do from the
- // documentation, but I suspect that it depends of font glyph
+ // documentation, but I suspect that it depends on font glyph
// size, not character positions
if (mods.colonMod) {
throw new UnsupportedOperationException("Colon mod is not supported for T directive");