1 | static class DynamicObject { |
2 | S className; |
3 | new Map<S, O> fieldValues; |
4 | } |
5 | |
6 | static Object unstructure(String text) { |
7 | ret unstructure(text, false); |
8 | } |
9 | |
10 | static Object unstructure(String text, boolean allDynamic) { |
11 | ret unstructure(text, allDynamic, new HashMap<Integer, O>()); |
12 | } |
13 | |
14 | static Object unstructure(String text, final boolean allDynamic, |
15 | final HashMap<Integer, O> seen) { |
16 | final L<S> tok = javaTok(text); |
17 | final boolean debug = true; |
18 | |
19 | class X { |
20 | int i = 1; |
21 | |
22 | Object parse() { |
23 | // the non-backreference things |
24 | |
25 | String t = tok.get(i); |
26 | |
27 | if (debug) |
28 | print("parse: " + quote(t)); |
29 | |
30 | if (t.startsWith("\"")) { |
31 | String s = unquote(tok.get(i)); |
32 | i += 2; |
33 | return s; |
34 | } |
35 | if (t.equals("bigint")) |
36 | return parseBigInt(); |
37 | if (t.equals("d")) |
38 | return parseDouble(); |
39 | if (t.equals("false")) { |
40 | i += 2; return false; |
41 | } |
42 | if (t.equals("true")) { |
43 | i += 2; return true; |
44 | } |
45 | if (t.equals("-")) { |
46 | t = tok.get(i+2); |
47 | i += 4; |
48 | t = dropSuffix("L", t); |
49 | long l = -Long.parseLong(t); |
50 | ret l == (int) l ? (int) l : l; |
51 | } |
52 | if (isInteger(t) || isLongConstant(t)) { |
53 | i += 2; |
54 | t = dropSuffix("L", t); |
55 | long l = Long.parseLong(t); |
56 | ret l == (int) l ? (int) l : l; |
57 | } |
58 | |
59 | if (t.startsWith("r") && isInteger(t.substring(1))) { |
60 | i += 2; |
61 | int ref = Integer.parseInt(t.substring(1)); |
62 | O o = seen.get(ref); |
63 | if (o == null) |
64 | print("Warning: unsatisfied back reference " + ref); |
65 | ret o; |
66 | } |
67 | |
68 | O o = parse_inner(); |
69 | seen.put(seen.size()+1, o); |
70 | ret o; |
71 | } |
72 | |
73 | // everything that can be backreferenced |
74 | O parse_inner() { |
75 | String t = tok.get(i); |
76 | |
77 | if (debug) |
78 | print("parse_inner: " + quote(t)); |
79 | |
80 | if (t.equals("hashset")) |
81 | return parseHashSet(); |
82 | if (t.equals("treeset")) |
83 | return parseTreeSet(); |
84 | if (t.equals("hashmap")) |
85 | return parseHashMap(); |
86 | if (t.equals("{")) |
87 | return parseMap(); |
88 | if (t.equals("[")) |
89 | return parseList(); |
90 | if (t.equals("array")) |
91 | return parseArray(); |
92 | if (t.equals("class")) |
93 | return parseClass(); |
94 | if (t.equals("l")) |
95 | return parseLisp(); |
96 | if (t.equals("null")) { |
97 | i += 2; return null; |
98 | } |
99 | if (isJavaIdentifier(t)) { |
100 | Class c = allDynamic ? null : findClass(t); |
101 | DynamicObject dO = null; |
102 | O o = null; |
103 | if (c != null) |
104 | o = nuObject(c); |
105 | else { |
106 | dO = new DynamicObject; |
107 | dO.className = t; |
108 | } |
109 | i += 2; |
110 | if (i < tok.size() && tok.get(i).equals("(")) { |
111 | consume("("); |
112 | while (!tok.get(i).equals(")")) { |
113 | // It's like parsing a map. |
114 | //Object key = parse(); |
115 | //if (tok.get(i).equals(")")) |
116 | // key = onlyField(); |
117 | String key = unquote(tok.get(i)); |
118 | i += 2; |
119 | consume("="); |
120 | Object value = parse(); |
121 | if (o != null) |
122 | setOpt(o, key, value); |
123 | else |
124 | dO.fieldValues.put(key, value); |
125 | if (tok.get(i).equals(",")) i += 2; |
126 | } |
127 | consume(")"); |
128 | } |
129 | return o != null ? o : dO; |
130 | } |
131 | throw new RuntimeException("Unknown token " + (i+1) + ": " + t); |
132 | } |
133 | |
134 | Object parseSet(Set set) { |
135 | set.addAll((L) parseList()); |
136 | return set; |
137 | } |
138 | |
139 | Object parseLisp() { |
140 | consume("l"); |
141 | consume("("); |
142 | List list = new ArrayList; |
143 | while (!tok.get(i).equals(")")) { |
144 | list.add(parse()); |
145 | if (tok.get(i).equals(",")) i += 2; |
146 | } |
147 | consume(")"); |
148 | return newObject("main$Lisp", (S) list.get(0), subList(list, 1)); |
149 | } |
150 | |
151 | Object parseList() { |
152 | consume("["); |
153 | List list = new ArrayList; |
154 | while (!tok.get(i).equals("]")) { |
155 | list.add(parse()); |
156 | if (tok.get(i).equals(",")) i += 2; |
157 | } |
158 | consume("]"); |
159 | return list; |
160 | } |
161 | |
162 | Object parseArray() { |
163 | consume("array"); |
164 | consume("{"); |
165 | List list = new ArrayList; |
166 | while (!tok.get(i).equals("}")) { |
167 | list.add(parse()); |
168 | if (tok.get(i).equals(",")) i += 2; |
169 | } |
170 | consume("}"); |
171 | return list.toArray(); |
172 | } |
173 | |
174 | Object parseClass() { |
175 | consume("class"); |
176 | consume("("); |
177 | S name = tok.get(i); |
178 | i += 2; |
179 | consume(")"); |
180 | Class c = allDynamic ? null : findClass(name); |
181 | if (c != null) ret c; |
182 | new DynamicObject dO; |
183 | dO.className = "java.lang.Class"; |
184 | dO.fieldValues.put("name", name); |
185 | ret dO; |
186 | } |
187 | |
188 | Object parseBigInt() { |
189 | consume("bigint"); |
190 | consume("("); |
191 | S val = tok.get(i); |
192 | i += 2; |
193 | if (eq(val, "-")) { |
194 | val = "-" + tok.get(i); |
195 | i += 2; |
196 | } |
197 | consume(")"); |
198 | ret new BigInteger(val); |
199 | } |
200 | |
201 | Object parseDouble() { |
202 | consume("d"); |
203 | consume("("); |
204 | S val = unquote(tok.get(i)); |
205 | i += 2; |
206 | consume(")"); |
207 | ret Double.parseDouble(val); |
208 | } |
209 | |
210 | Object parseHashMap() { |
211 | consume("hashmap"); |
212 | return parseMap(new HashMap); |
213 | } |
214 | |
215 | Object parseHashSet() { |
216 | consume("hashset"); |
217 | return parseSet(new HashSet); |
218 | } |
219 | |
220 | Object parseTreeSet() { |
221 | consume("treeset"); |
222 | return parseSet(new TreeSet); |
223 | } |
224 | |
225 | Object parseMap() { |
226 | return parseMap(new TreeMap); |
227 | } |
228 | |
229 | Object parseMap(Map map) { |
230 | consume("{"); |
231 | while (!tok.get(i).equals("}")) { |
232 | //O key = unstructure(tok.get(i)); |
233 | O key = parse(); |
234 | consume("="); |
235 | Object value = parse(); |
236 | map.put(key, value); |
237 | if (tok.get(i).equals(",")) i += 2; |
238 | } |
239 | consume("}"); |
240 | return map; |
241 | } |
242 | |
243 | void consume(String s) { |
244 | if (!tok.get(i).equals(s)) { |
245 | S prevToken = i-2 >= 0 ? tok.get(i-2) : ""; |
246 | S nextTokens = join(tok.subList(i, Math.min(i+4, tok.size()))); |
247 | fail(quote(s) + " expected: " + prevToken + " " + nextTokens + " (" + i + "/" + tok.size() + ")"); |
248 | } |
249 | i += 2; |
250 | } |
251 | } |
252 | |
253 | return new X().parse(); |
254 | } |
Began life as a copy of #1001355
download show line numbers debug dex old transpilations
Travelled to 13 computer(s): aoiabmzegqzx, bhatertpkbcr, cbybwowwnfue, cfunsshuasjs, gwrvuhgaqvyk, ishqpsrjomds, lpdgvwnxivlt, mqqgnosmbjvj, pyentgdyhuwx, pzhvpgtvlbxg, tslmcundralx, tvejysmllsmz, vouqrxazstgt
No comments. add comment
Snippet ID: | #1003021 |
Snippet name: | unstructure with back references |
Eternal ID of this version: | #1003021/1 |
Text MD5: | 884f1927332db4a091c356c8f6fb8056 |
Author: | stefan |
Category: | javax |
Type: | JavaX fragment (include) |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2016-04-19 17:54:07 |
Source code size: | 6531 bytes / 254 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 586 / 802 |
Referenced in: | [show references] |