diff options
| author | Benjamin J. Culkin <bjculkin@mix.wvu.edu> | 2019-07-26 17:38:12 -0300 |
|---|---|---|
| committer | Benjamin J. Culkin <bjculkin@mix.wvu.edu> | 2019-07-26 17:38:12 -0300 |
| commit | d317469f2063e7e57f97df9381d23a94bbc43bb0 (patch) | |
| tree | eaf0adb827ed3d9265154f722355c817e8896923 | |
| parent | 58ba68ad475074311a8921067ea04feb6f22588d (diff) | |
Refactor directive handling
Refactored the tokenizer to pass back tokens which have the data stored
on them, significantly cutting down on the amount of parsing/reparsing
of directives we are doing.
Also, it makes the over-arching goal of allowing compilation easier
21 files changed, 427 insertions, 279 deletions
diff --git a/clformat/src/main/java/bjc/utils/ioutils/format/CLFormatter.java b/clformat/src/main/java/bjc/utils/ioutils/format/CLFormatter.java index 12802cf..c68e8f5 100644 --- a/clformat/src/main/java/bjc/utils/ioutils/format/CLFormatter.java +++ b/clformat/src/main/java/bjc/utils/ioutils/format/CLFormatter.java @@ -230,57 +230,91 @@ public class CLFormatter { public void doFormatString(String format, ReportWriter rw, Tape<Object> tParams, boolean isToplevel) throws IOException { CLTokenizer cltok = new CLTokenizer(format); + doFormatString(cltok, rw, tParams, isToplevel); + } + + /** + * Fill in a partially started format string. + * + * Used mostly for directives that require formatting again with a + * different string. + * + * @param cltok + * The place to get tokens from. + * + * @param rw + * The buffer to file output into. + * + * @param tParams + * The parameters to use. + * + * @param isToplevel + * Whether or not this is a top-level format + * + * @throws IOException If something goes wrong + */ + public void doFormatString(Iterable<Decree> cltok, ReportWriter rw, Tape<Object> tParams, boolean isToplevel) throws IOException { + doFormatString(cltok.iterator(), rw, tParams, isToplevel); + } + /** + * Fill in a partially started format string. + * + * Used mostly for directives that require formatting again with a + * different string. + * + * @param cltok + * The place to get tokens from. + * + * @param rw + * The buffer to file output into. + * + * @param tParams + * The parameters to use. + * + * @param isToplevel + * Whether or not this is a top-level format + * + * @throws IOException If something goes wrong + */ + public void doFormatString(Iterator<Decree> cltok, ReportWriter rw, Tape<Object> tParams, boolean isToplevel) throws IOException { boolean doTail = true; + try { while (cltok.hasNext()) { - String direc = cltok.next(); + Decree decr = cltok.next(); - if (!direc.startsWith("~")) { - rw.write(direc); + if (decr.isLiteral) { + rw.write(decr.name); continue; } - Matcher dirMatcher = CLPattern.getDirectiveMatcher(direc); - if (!dirMatcher.find()) { - throw new IllegalArgumentException("Unable to match directive found from tokenizer"); - } - - 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); - - CLModifiers mods = CLModifiers.fromString(dirMods); - Object item = tParams.item(); - if(dirName == null && dirFunc != null) { + if(decr.isUserCall) { /* * @TODO implement user-called functions. */ continue; } - if(extraDirectives.containsKey(dirName)) { - extraDirectives.get(dirName).format(new FormatParameters(rw, item, mods, arrParams, tParams, cltok, this)); + if(extraDirectives.containsKey(decr.name)) { + FormatParameters params = new FormatParameters(rw, item, decr, tParams, cltok, this); + + extraDirectives.get(decr.name).format(params); continue; } - if(builtinDirectives.containsKey(dirName)) { - builtinDirectives.get(dirName).format(new FormatParameters(rw, item, mods, arrParams, tParams, cltok, this)); + if(builtinDirectives.containsKey(decr.name)) { + FormatParameters params = new FormatParameters(rw, item, decr, tParams, cltok, this); + builtinDirectives.get(decr.name).format(params); continue; } - if(dirName == null) dirName = "<null>"; + if(decr.name == null) decr.name = "<null>"; - switch(dirName) { + switch(decr.name) { case "]": throw new IllegalArgumentException("Found conditional-end outside of conditional."); case ";": @@ -325,7 +359,7 @@ public class CLFormatter { */ break; default: - String msg = String.format("Unknown format directive '%s'", dirName); + String msg = String.format("Unknown format directive '%s'", decr.name); throw new IllegalArgumentException(msg); } } 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 8c1857f..7c76696 100644 --- a/clformat/src/main/java/bjc/utils/ioutils/format/CLTokenizer.java +++ b/clformat/src/main/java/bjc/utils/ioutils/format/CLTokenizer.java @@ -7,10 +7,10 @@ import java.util.regex.Matcher; import bjc.utils.ioutils.SimpleProperties; import bjc.utils.ioutils.format.directives.*; -public class CLTokenizer implements Iterator<String> { +public class CLTokenizer implements Iterator<Decree> { private Matcher mat; - private String dir; + private Decree dir; public CLTokenizer(String strang) { this.mat = CLPattern.getDirectiveMatcher(strang); @@ -22,20 +22,20 @@ public class CLTokenizer implements Iterator<String> { } @Override - public String next() { - String tk = getNext(); - // System.out.printf("\tToken: %s\n", tk); + public Decree next() { + Decree tk = getNext(); return tk; } - private String getNext() { - if (!hasNext()) return ""; + private Decree getNext() { + if (!hasNext()) return null; if (dir != null) { - String tmp = dir; + Decree tmp = dir; dir = null; + return tmp; } @@ -44,20 +44,42 @@ public class CLTokenizer implements Iterator<String> { while (mat.find()) { mat.appendReplacement(sb, ""); - dir = mat.group(); - String tmp = sb.toString(); + + { + String dirName = mat.group("name"); + String dirFunc = mat.group("funcname"); + String dirMods = mat.group("modifiers"); + String dirParams = mat.group("params"); + + if(dirMods == null) { + dirMods = ""; + } + + if(dirParams == null) { + dirParams = ""; + } + + boolean isUser = dirName == null && dirFunc != null; + + dir = new Decree(dirName, isUser, + CLParameters.fromDirective(dirParams), + CLModifiers.fromString(dirMods)); + } + if (tmp.equals("")) { + Decree dcr = dir; + dir = null; - return mat.group(); + return dcr; } - return sb.toString(); + return new Decree(sb.toString()); } mat.appendTail(sb); - return sb.toString(); + return new Decree(sb.toString()); } } diff --git a/clformat/src/main/java/bjc/utils/ioutils/format/Decree.java b/clformat/src/main/java/bjc/utils/ioutils/format/Decree.java new file mode 100644 index 0000000..ce1f04d --- /dev/null +++ b/clformat/src/main/java/bjc/utils/ioutils/format/Decree.java @@ -0,0 +1,106 @@ +package bjc.utils.ioutils.format; + +/** + * A decree is the building blocks of what we need to pick and call a directive. + * + * Namely, it is the name of the directive, any modifiers attached to the + * directive, and any prefix parameters that are also attached to the directive. + * + * @author Ben Culkin. + */ +public class Decree { + /** + * The name of the directive. + */ + public String name; + + /** + * Is this directive an actual directive, or just a literal string? + */ + public boolean isLiteral; + + /** + * Is this directive a user function call? + */ + public boolean isUserCall; + + /** + * The prefix parameters for this directive. + */ + public CLParameters parameters; + + /** + * The modifiers for this directive. + */ + public CLModifiers modifiers; + + /** + * Create a new blank decree. + */ + public Decree() { + + } + + /** + * Create a new literal text directive. + * + * @param txt + * The text of the directive. + */ + public Decree(String txt) { + this.name = txt; + + this.isLiteral = true; + } + + /** + * Create a new directive. + * + * @param name + * The name of the directive. Whether or not it is an actual directive will + * be auto-determined (if it starts with a ~, it's a directive.) + * + * @param params + * The prefix parameters to the directive. + * + * @param mods + * The modifiers to the directive. + */ + public Decree(String name, CLParameters params, CLModifiers mods) { + this.name = name; + + this.parameters = params; + + this.modifiers = mods; + + this.isLiteral = false; + } + + /** + * Create a new directive that may be a user function. + * + * @param name + * The name of the directive. Whether or not it is an actual directive will + * be auto-determined (if it starts with a ~ and is not a user function, it's a directive.) + * + * @param isUser + * Is this directive a user function? + * + * @param params + * The prefix parameters to the directive. + * + * @param mods + * The modifiers to the directive. + */ + public Decree(String name, boolean isUser, CLParameters params, CLModifiers mods) { + this.name = name; + + this.parameters = params; + + this.modifiers = mods; + + this.isUserCall = isUser; + + this.isLiteral = isUser; + } +} diff --git a/clformat/src/main/java/bjc/utils/ioutils/format/directives/AestheticDirective.java b/clformat/src/main/java/bjc/utils/ioutils/format/directives/AestheticDirective.java index d0a5d92..35119e5 100644 --- a/clformat/src/main/java/bjc/utils/ioutils/format/directives/AestheticDirective.java +++ b/clformat/src/main/java/bjc/utils/ioutils/format/directives/AestheticDirective.java @@ -27,7 +27,8 @@ public class AestheticDirective implements Directive { char padchar = ' '; - CLParameters params = dirParams.arrParams; + CLParameters params = dirParams.getParams(); + CLModifiers mods = dirParams.getMods(); // We take 0, 1 or 4 parameters switch (params.length()) { @@ -56,7 +57,7 @@ public class AestheticDirective implements Directive { StringBuilder work = new StringBuilder(); - if (dirParams.mods.atMod) { + if (mods.atMod) { for (int i = 0; i < minpad; i++) { work.append(padchar); } @@ -70,7 +71,7 @@ public class AestheticDirective implements Directive { work.append(tmp); - if (!dirParams.mods.atMod) { + if (!mods.atMod) { for (int i = 0; i < minpad; i++) { work.append(padchar); } diff --git a/clformat/src/main/java/bjc/utils/ioutils/format/directives/CaseDirective.java b/clformat/src/main/java/bjc/utils/ioutils/format/directives/CaseDirective.java index 7943fb9..4bb54b4 100644 --- a/clformat/src/main/java/bjc/utils/ioutils/format/directives/CaseDirective.java +++ b/clformat/src/main/java/bjc/utils/ioutils/format/directives/CaseDirective.java @@ -1,48 +1,44 @@ package bjc.utils.ioutils.format.directives; -import java.io.IOException; -import java.io.StringWriter; -import java.util.Iterator; -import java.util.regex.Matcher; -import java.util.regex.Pattern; +import java.io.*; +import java.util.*; +import java.util.regex.*; -import bjc.utils.ioutils.ReportWriter; -import bjc.utils.ioutils.format.CLPattern; +import bjc.utils.ioutils.*; +import bjc.utils.ioutils.format.*; public class CaseDirective implements Directive { private static final Pattern wordPattern = Pattern.compile("(\\w+)(\\b*)"); @Override public void format(FormatParameters dirParams) throws IOException { - StringBuilder condBody = new StringBuilder(); + CLModifiers mods = dirParams.getMods(); + + List<Decree> condBody = new ArrayList<>(); int nestLevel = 1; - Iterator<String> dirIter = dirParams.dirIter; - while (dirParams.dirIter.hasNext()) { - String direc = dirIter.next(); - if (!direc.startsWith("~")) { - condBody.append(direc); + Iterator<Decree> dirIter = dirParams.dirIter; + while (dirIter.hasNext()) { + Decree decr = dirIter.next(); + if (decr.isLiteral) { + condBody.add(decr); continue; } - Matcher dirMat = CLPattern.getDirectiveMatcher(direc); - dirMat.find(); - - /* Process a list of clauses. */ - String dirName = dirMat.group("name"); + String dirName = decr.name; if (dirName != null) { if (dirName.equals("(")) { if (nestLevel > 0) { - condBody.append(dirMat.group()); + condBody.add(decr); } nestLevel += 1; } else if (Directive.isOpening(dirName)) { nestLevel += 1; - condBody.append(dirMat.group()); + condBody.add(decr); } else if (dirName.equals(")")) { nestLevel = Math.max(0, nestLevel - 1); @@ -52,22 +48,20 @@ public class CaseDirective implements Directive { nestLevel = Math.max(0, nestLevel - 1); } else { /* Not a special directive. */ - condBody.append(dirMat.group()); + condBody.add(decr); } } } - String frmt = condBody.toString(); - ReportWriter nrw = dirParams.rw.duplicate(new StringWriter()); - dirParams.fmt.doFormatString(frmt, nrw, dirParams.tParams, false); + dirParams.fmt.doFormatString(condBody, nrw, dirParams.tParams, false); String strang = nrw.toString(); - if (dirParams.mods.colonMod && dirParams.mods.atMod) { + if (mods.colonMod && mods.atMod) { strang = strang.toUpperCase(); - } else if (dirParams.mods.colonMod) { + } else if (mods.colonMod) { Matcher mat = wordPattern.matcher(strang); StringBuffer sb = new StringBuffer(); @@ -84,7 +78,7 @@ public class CaseDirective implements Directive { mat.appendTail(sb); strang = sb.toString(); - } else if (dirParams.mods.atMod) { + } else if (mods.atMod) { Matcher mat = wordPattern.matcher(strang); StringBuffer sb = new StringBuffer(); diff --git a/clformat/src/main/java/bjc/utils/ioutils/format/directives/CharacterDirective.java b/clformat/src/main/java/bjc/utils/ioutils/format/directives/CharacterDirective.java index d9ea3da..025e6e6 100644 --- a/clformat/src/main/java/bjc/utils/ioutils/format/directives/CharacterDirective.java +++ b/clformat/src/main/java/bjc/utils/ioutils/format/directives/CharacterDirective.java @@ -24,7 +24,7 @@ public class CharacterDirective implements Directive { char ch = (Character) dirParams.item; int codepoint = ch; - if (dirParams.mods.colonMod) { + if (dirParams.getMods().colonMod) { /* * Colon mod means print Unicode character name. */ diff --git a/clformat/src/main/java/bjc/utils/ioutils/format/directives/ConditionalDirective.java b/clformat/src/main/java/bjc/utils/ioutils/format/directives/ConditionalDirective.java index d4f9484..0a400e9 100644 --- a/clformat/src/main/java/bjc/utils/ioutils/format/directives/ConditionalDirective.java +++ b/clformat/src/main/java/bjc/utils/ioutils/format/directives/ConditionalDirective.java @@ -1,14 +1,10 @@ package bjc.utils.ioutils.format.directives; -import java.io.IOException; -import java.util.ArrayList; -import java.util.IllegalFormatConversionException; -import java.util.Iterator; -import java.util.List; -import java.util.regex.Matcher; +import java.io.*; +import java.util.*; +import java.util.regex.*; -import bjc.utils.ioutils.format.CLPattern; -import bjc.utils.ioutils.format.EscapeException; +import bjc.utils.ioutils.format.*; /** * Implements the [ directive. @@ -19,46 +15,45 @@ import bjc.utils.ioutils.format.EscapeException; public class ConditionalDirective implements Directive { @Override public void format(FormatParameters dirParams) throws IOException { - StringBuilder condBody = new StringBuilder(); + CLModifiers mods = dirParams.getMods(); + CLParameters params = dirParams.getParams(); - List<String> clauses = new ArrayList<>(); + List<Decree> condBody = new ArrayList<>(); - String defClause = null; + List<List<Decree>> clauses = new ArrayList<>(); + + List<Decree> defClause = null; boolean isDefault = false; int nestLevel = 1; - Iterator<String> dirIter = dirParams.dirIter; + Iterator<Decree> dirIter = dirParams.dirIter; while (dirIter.hasNext()) { - String direc = dirIter.next(); - if (!direc.startsWith("~")) { - condBody.append(direc); + Decree decr = dirIter.next(); + if (decr.isLiteral) { + condBody.add(decr); continue; } - Matcher dirMat = CLPattern.getDirectiveMatcher(direc); - dirMat.find(); - /* Process a list of clauses. */ - String dirName = dirMat.group("name"); - String dirMods = dirMat.group("modifiers"); - + String dirName = decr.name; if (dirName != null) { if (dirName.equals("[")) { if (nestLevel > 0) { - condBody.append(dirMat.group()); + condBody.add(decr); } nestLevel += 1; } else if (Directive.isOpening(dirName)) { nestLevel += 1; - condBody.append(dirMat.group()); + condBody.add(decr); } else if (dirName.equals("]")) { nestLevel = Math.max(0, nestLevel - 1); if (nestLevel == 0) { /* End the conditional. */ - String clause = condBody.toString(); - condBody = new StringBuilder(); + List<Decree> clause = condBody; + + condBody = new ArrayList<>(); if (isDefault) { defClause = clause; @@ -68,17 +63,18 @@ public class ConditionalDirective implements Directive { break; } else { /* Not a special directive. */ - condBody.append(dirMat.group()); + condBody.add(decr); } } else if (Directive.isClosing(dirName)) { nestLevel = Math.max(0, nestLevel - 1); - condBody.append(dirMat.group()); + condBody.add(decr); } else if (dirName.equals(";")) { if (nestLevel == 1) { /* End the clause. */ - String clause = condBody.toString(); - condBody = new StringBuilder(); + List<Decree> clause = condBody; + + condBody = new ArrayList<>(); if (isDefault) { defClause = clause; @@ -88,24 +84,24 @@ public class ConditionalDirective implements Directive { /* * Mark the next clause as the default. */ - if (dirMods.contains(":")) { + if (decr.modifiers.colonMod) { isDefault = true; } } else { /* Not a special directive. */ - condBody.append(dirMat.group()); + condBody.add(decr); } } else { /* Not a special directive. */ - condBody.append(dirMat.group()); + condBody.add(decr); } } } - if (dirParams.mods.starMod && clauses.size() > 0) defClause = clauses.get(0); + if (mods.starMod && clauses.size() > 0) defClause = clauses.get(0); try { - if (dirParams.mods.colonMod) { + if (mods.colonMod) { dirParams.tParams.right(); boolean res = false; @@ -117,14 +113,14 @@ public class ConditionalDirective implements Directive { res = (Boolean) dirParams.item; } - String frmt; + List<Decree> frmt; if (res) frmt = clauses.get(1); else frmt = clauses.get(0); dirParams.fmt.doFormatString(frmt, dirParams.rw, dirParams.tParams, false); - } else if (dirParams.mods.atMod) { + } else if (mods.atMod) { boolean res = false; if (dirParams.item == null) { // throw new IllegalArgumentException("No parameter provided for [ directive."); @@ -143,10 +139,10 @@ public class ConditionalDirective implements Directive { } } else { int res; - if (dirParams.arrParams.length() >= 1) { - dirParams.arrParams.mapIndices("choice"); + if (params.length() >= 1) { + params.mapIndices("choice"); - res = dirParams.arrParams.getInt(dirParams.tParams, + res = params.getInt(dirParams.tParams, "choice", "conditional choice", "[", 0); } else { if (dirParams.item == null) { @@ -159,7 +155,7 @@ public class ConditionalDirective implements Directive { dirParams.tParams.right(); } - if (dirParams.mods.dollarMod) res -= 1; + if (mods.dollarMod) res -= 1; // System.err.printf("Attempting selection of clause %d of %d (%s) (default %s)\n", // res, clauses.size(), clauses, defClause); @@ -172,7 +168,7 @@ public class ConditionalDirective implements Directive { if (defClause != null) dirParams.fmt.doFormatString(defClause, dirParams.rw, dirParams.tParams, false); } else { - String frmt = clauses.get(res); + List<Decree> frmt = clauses.get(res); // System.out.printf("Selecting clause %d of %d (params %s): %s\n", res, clauses.size(), formatParams, frmt); dirParams.fmt.doFormatString(frmt, dirParams.rw, dirParams.tParams, false); diff --git a/clformat/src/main/java/bjc/utils/ioutils/format/directives/EscapeDirective.java b/clformat/src/main/java/bjc/utils/ioutils/format/directives/EscapeDirective.java index 0820c16..f20f976 100644 --- a/clformat/src/main/java/bjc/utils/ioutils/format/directives/EscapeDirective.java +++ b/clformat/src/main/java/bjc/utils/ioutils/format/directives/EscapeDirective.java @@ -13,12 +13,13 @@ public class EscapeDirective implements Directive { @Override public void format(FormatParameters dirParams) { Tape<Object> itemTape = dirParams.tParams; + CLModifiers mods = dirParams.getMods(); boolean shouldExit; - if (dirParams.mods.dollarMod) dirParams.tParams.right(); + if (mods.dollarMod) dirParams.tParams.right(); - CLParameters params = dirParams.arrParams; + CLParameters params = dirParams.getParams(); switch(params.length()) { case 0: shouldExit = dirParams.tParams.atEnd(); @@ -51,12 +52,12 @@ public class EscapeDirective implements Directive { } } - if (dirParams.mods.dollarMod) dirParams.tParams.left(); + if (mods.dollarMod) dirParams.tParams.left(); /* At negates it. */ - if(dirParams.mods.atMod) shouldExit = !shouldExit; + if(mods.atMod) shouldExit = !shouldExit; - if(shouldExit) throw new EscapeException(dirParams.mods.colonMod); + if(shouldExit) throw new EscapeException(mods.colonMod); } } diff --git a/clformat/src/main/java/bjc/utils/ioutils/format/directives/FormatParameters.java b/clformat/src/main/java/bjc/utils/ioutils/format/directives/FormatParameters.java index c5f3331..b641cde 100644 --- a/clformat/src/main/java/bjc/utils/ioutils/format/directives/FormatParameters.java +++ b/clformat/src/main/java/bjc/utils/ioutils/format/directives/FormatParameters.java @@ -1,30 +1,44 @@ package bjc.utils.ioutils.format.directives; -import java.util.Iterator; +import java.util.*; -import bjc.utils.esodata.Tape; -import bjc.utils.ioutils.ReportWriter; -import bjc.utils.ioutils.format.CLFormatter; -import bjc.utils.ioutils.format.CLModifiers; -import bjc.utils.ioutils.format.CLParameters; +import bjc.utils.esodata.*; +import bjc.utils.ioutils.*; +import bjc.utils.ioutils.format.*; public class FormatParameters { - public ReportWriter rw; - public Object item; - public CLModifiers mods; - public CLParameters arrParams; - public Tape<Object> tParams; - public Iterator<String> dirIter; - public CLFormatter fmt; - - public FormatParameters(ReportWriter rw, Object item, CLModifiers mods, CLParameters arrParams, - Tape<Object> tParams, Iterator<String> dirIter, CLFormatter fmt) { - this.rw = rw; - this.item = item; - this.mods = mods; - this.arrParams = arrParams; - this.tParams = tParams; - this.dirIter = dirIter; - this.fmt = fmt; + public ReportWriter rw; + + public Object item; + + public Decree decr; + + public Tape<Object> tParams; + + public Iterator<Decree> dirIter; + + public CLFormatter fmt; + + public FormatParameters(ReportWriter rw, Object item, Decree decr, Tape<Object> tParams, + Iterator<Decree> dirIter, CLFormatter fmt) { + this.rw = rw; + + this.item = item; + + this.decr = decr; + + this.tParams = tParams; + + this.dirIter = dirIter; + + this.fmt = fmt; + } + + public CLParameters getParams() { + return decr.parameters; + } + + public CLModifiers getMods() { + return decr.modifiers; } } diff --git a/clformat/src/main/java/bjc/utils/ioutils/format/directives/FreshlineDirective.java b/clformat/src/main/java/bjc/utils/ioutils/format/directives/FreshlineDirective.java index 3b54a92..ce383ee 100644 --- a/clformat/src/main/java/bjc/utils/ioutils/format/directives/FreshlineDirective.java +++ b/clformat/src/main/java/bjc/utils/ioutils/format/directives/FreshlineDirective.java @@ -2,6 +2,8 @@ package bjc.utils.ioutils.format.directives; import java.io.*; +import bjc.utils.ioutils.format.*; + /** * Implement the & directive. * @author student @@ -13,10 +15,11 @@ public class FreshlineDirective implements Directive { public void format(FormatParameters dirParams) throws IOException { int nTimes = 1; - if(dirParams.arrParams.length() >= 1) { - dirParams.arrParams.mapIndices("count"); - nTimes = dirParams.arrParams.getInt(dirParams.tParams, - "count", "occurance count", "&", 1); + CLParameters params = dirParams.getParams(); + + if(params.length() >= 1) { + params.mapIndices("count"); + nTimes = params.getInt(dirParams.tParams, "count", "occurance count", "&", 1); } if(dirParams.rw.isLastCharNL()) nTimes -= 1; diff --git a/clformat/src/main/java/bjc/utils/ioutils/format/directives/GeneralNumberDirective.java b/clformat/src/main/java/bjc/utils/ioutils/format/directives/GeneralNumberDirective.java index 7f4cd02..990558c 100644 --- a/clformat/src/main/java/bjc/utils/ioutils/format/directives/GeneralNumberDirective.java +++ b/clformat/src/main/java/bjc/utils/ioutils/format/directives/GeneralNumberDirective.java @@ -14,9 +14,12 @@ import bjc.utils.math.*; * */ public abstract class GeneralNumberDirective implements Directive { - protected static void handleNumberDirective(Tape<Object> itemTape, ReportWriter rw, CLModifiers mods, CLParameters params, int argidx, + protected static void handleNumberDirective(Tape<Object> itemTape, ReportWriter rw, Decree decr, int argidx, long val, int radix) throws IOException { + CLParameters params = decr.parameters; + CLModifiers mods = decr.modifiers; + /* * Initialize the two padding related parameters, and then fill them in from the * directive parameters if they are present. diff --git a/clformat/src/main/java/bjc/utils/ioutils/format/directives/GotoDirective.java b/clformat/src/main/java/bjc/utils/ioutils/format/directives/GotoDirective.java index 941b74d..22196fa 100644 --- a/clformat/src/main/java/bjc/utils/ioutils/format/directives/GotoDirective.java +++ b/clformat/src/main/java/bjc/utils/ioutils/format/directives/GotoDirective.java @@ -15,8 +15,10 @@ public class GotoDirective implements Directive { public void format(FormatParameters dirParams) { Tape<Object> itemTape = dirParams.tParams; - CLParameters params = dirParams.arrParams; - if (dirParams.mods.colonMod) { + CLParameters params = dirParams.getParams(); + CLModifiers mods = dirParams.getMods(); + + if (mods.colonMod) { int num = 1; if (params.length() >= 1) { params.mapIndices("numargs"); @@ -25,7 +27,7 @@ public class GotoDirective implements Directive { } dirParams.tParams.left(num); - } else if (dirParams.mods.atMod) { + } else if (mods.atMod) { int num = 0; if (params.length() >= 1) { params.mapIndices("argidx"); diff --git a/clformat/src/main/java/bjc/utils/ioutils/format/directives/IndentDirective.java b/clformat/src/main/java/bjc/utils/ioutils/format/directives/IndentDirective.java index a6354f8..9226761 100644 --- a/clformat/src/main/java/bjc/utils/ioutils/format/directives/IndentDirective.java +++ b/clformat/src/main/java/bjc/utils/ioutils/format/directives/IndentDirective.java @@ -3,6 +3,7 @@ package bjc.utils.ioutils.format.directives; import java.io.*; import bjc.utils.esodata.*; +import bjc.utils.ioutils.format.*; /** * Implement the I directive. @@ -14,17 +15,20 @@ public class IndentDirective implements Directive { public void format(FormatParameters dirParams) throws IOException { Tape<Object> itemTape = dirParams.tParams; + CLModifiers mods = dirParams.getMods(); + CLParameters params = dirParams.getParams(); + // Dollar mod is indent configuration - if (dirParams.mods.dollarMod) { + if (mods.dollarMod) { return; } int nIndents = 1; - if(dirParams.arrParams.length() >= 1) { - dirParams.arrParams.mapIndices("count"); + if(params.length() >= 1) { + params.mapIndices("count"); - nIndents = dirParams.arrParams.getInt(itemTape, "count", "indent count", "I", 1); + nIndents = params.getInt(itemTape, "count", "indent count", "I", 1); } boolean dedent = false; @@ -34,7 +38,7 @@ public class IndentDirective implements Directive { dedent = true; } - if (dirParams.mods.colonMod) { + if (mods.colonMod) { if (dedent) dirParams.rw.dedent(nIndents); else dirParams.rw.indent(nIndents); } else { diff --git a/clformat/src/main/java/bjc/utils/ioutils/format/directives/InflectDirective.java b/clformat/src/main/java/bjc/utils/ioutils/format/directives/InflectDirective.java index 5cbde64..bb099a2 100644 --- a/clformat/src/main/java/bjc/utils/ioutils/format/directives/InflectDirective.java +++ b/clformat/src/main/java/bjc/utils/ioutils/format/directives/InflectDirective.java @@ -1,14 +1,13 @@ package bjc.utils.ioutils.format.directives; -import java.io.IOException; -import java.io.StringWriter; -import java.util.Iterator; -import java.util.regex.Matcher; +import java.io.*; +import java.util.*; +import java.util.regex.*; -import bjc.inflexion.InflectionML; +import bjc.inflexion.*; -import bjc.utils.ioutils.ReportWriter; -import bjc.utils.ioutils.format.CLPattern; +import bjc.utils.ioutils.*; +import bjc.utils.ioutils.format.*; /** * Inflection directive. @@ -18,34 +17,32 @@ import bjc.utils.ioutils.format.CLPattern; public class InflectDirective implements Directive { @Override public void format(FormatParameters dirParams) throws IOException { - StringBuilder condBody = new StringBuilder(); + List<Decree> condBody = new ArrayList<>(); int nestLevel = 1; - Iterator<String> dirIter = dirParams.dirIter; + Iterator<Decree> dirIter = dirParams.dirIter; while (dirIter.hasNext()) { - String direc = dirIter.next(); - if (!direc.startsWith("~")) { - condBody.append(direc); + Decree decr = dirIter.next(); + if (decr.isLiteral) { + condBody.add(decr); + continue; } - Matcher dirMat = CLPattern.getDirectiveMatcher(direc); - - /* Process a list of clauses. */ - String dirName = dirMat.group("name"); + String dirName = decr.name; if (dirName != null) { if (dirName.equals("`[")) { if (nestLevel > 0) { - condBody.append(dirMat.group()); + condBody.add(decr); } nestLevel += 1; } else if (Directive.isOpening(dirName)) { nestLevel += 1; - condBody.append(dirMat.group()); + condBody.add(decr); } else if (dirName.equals("`]")) { nestLevel = Math.max(0, nestLevel - 1); @@ -55,16 +52,14 @@ public class InflectDirective implements Directive { nestLevel = Math.max(0, nestLevel - 1); } else { /* Not a special directive. */ - condBody.append(dirMat.group()); + condBody.add(decr); } } } - String frmt = condBody.toString(); - ReportWriter nrw = dirParams.rw.duplicate(new StringWriter()); - dirParams.fmt.doFormatString(frmt, nrw, dirParams.tParams, false); + dirParams.fmt.doFormatString(condBody.iterator(), nrw, dirParams.tParams, false); String strang = nrw.toString(); diff --git a/clformat/src/main/java/bjc/utils/ioutils/format/directives/IterationDirective.java b/clformat/src/main/java/bjc/utils/ioutils/format/directives/IterationDirective.java index be5d48e..f38a7ed 100644 --- a/clformat/src/main/java/bjc/utils/ioutils/format/directives/IterationDirective.java +++ b/clformat/src/main/java/bjc/utils/ioutils/format/directives/IterationDirective.java @@ -1,12 +1,10 @@ package bjc.utils.ioutils.format.directives; -import java.io.IOException; -import java.util.IllegalFormatConversionException; -import java.util.Iterator; -import java.util.regex.Matcher; +import java.io.*; +import java.util.*; +import java.util.regex.*; -import bjc.utils.esodata.SingleTape; -import bjc.utils.esodata.Tape; +import bjc.utils.esodata.*; import bjc.utils.ioutils.format.*; /** @@ -21,42 +19,41 @@ public class IterationDirective implements Directive { public void format(FormatParameters dirParams) throws IOException { CLFormatter.checkItem(dirParams.item, '{'); - StringBuilder condBody = new StringBuilder(); + List<Decree> condBody = new ArrayList<>(); - Iterator<String> dirIter = dirParams.dirIter; + Iterator<Decree> dirIter = dirParams.dirIter; while (dirIter.hasNext()) { - String direc = dirIter.next(); - if (!direc.startsWith("~")) { - condBody.append(direc); + Decree decr = dirIter.next(); + if (decr.isLiteral) { + condBody.add(decr); continue; } - Matcher dirMat = CLPattern.getDirectiveMatcher(direc); - dirMat.find(); - /* Process a list of clauses. */ - String dirName = dirMat.group("name"); + String dirName = decr.name; if (dirName != null) { if (dirName.equals("}")) { break; } else { /* Not a special directive. */ - condBody.append(dirMat.group()); + condBody.add(decr); } } } - String frmt = condBody.toString(); Object iter = dirParams.item; - // System.err.printf("Iteration format \"%s\" (iter %s)\n", frmt, item); - if (frmt.equals("")) { + boolean usingString = false; + String strang = ""; + + if (condBody.size() == 0) { /* Grab an argument. */ if (!(dirParams.item instanceof String)) { throw new IllegalFormatConversionException('{', String.class); } - frmt = (String) dirParams.item; + usingString = true; + strang = (String) dirParams.item; if (!dirParams.tParams.right()) { throw new IllegalArgumentException("Not enough parameters to '{' directive"); @@ -67,7 +64,9 @@ public class IterationDirective implements Directive { int maxItr = Integer.MAX_VALUE; - CLParameters params = dirParams.arrParams; + CLParameters params = dirParams.getParams(); + CLModifiers mods = dirParams.getMods(); + if (params.length() > 0) { params.mapIndices("maxitr"); @@ -77,7 +76,7 @@ public class IterationDirective implements Directive { int numItr = 0; - if (dirParams.mods.atMod && dirParams.mods.colonMod) { + if (mods.atMod &&mods.colonMod) { try { do { if (numItr > maxItr) break; @@ -92,7 +91,11 @@ public class IterationDirective implements Directive { Tape<Object> nParams = new SingleTape<>(nitr); try { - dirParams.fmt.doFormatString(frmt, dirParams.rw, nParams, false); + if (usingString) { + dirParams.fmt.doFormatString(strang, dirParams.rw, nParams, false); + } else { + dirParams.fmt.doFormatString(condBody, dirParams.rw, nParams, false); + } } catch (EscapeException eex) { if (eex.endIteration) { if (dirParams.tParams.atEnd()) { @@ -107,20 +110,24 @@ public class IterationDirective implements Directive { } catch (EscapeException eex) { // Do nothing } - } else if (dirParams.mods.atMod) { + } else if (mods.atMod) { try { while (!dirParams.tParams.atEnd()) { // System.err.printf("Iterating with format \"%s\"\n", frmt); if (numItr > maxItr) break; numItr += 1; - dirParams.fmt.doFormatString(frmt, dirParams.rw, dirParams.tParams, false); + if (usingString) { + dirParams.fmt.doFormatString(strang, dirParams.rw, dirParams.tParams, false); + } else { + dirParams.fmt.doFormatString(condBody, dirParams.rw, dirParams.tParams, false); + } } } catch (EscapeException eex) { if (eex.endIteration) throw new UnsupportedOperationException("Colon mod not allowed on escape marker without colon mod on iteration"); } - } else if (dirParams.mods.colonMod) { + } else if (mods.colonMod) { if (!(dirParams.item instanceof Iterable<?>)) { throw new IllegalFormatConversionException('{', dirParams.item.getClass()); } @@ -144,7 +151,11 @@ public class IterationDirective implements Directive { Tape<Object> nParams = new SingleTape<>(nitr); try { - dirParams.fmt.doFormatString(frmt, dirParams.rw, nParams, false); + if (usingString) { + dirParams.fmt.doFormatString(strang, dirParams.rw, nParams, false); + } else { + dirParams.fmt.doFormatString(condBody, dirParams.rw, nParams, false); + } } catch (EscapeException eex) { if(eex.endIteration && !itr.hasNext()) throw eex; } @@ -166,7 +177,11 @@ public class IterationDirective implements Directive { if (numItr > maxItr) break; numItr += 1; - dirParams.fmt.doFormatString(frmt, dirParams.rw, nParams, false); + if (usingString) { + dirParams.fmt.doFormatString(strang, dirParams.rw, nParams, false); + } else { + dirParams.fmt.doFormatString(condBody, dirParams.rw, nParams, false); + } } } catch (EscapeException eex) { if (eex.endIteration) diff --git a/clformat/src/main/java/bjc/utils/ioutils/format/directives/LiteralDirective.java b/clformat/src/main/java/bjc/utils/ioutils/format/directives/LiteralDirective.java index e603305..7a53d90 100644 --- a/clformat/src/main/java/bjc/utils/ioutils/format/directives/LiteralDirective.java +++ b/clformat/src/main/java/bjc/utils/ioutils/format/directives/LiteralDirective.java @@ -1,6 +1,8 @@ package bjc.utils.ioutils.format.directives; -import java.io.IOException; +import java.io.*; + +import bjc.utils.ioutils.format.*; /** * Implements directives that create a literal string. @@ -29,10 +31,12 @@ public class LiteralDirective implements Directive { public void format(FormatParameters dirParams) throws IOException { int nTimes = 1; - if (dirParams.arrParams.length() >= 1) { - dirParams.arrParams.mapIndices("count"); + CLParameters params = dirParams.getParams(); + + if (params.length() >= 1) { + params.mapIndices("count"); - nTimes = dirParams.arrParams.getInt(dirParams.tParams, "count", "occurance count", directive, 1); + nTimes = params.getInt(dirParams.tParams, "count", "occurance count", directive, 1); } for (int i = 0; i < nTimes; i++) { diff --git a/clformat/src/main/java/bjc/utils/ioutils/format/directives/NumberDirective.java b/clformat/src/main/java/bjc/utils/ioutils/format/directives/NumberDirective.java index 68b5873..09acdd5 100644 --- a/clformat/src/main/java/bjc/utils/ioutils/format/directives/NumberDirective.java +++ b/clformat/src/main/java/bjc/utils/ioutils/format/directives/NumberDirective.java @@ -42,8 +42,7 @@ public class NumberDirective extends GeneralNumberDirective { long val = ((Number) dirParams.item).longValue(); - handleNumberDirective(dirParams.tParams, dirParams.rw, - dirParams.mods, dirParams.arrParams, argidx, val, radix); + handleNumberDirective(dirParams.tParams, dirParams.rw, dirParams.decr, argidx, val, radix); dirParams.tParams.right(); } diff --git a/clformat/src/main/java/bjc/utils/ioutils/format/directives/RadixDirective.java b/clformat/src/main/java/bjc/utils/ioutils/format/directives/RadixDirective.java index 87fba8e..d3b662a 100644 --- a/clformat/src/main/java/bjc/utils/ioutils/format/directives/RadixDirective.java +++ b/clformat/src/main/java/bjc/utils/ioutils/format/directives/RadixDirective.java @@ -1,11 +1,10 @@ package bjc.utils.ioutils.format.directives; -import java.io.IOException; -import java.util.IllegalFormatConversionException; +import java.io.*; +import java.util.*; -import bjc.utils.ioutils.format.CLFormatter; -import bjc.utils.ioutils.format.CLParameters; -import bjc.utils.math.NumberUtils; +import bjc.utils.ioutils.format.*; +import bjc.utils.math.*; /** * Generalized radix directive. @@ -28,11 +27,13 @@ public class RadixDirective extends GeneralNumberDirective { */ long val = ((Number) dirParams.item).longValue(); - CLParameters params = dirParams.arrParams; + CLParameters params = dirParams.getParams(); + CLModifiers mods = dirParams.getMods(); + if (params.length() == 0) { - if (dirParams.mods.atMod) { - dirParams.rw.write(NumberUtils.toRoman(val, dirParams.mods.colonMod)); - } else if (dirParams.mods.colonMod) { + if (mods.atMod) { + dirParams.rw.write(NumberUtils.toRoman(val,mods.colonMod)); + } else if (mods.colonMod) { dirParams.rw.write(NumberUtils.toOrdinal(val)); } else { dirParams.rw.write(NumberUtils.toCardinal(val)); @@ -46,7 +47,7 @@ public class RadixDirective extends GeneralNumberDirective { int radix = params.getInt(dirParams.tParams, "radix", "radix", "R", 10); handleNumberDirective(dirParams.tParams, dirParams.rw, - dirParams.mods, params, 0, val, radix); + dirParams.decr, 0, val, radix); } dirParams.tParams.right(); diff --git a/clformat/src/main/java/bjc/utils/ioutils/format/directives/RecursiveDirective.java b/clformat/src/main/java/bjc/utils/ioutils/format/directives/RecursiveDirective.java index c0c752c..08d5e3f 100644 --- a/clformat/src/main/java/bjc/utils/ioutils/format/directives/RecursiveDirective.java +++ b/clformat/src/main/java/bjc/utils/ioutils/format/directives/RecursiveDirective.java @@ -1,12 +1,10 @@ package bjc.utils.ioutils.format.directives; -import java.io.IOException; -import java.util.IllegalFormatConversionException; +import java.io.*; +import java.util.*; -import bjc.utils.esodata.SingleTape; -import bjc.utils.esodata.Tape; -import bjc.utils.ioutils.format.CLFormatter; -import bjc.utils.ioutils.format.EscapeException; +import bjc.utils.esodata.*; +import bjc.utils.ioutils.format.*; public class RecursiveDirective implements Directive { public void format(FormatParameters dirParams) throws IOException { @@ -14,7 +12,9 @@ public class RecursiveDirective implements Directive { CLFormatter.checkItem(dirParams.item, '?'); - if (dirParams.mods.atMod) { + CLModifiers mods = dirParams.getMods(); + + if (mods.atMod) { if (!(dirParams.item instanceof String)) throw new IllegalFormatConversionException('?', dirParams.item.getClass()); @@ -22,7 +22,7 @@ public class RecursiveDirective implements Directive { dirParams.fmt.doFormatString((String)dirParams.item, dirParams.rw, dirParams.tParams, true); } catch (EscapeException eex) { if (eex.endIteration) - throw new UnsupportedOperationException("Colon mod not allowed on escape marker without colon mod on iteration"); + throw new UnsupportedOperationException("Colon mod not allowed on escape marker outside of iteration"); } } else { if (dirParams.tParams.atEnd()) @@ -41,7 +41,7 @@ public class RecursiveDirective implements Directive { try { dirParams.fmt.doFormatString((String)dirParams.item, dirParams.rw, newParams, true); } catch (EscapeException eex) { - throw new UnsupportedOperationException("Colon mod not allowed on escape marker without colon mod on iteration"); + throw new UnsupportedOperationException("Colon mod not allowed on escape marker outside of iteration"); } } } diff --git a/clformat/src/main/java/bjc/utils/ioutils/format/directives/TabulateDirective.java b/clformat/src/main/java/bjc/utils/ioutils/format/directives/TabulateDirective.java index a06e585..af8bff0 100644 --- a/clformat/src/main/java/bjc/utils/ioutils/format/directives/TabulateDirective.java +++ b/clformat/src/main/java/bjc/utils/ioutils/format/directives/TabulateDirective.java @@ -8,18 +8,19 @@ import bjc.utils.ioutils.format.*; public class TabulateDirective implements Directive { public void format(FormatParameters dirParams) throws IOException { Tape<Object> itemTape = dirParams.tParams; + CLModifiers mods = dirParams.getMods(); // Support for a possible future feature char padchar = ' '; int currCol = dirParams.rw.getLinePos(); - if (dirParams.mods.colonMod) { + if (mods.colonMod) { currCol = dirParams.rw.getIndentPos(); } - CLParameters params = dirParams.arrParams; - if (dirParams.mods.atMod) { + CLParameters params = dirParams.getParams(); + if (mods.atMod) { int colrel = 1, colinc = 1; if (params.length() > 2) { diff --git a/clformat/src/test/java/bjc/utils/test/ioutils/CLTokenizerTest.java b/clformat/src/test/java/bjc/utils/test/ioutils/CLTokenizerTest.java deleted file mode 100644 index a66ffe1..0000000 --- a/clformat/src/test/java/bjc/utils/test/ioutils/CLTokenizerTest.java +++ /dev/null @@ -1,47 +0,0 @@ -package bjc.utils.test.ioutils; - -import java.io.IOException; -import java.util.Iterator; - -import org.junit.Test; - -import bjc.utils.ioutils.format.CLTokenizer; - -// Static imports - -import static java.util.Arrays.asList; - -import static org.junit.Assert.assertEquals; - -/** - * Tests for CL format strings. - * - * @author EVE - * - */ -@SuppressWarnings("javadoc") -public class CLTokenizerTest { - @Test - public void testTokenizer() { - assertIteratorEquals(tokenize(""), ""); - assertIteratorEquals(tokenize("hello"), "hello"); - assertIteratorEquals(tokenize("hello olleh"), "hello olleh"); - assertIteratorEquals(tokenize("A ~A"), "A ", "~A"); - - assertIteratorEquals(tokenize("~3,'0D"), "~3,'0D"); - assertIteratorEquals(tokenize("~,,'|,2:D"), "~,,'|,2:D"); - assertIteratorEquals(tokenize("~3,,,' ,2:R"), "~3,,,' ,2:R"); - - assertIteratorEquals(tokenize("~@[print level = ~D~]~@[print length = ~D~]"), "~@[", "print level = ", "~D", "~]", "~@[", "print length = ", "~D", "~]"); - } - - private static Iterator<String> tokenize(String inp) { - return new CLTokenizer(inp); - } - - private static <T> void assertIteratorEquals(Iterator<T> src, T... vals) { - for (T val : vals) { - assertEquals(val, src.next()); - } - } -} |
