1 package net.sourceforge.jenesis4java.impl;
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 import net.sourceforge.jenesis4java.*;
41 import net.sourceforge.jenesis4java.impl.util.VisitorUtils;
42
43 import java.util.*;
44
45 import static java.lang.String.format;
46
47
48
49
50 public abstract class MLiteral extends MVM.MCodeable implements Literal {
51
52
53
54
55 static class MBooleanLiteral extends MLiteral implements BooleanLiteral {
56
57 MBooleanLiteral(MVM vm, boolean val) {
58 super(vm, vm.BOOLEAN, val, val ? "true" : "false");
59 }
60
61 @Override
62 public boolean toBoolean() {
63 return (Boolean) val;
64 }
65 }
66
67
68
69
70 static class MByteLiteral extends MLiteral implements ByteLiteral {
71
72 MByteLiteral(MVM vm, byte val) {
73 super(vm, vm.BYTE, val, "(byte) " + val);
74 }
75
76 @Override
77 public byte toByte() {
78 return (Byte) val;
79 }
80 }
81
82
83
84
85 static class MCharLiteral extends MLiteral implements CharLiteral {
86
87
88
89
90
91 private static final Set<Character> CONTROL_CODES;
92
93
94
95
96 private static final Map<Character, String> SPECIAL_ENCODINGS;
97
98 MCharLiteral(MVM vm, char val) {
99 super(vm, vm.CHAR, val, escapedValue(val));
100 }
101
102 private static String escapedValue(char val) {
103 StringBuilder b = new StringBuilder();
104 b.append("'");
105 escape(val, b, false);
106 b.append("'");
107 return b.toString();
108 }
109
110 static {
111 CONTROL_CODES = new HashSet<>();
112 CONTROL_CODES.addAll(Arrays.asList(
113 '\u0001', '\u0002', '\u0003', '\u0004', '\u0005', '\u0006',
114 '\u0007', '\u000B', '\u000E', '\u000F', '\u0010', '\u0011',
115 '\u0012', '\u0013', '\u0014', '\u0015', '\u0016', '\u0017',
116 '\u0018', '\u0019', '\u001A', '\u001B', '\u001C', '\u001D',
117 '\u001E', '\u001F'));
118
119 SPECIAL_ENCODINGS = new HashMap<>();
120 SPECIAL_ENCODINGS.put('\0', "\\0");
121 SPECIAL_ENCODINGS.put('\b', "\\b");
122 SPECIAL_ENCODINGS.put('\t', "\\t");
123 SPECIAL_ENCODINGS.put('\n', "\\n");
124 SPECIAL_ENCODINGS.put('\f', "\\f");
125 SPECIAL_ENCODINGS.put('\r', "\\r");
126 SPECIAL_ENCODINGS.put('\\', "\\\\");
127 }
128
129 static void escape(char c, StringBuilder b, boolean escapeForString) {
130
131
132 if (c == '"' && escapeForString
133 || c == '\'' && !escapeForString) {
134 b.append("\\");
135 b.append(c);
136
137 } else if (CONTROL_CODES.contains(c)) {
138 String charString = Integer.toHexString(c);
139 b.append("\\u");
140 b.append("0000".substring(charString.length()));
141 b.append(charString);
142
143 } else if (SPECIAL_ENCODINGS.containsKey(c)) {
144 b.append(SPECIAL_ENCODINGS.get(c));
145
146 } else {
147 b.append(c);
148 }
149 }
150
151 @Override
152 public char toChar() {
153 return (Character) val;
154 }
155 }
156
157
158
159
160 static class MClassLiteral extends MLiteral implements ClassLiteral {
161
162 MClassLiteral(MVM vm, ClassType val) {
163 super(vm, val, val, val.toString() + ".class");
164 }
165
166 }
167
168
169
170
171 static class MDoubleLiteral extends MLiteral implements DoubleLiteral {
172
173 MDoubleLiteral(MVM vm, double val) {
174 super(vm, vm.DOUBLE, val, Double.toString(val) + "D");
175 }
176
177 @Override
178 public double toDouble() {
179 return (Double) val;
180 }
181 }
182
183
184
185
186 static class MFalse extends MBooleanLiteral implements False {
187
188 MFalse(MVM vm) {
189 super(vm, false);
190 }
191 }
192
193
194
195
196 static class MFloatLiteral extends MLiteral implements FloatLiteral {
197
198 MFloatLiteral(MVM vm, float val) {
199 super(vm, vm.FLOAT, val, Float.toString(val) + "F");
200 }
201
202 @Override
203 public float toFloat() {
204 return (Float) val;
205 }
206 }
207
208
209
210
211 static class MIntLiteral extends MLiteral implements IntLiteral {
212
213 MIntLiteral(MVM vm, int val) {
214 super(vm, vm.INT, val, Integer.toString(val));
215 }
216
217 @Override
218 public int toInt() {
219 return (Integer) val;
220 }
221 }
222
223
224
225
226 static class MLongLiteral extends MLiteral implements LongLiteral {
227
228 MLongLiteral(MVM vm, long val) {
229 super(vm, vm.LONG, val, Long.toString(val) + 'L');
230 }
231
232 @Override
233 public long toLong() {
234 return (Long) val;
235 }
236 }
237
238
239
240
241 static class MNull extends MLiteral implements Null {
242
243 MNull(MVM vm) {
244 super(vm, vm.NULL, null, "null");
245 }
246 }
247
248
249
250
251 static class MOctalLiteral extends MCharLiteral implements OctalLiteral {
252
253 MOctalLiteral(MVM vm, char val) {
254 super(vm, val);
255 label = "'\\" + Integer.toOctalString(val) + "'";
256 }
257 }
258
259
260
261
262 static class MScientificLiteral extends MLiteral implements ScientificLiteral {
263
264 final int precision;
265
266 final int scale;
267
268 final int exponent;
269
270 MScientificLiteral(MVM vm, int precision, int scale, int exponent) {
271 super(vm, vm.DOUBLE, null, format("%d.%de%d", precision, scale, exponent));
272 this.precision = precision;
273 this.scale = scale;
274 this.exponent = exponent;
275 }
276
277 @Override
278 public int getExponent() {
279 return exponent;
280 }
281
282 @Override
283 public int getPrecision() {
284 return precision;
285 }
286
287 @Override
288 public int getScale() {
289 return scale;
290 }
291 }
292
293
294
295
296 static class MShortLiteral extends MLiteral implements ShortLiteral {
297
298 MShortLiteral(MVM vm, short val) {
299 super(vm, vm.SHORT, val, "(short) " + val);
300 }
301
302 @Override
303 public short toShort() {
304 return (short) val;
305 }
306 }
307
308
309
310
311 static class MStringLiteral extends MLiteral implements StringLiteral {
312
313 MStringLiteral(MVM vm, String val) {
314 super(vm, vm.STRING, val, escapeValue(val));
315 }
316
317 private static void escape(String s, StringBuilder b) {
318
319 int len = s.length();
320
321 for (int i = 0; i < len; i++) {
322 MCharLiteral.escape(s.charAt(i), b, true);
323 }
324 }
325
326 private static String escapeValue(String val) {
327 StringBuilder b = new StringBuilder();
328 b.append("\"");
329 escape(val, b);
330 b.append("\"");
331 return b.toString();
332 }
333 }
334
335
336
337
338 static class MTrue extends MBooleanLiteral implements True {
339
340 MTrue(MVM vm) {
341 super(vm, true);
342 }
343 }
344
345
346
347
348 static class MUnicodeLiteral extends MCharLiteral implements UnicodeLiteral {
349
350 MUnicodeLiteral(MVM vm, char val) {
351 super(vm, val);
352 label = "'\\u" + Integer.toHexString(val) + "'";
353 }
354 }
355
356 private Comment comment;
357
358 private Type type;
359
360 final Object val;
361
362 String label;
363
364 MLiteral(MVM vm, Type type, Object val, String label) {
365 super(vm);
366 this.type = type;
367 this.val = val;
368 this.label = label;
369 }
370
371 @Override
372 public Comment getComment() {
373 return comment;
374 }
375
376 public MLiteral setComment(Comment comment) {
377 this.comment = comment;
378 return this;
379 }
380
381 @Override
382 public Type getType() {
383 return type;
384 }
385
386 @Override
387 public CodeWriter toCode(CodeWriter out) {
388 out.queue(comment);
389 out.write(label);
390 return out;
391 }
392
393 @Override
394 public Object toObject() {
395 return val;
396 }
397
398 @Override
399 public void visit(ReplacingVisitor visitor) {
400 super.visit(visitor);
401 type = VisitorUtils.visit(type, this, visitor);
402 comment = VisitorUtils.visit(comment, this, visitor);
403 }
404 }