From 37df91c753caf9937aac9b0d45a964c22aec28b8 Mon Sep 17 00:00:00 2001 From: "Benjamin J. Culkin" Date: Wed, 14 Aug 2019 22:58:10 -0300 Subject: Implement compilation of RecursionDirective --- .../format/directives/RecursiveDirective.java | 75 ++++++++++++++++++++++ .../format/exceptions/MismatchedFormatArgType.java | 34 ++++++++++ .../format/exceptions/UnexpectedColonEscape.java | 13 ++++ .../bjc/utils/test/ioutils/CLFormatterTest.java | 4 +- 4 files changed, 125 insertions(+), 1 deletion(-) create mode 100644 clformat/src/main/java/bjc/utils/ioutils/format/exceptions/MismatchedFormatArgType.java create mode 100644 clformat/src/main/java/bjc/utils/ioutils/format/exceptions/UnexpectedColonEscape.java (limited to 'clformat/src') 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 08d5e3f..222ee87 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 @@ -5,9 +5,16 @@ import java.util.*; import bjc.utils.esodata.*; import bjc.utils.ioutils.format.*; +import bjc.utils.ioutils.format.exceptions.*; public class RecursiveDirective implements Directive { public void format(FormatParameters dirParams) throws IOException { + Edict edt = compile(dirParams.toCompileCTX()); + + edt.format(dirParams.toFormatCTX()); + } + + public void formatF(FormatParameters dirParams) throws IOException { dirParams.tParams.right(); CLFormatter.checkItem(dirParams.item, '?'); @@ -45,4 +52,72 @@ public class RecursiveDirective implements Directive { } } } + + @Override + public Edict compile(CompileContext compCTX) { + return new RecursiveEdict(compCTX.decr.modifiers.atMod, compCTX.formatter); + } +} + +class RecursiveEdict implements Edict { + private boolean isInline; + + private CLFormatter fmt; + + public RecursiveEdict(boolean isInline, CLFormatter fmt) { + this.isInline = isInline; + + this.fmt = fmt; + } + + @Override + public void format(FormatContext formCTX) throws IOException { + // System.err.printf("[TRACE] Processing ? directive with params: " + formCTX.items.toString()); + Object body = formCTX.items.item(); + + formCTX.items.right(); + + if (isInline) { + if (!(body instanceof String)) { + throw new MismatchedFormatArgType("?", String.class, body.getClass()); + } + + try { + String bod = (String)body; + + fmt.doFormatString(bod, formCTX.writer, formCTX.items, true); + } catch (EscapeException eex) { + if (eex.endIteration) { + throw new UnexpectedColonEscape(); + } + } + } else { + if (formCTX.items.atEnd()) { + throw new IllegalArgumentException("? directive requires two format parameters"); + } + + Object o = formCTX.items.item(); + formCTX.items.right(); + + if (!(o instanceof Iterable)) { + throw new MismatchedFormatArgType("?", Iterable.class, o.getClass()); + } + + if (!(body instanceof String)) { + throw new MismatchedFormatArgType("?", String.class, body.getClass()); + } + + @SuppressWarnings("unchecked") + Iterable itb = (Iterable)o; + Tape newParams = new SingleTape<>(itb); + + try { + String bod = (String)body; + + fmt.doFormatString(bod, formCTX.writer, newParams, true); + } catch (EscapeException eex) { + throw new UnexpectedColonEscape(); + } + } + } } diff --git a/clformat/src/main/java/bjc/utils/ioutils/format/exceptions/MismatchedFormatArgType.java b/clformat/src/main/java/bjc/utils/ioutils/format/exceptions/MismatchedFormatArgType.java new file mode 100644 index 0000000..7ac9e9d --- /dev/null +++ b/clformat/src/main/java/bjc/utils/ioutils/format/exceptions/MismatchedFormatArgType.java @@ -0,0 +1,34 @@ +package bjc.utils.ioutils.format.exceptions; + +/** + * Exception thrown when a provided format argument was not of the correct type. + * + * @author Ben Culkin + */ +public class MismatchedFormatArgType extends RuntimeException { + /** + * Create a new format arg mismatch with a given message. + * + * @param msg + * The message for the exception. + */ + public MismatchedFormatArgType(String msg) { + super(msg); + } + + /** + * Create a new standard format arg mismatch. + * + * @param dir + * The directive this argument was for. + * + * @param expected + * The class we expected to get. + * + * @param got + * The class we actually got. + */ + public MismatchedFormatArgType(String dir, Class expected, Class got) { + this(String.format("Bad format argument to %s directive: got %s, expected %s", dir, got.getName(), expected.getName())); + } +} diff --git a/clformat/src/main/java/bjc/utils/ioutils/format/exceptions/UnexpectedColonEscape.java b/clformat/src/main/java/bjc/utils/ioutils/format/exceptions/UnexpectedColonEscape.java new file mode 100644 index 0000000..260e503 --- /dev/null +++ b/clformat/src/main/java/bjc/utils/ioutils/format/exceptions/UnexpectedColonEscape.java @@ -0,0 +1,13 @@ +package bjc.utils.ioutils.format.exceptions; + +/** + * Exception thrown when the colon modifier is used on the escape directive when + * it shouldn't have been. + * + * @author Ben Culkin + */ +public class UnexpectedColonEscape extends RuntimeException { + public UnexpectedColonEscape() { + super("Colon mod not allowed on escape marker in this context"); + } +} diff --git a/clformat/src/test/java/bjc/utils/test/ioutils/CLFormatterTest.java b/clformat/src/test/java/bjc/utils/test/ioutils/CLFormatterTest.java index e7ee64c..2ceab42 100644 --- a/clformat/src/test/java/bjc/utils/test/ioutils/CLFormatterTest.java +++ b/clformat/src/test/java/bjc/utils/test/ioutils/CLFormatterTest.java @@ -142,7 +142,9 @@ public class CLFormatterTest { private String format(String str, Object... params) { try { return fmt.formatString(str, params); - } catch (IOException ioex) { + } catch (Exception ex) { + ex.printStackTrace(); + return null; } } -- cgit v1.2.3