summaryrefslogtreecommitdiff
path: root/clformat/src/main/java/bjc/utils/ioutils/format/directives/RecursiveDirective.java
blob: c60d0bb22d8df9c2376918ebdfe4c43e6767ac49 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
package bjc.utils.ioutils.format.directives;

import java.io.*;
import bjc.esodata.*;
import bjc.utils.ioutils.format.*;
import bjc.utils.ioutils.format.exceptions.*;

/**
 * Implementation of the ? directive, which does recursive execution of a format
 * string.
 *
 * @author bjculkin
 *
 */
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 (DirectiveEscape eex) {
				if (eex.endIteration) throw new UnexpectedColonEscape();
			}
		} else {
			if (formCTX.items.atEnd()) {
				throw new IllegalArgumentException(
						"? directive requires two format parameters");
			}

			Object item = formCTX.items.item();
			formCTX.items.right();

			if (!(item instanceof Iterable<?>)) {
				throw new MismatchedFormatArgType("?", Iterable.class, item.getClass());
			}

			if (!(body instanceof String)) {
				throw new MismatchedFormatArgType("?", String.class, body.getClass());
			}

			@SuppressWarnings("unchecked")
			Iterable<Object> itb = (Iterable<Object>) item;
			Tape<Object> newParams = new SingleTape<>(itb);

			try {
				String bod = (String) body;

				// :DynamicString
				fmt.doFormatString(bod, formCTX.writer, newParams, true);
			} catch (DirectiveEscape eex) {
				throw new UnexpectedColonEscape();
			}
		}
	}
}