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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
|
package org.zwobble.couscous.backends;
import com.google.common.base.Strings;
import org.zwobble.couscous.util.Action;
import java.util.Iterator;
import java.util.function.Consumer;
public class SourceCodeWriter {
public interface WriterAction {
void run(SourceCodeWriter writer);
}
private static final int SPACES_PER_INDENT = 4;
private final StringBuilder builder = new StringBuilder();
private final WriterAction blockStart;
private final WriterAction blockEnd;
private int depth = 0;
public SourceCodeWriter(WriterAction blockStart, WriterAction blockEnd) {
this.blockStart = blockStart;
this.blockEnd = blockEnd;
}
public String asString() {
return builder.toString();
}
public void writeInteger(int value) {
builder.append(value);
}
public void writeStringLiteral(String value) {
builder.append("\"");
builder.append(value
.replace("\\", "\\\\")
.replace("\"", "\\\"")
.replace("\n", "\\n")
.replace("\r", "\\r")
.replace("\t", "\\t"));
builder.append("\"");
}
public void writeKeyword(String keyword) {
builder.append(keyword);
}
public void writeSpace() {
builder.append(" ");
}
public void writeIdentifier(String name) {
builder.append(name);
}
public void writeSymbol(String symbol) {
builder.append(symbol);
}
public void startBlock() {
runAction(blockStart);
depth++;
builder.append("\n");
}
public void endBlock() {
depth--;
runAction(blockEnd);
}
public void writeStatement(Action action) {
startStatement();
action.run();
endStatement();
}
private void startStatement() {
writeIndentation();
}
public void writeIndentation() {
builder.append(Strings.repeat(" ", depth * SPACES_PER_INDENT));
}
private void endStatement() {
if (builder.charAt(builder.length() - 1) != '\n') {
builder.append("\n");
}
}
private void runAction(WriterAction action) {
action.run(this);
}
public <T> void writeCommaSeparated(Iterable<T> values, Consumer<T> writeValue) {
writeWithSeparator(values, writeValue, () -> {
writeSymbol(",");
writeSpace();
});
}
public <T> void writeWithSeparator(Iterable<T> values, Consumer<T> writeValue, Action separator) {
Iterator<T> iterator = values.iterator();
if (iterator.hasNext()) {
writeValue.accept(iterator.next());
while(iterator.hasNext()) {
separator.run();
writeValue.accept(iterator.next());
}
}
}
}
|