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: | 789 / 1022 |
| Referenced in: | [show references] |