Not logged in.  Login/Logout/Register | List snippets | | Create snippet | Upload image | Upload data

502
LINES

< > BotCompany Repo | #1005975 // unstructure (v10, from stream, dev.)

JavaX fragment (include)

1  
static Object unstructure(String text) {
2  
  ret unstructure(text, false);
3  
}
4  
5  
static Object unstructure(String text, final boolean allDynamic) {
6  
  ret unstructure(text, allDynamic, null);
7  
}
8  
9  
static int structure_internStringsLongerThan = 50;
10  
11  
abstract sclass unstructure_Receiver {
12  
  abstract void set(O o);
13  
}
14  
15  
// classFinder: func(name) -> class (optional)
16  
static Object unstructure(String text, boolean allDynamic,
17  
  O classFinder) {
18  
  if (text == null) ret null;
19  
  final L<S> tok = javaTokC(text);
20  
  ret unstructure_tok(tok, allDynamic, classFinder);
21  
}
22  
23  
// so text can be freed
24  
static Object unstructure_tempVar(Var<S> text) {
25  
  L<S> tok = javaTokC(text.get());
26  
  text.clear();
27  
  ret unstructure_tok(tok, false, null);
28  
}
29  
30  
static O unstructure_tok(final L<S> tok, final boolean allDynamic, final O classFinder) {
31  
  final boolean debug = unstructure_debug;
32  
  
33  
  class X {
34  
    int i = 0;
35  
    new HashMap<Integer, O> refs;
36  
    new HashMap<Integer, O> tokrefs;
37  
    new HashSet<S> concepts;
38  
    new HashMap<S, Class> classesMap;
39  
    new L<Runnable> stack;
40  
    
41  
    // look at current token
42  
    S t() {
43  
      ret _get(tok, i);
44  
    }
45  
    
46  
    // get current token, move to next
47  
    S tpp() {
48  
      ret _get(tok, i++);
49  
    }
50  
    
51  
    void parse(final unstructure_Receiver out) {
52  
      S t = t();
53  
      
54  
      int refID = 0;
55  
      if (structure_isMarker(t, 0, l(t))) {
56  
        refID = parseInt(t.substring(1));
57  
        consume();
58  
      }
59  
      final int _refID = refID;
60  
      
61  
      // if (debug) print("parse: " + quote(t));
62  
      
63  
      final int tokIndex = i;  
64  
      parse_inner(refID, tokIndex, new unstructure_Receiver {
65  
        void set(O o) {
66  
          if (_refID != 0)
67  
            refs.put(_refID, o);
68  
          if (o != null)
69  
            tokrefs.put(tokIndex, o);
70  
          out.set(o);
71  
        }
72  
      });
73  
    }
74  
    
75  
    void parse_inner(int refID, int tokIndex, final unstructure_Receiver out) {
76  
      S t = t();
77  
      
78  
      // if (debug) print("parse_inner: " + quote(t));
79  
      
80  
      Class c = classesMap.get(t);
81  
      if (c == null) {
82  
        if (t.startsWith("\"")) {
83  
          S s = internIfLongerThan(unquote(tpp()), structure_internStringsLongerThan);
84  
          out.set(s); ret;
85  
        }
86  
        
87  
        if (t.startsWith("'")) {
88  
          out.set(unquoteCharacter(tpp())); ret;
89  
        }
90  
        if (t.equals("bigint")) {
91  
          out.set(parseBigInt()); ret;
92  
        }
93  
        if (t.equals("d")) {
94  
          out.set(parseDouble()); ret;
95  
        }
96  
        if (t.equals("fl")) {
97  
          out.set(parseFloat()); ret;
98  
        }
99  
        if (t.equals("false") || t.equals("f")) {
100  
          consume(); out.set(false); ret;
101  
        }
102  
        if (t.equals("true") || t.equals("t")) {
103  
          consume(); out.set(true); ret;
104  
        }
105  
        if (t.equals("-")) {
106  
          consume();
107  
          t = tpp();
108  
          out.set(isLongConstant(t) ? (O) (-parseLong(t)) : (O) (-parseInt(t))); ret;
109  
        }
110  
        if (isInteger(t) || isLongConstant(t)) {
111  
          consume();
112  
          //if (debug) print("isLongConstant " + quote(t) + " => " + isLongConstant(t));
113  
          if (isLongConstant(t)) {
114  
            out.set(parseLong(t)); ret;
115  
          }
116  
          long l = parseLong(t);
117  
          bool isInt = l == (int) l;
118  
          if (debug)
119  
            print("l=" + l + ", isInt: " + isInt);
120  
          out.set(isInt ? (O) new Integer((int) l) : (O) new Long(l)); ret;
121  
        }
122  
        
123  
        if (t.equals("File")) {
124  
          consume();
125  
          File f = new File(unquote(tpp()));
126  
          out.set(f); ret;
127  
        }
128  
        
129  
        if (t.startsWith("r") && isInteger(t.substring(1))) {
130  
          consume();
131  
          int ref = Integer.parseInt(t.substring(1));
132  
          O o = refs.get(ref);
133  
          if (o == null)
134  
            print("Warning: unsatisfied back reference " + ref);
135  
          out.set(o); ret;
136  
        }
137  
      
138  
        if (t.startsWith("t") && isInteger(t.substring(1))) {
139  
          consume();
140  
          int ref = Integer.parseInt(t.substring(1));
141  
          O o = tokrefs.get(ref);
142  
          if (o == null)
143  
            print("Warning: unsatisfied token reference " + ref);
144  
          out.set(o); ret;
145  
        }
146  
        
147  
        if (t.equals("hashset")) {
148  
          parseHashSet(out); ret;
149  
        }
150  
        if (t.equals("treeset")) {
151  
          parseTreeSet(out); ret;
152  
        }
153  
        if (eqOneOf(t, "hashmap", "hm")) {
154  
          parseHashMap(out); ret;
155  
        }
156  
        if (t.equals("{")) {
157  
          parseMap(out); ret;
158  
        }
159  
        if (t.equals("[")) {
160  
          parseList(out); ret;
161  
        }
162  
        if (t.equals("bitset")) {
163  
          parseBitSet(out); ret;
164  
        }
165  
        if (t.equals("array") || t.equals("intarray")) {
166  
          parseArray(out); ret;
167  
        }
168  
        if (t.equals("ba")) {
169  
          consume();
170  
          S hex = unquote(tpp());
171  
          out.set(hexToBytes(hex)); ret;
172  
        }
173  
        if (t.equals("boolarray")) {
174  
          consume();
175  
          int n = parseInt(tpp());
176  
          S hex = unquote(tpp());
177  
          out.set(boolArrayFromBytes(hexToBytes(hex), n)); ret;
178  
        }
179  
        if (t.equals("class")) {
180  
          out.set(parseClass()); ret;
181  
        }
182  
        if (t.equals("l")) {
183  
          parseLisp(out); ret;
184  
        }
185  
        if (t.equals("null")) {
186  
          consume(); out.set(null); ret;
187  
        }
188  
        
189  
        if (eq(t, "c")) {
190  
          consume("c");
191  
          t = t();
192  
          assertTrue(isJavaIdentifier(t));
193  
          concepts.add(t);
194  
        }
195  
      }
196  
      
197  
      if (c == null && !isJavaIdentifier(t))
198  
        throw new RuntimeException("Unknown token " + (i+1) + ": " + t);
199  
200  
      // any other class name
201  
      if (c == null) {
202  
        // First, find class
203  
        if (allDynamic) c = null;
204  
        else if (classFinder != null)
205  
          c = (Class) callF(classFinder, t);
206  
        else
207  
          c = findClass(t);
208  
        if (c != null)
209  
          classesMap.put(t, c);
210  
      }
211  
          
212  
      // Check if it has an outer reference
213  
      consume();
214  
      bool hasBracket = eq(t(), "(");
215  
      if (hasBracket) consume();
216  
      bool hasOuter = hasBracket && eq(t(), "this$1");
217  
      
218  
      DynamicObject dO = null;
219  
      O o = null;
220  
      if (c != null)
221  
        o = hasOuter ? nuStubInnerObject(c) : nuEmptyObject(c);
222  
      else {
223  
        if (concepts.contains(t) && (c = findClass("Concept")) != null)
224  
          o = dO = (DynamicObject) nuEmptyObject(c);
225  
        else
226  
          dO = new DynamicObject;
227  
        dO.className = t;
228  
        if (debug) print("Made dynamic object " + t + " " + shortClassName(dO));
229  
      }
230  
      
231  
      // Save in references list early because contents of object
232  
      // might link back to main object
233  
      
234  
      if (refID != 0)
235  
        refs.put(refID, o != null ? o : dO);
236  
      tokrefs.put(tokIndex, o != null ? o : dO);
237  
      
238  
      // NOW parse the fields!
239  
      
240  
      final new HashMap<S, O> fields;
241  
      final O _o = o;
242  
      final DynamicObject _dO = dO;
243  
      if (hasBracket) {
244  
        stack.add(r {
245  
          if (eq(t(), ")")) {
246  
            consume(")");
247  
            objRead(_o, _dO, fields);
248  
            out.set(_o != null ? _o : _dO);
249  
          } else {
250  
            final S key = unquote(tpp());
251  
            consume("=");
252  
            stack.add(this);
253  
            parse(new unstructure_Receiver {
254  
              void set(O value) {
255  
                fields.put(key, value);
256  
                if (eq(t(), ",")) consume();
257  
              }
258  
            });
259  
          }
260  
        });
261  
      } else
262  
        objRead(o, dO, fields);
263  
    }
264  
    
265  
    void objRead(O o, DynamicObject dO, Map<S, O> fields) {
266  
      if (o != null)
267  
        if (dO != null) {
268  
          if (debug)
269  
            printStructure("setOptAllDyn", fields);
270  
          setOptAllDyn(dO, fields);
271  
        } else
272  
          setOptAll(o, fields);
273  
      else for (S field : keys(fields))
274  
        dO.fieldValues.put(field.intern(), fields.get(field));
275  
276  
      if (o != null)
277  
        pcallOpt_noArgs(o, "_doneLoading");
278  
    }
279  
    
280  
    void parseSet(final Set set, final unstructure_Receiver out) {
281  
      parseList(new unstructure_Receiver {
282  
        void set(O o) {
283  
          set.addAll((L) o);
284  
          out.set(set);
285  
        }
286  
      });
287  
    }
288  
    
289  
    void parseLisp(final unstructure_Receiver out) {
290  
      consume("l");
291  
      consume("(");
292  
      final new ArrayList list;
293  
      stack.add(r {
294  
        if (eq(t(), ")")) {
295  
          consume(")");
296  
          out.set(newObject("main$Lisp", (S) list.get(0), subList(list, 1)));
297  
        } else {
298  
          stack.add(this);
299  
          parse(new unstructure_Receiver {
300  
            void set(O o) {
301  
              list.add(o);
302  
              if (eq(t(), ",")) consume();
303  
            }
304  
          });
305  
        }
306  
      });
307  
    }
308  
    
309  
    void parseBitSet(final unstructure_Receiver out) {
310  
      consume("bitset");
311  
      consume("{");
312  
      final new BitSet bs;
313  
      stack.add(r {
314  
        if (eq(t(), "}")) {
315  
          consume("}");
316  
          out.set(bs);
317  
        } else {
318  
          stack.add(this);
319  
          parse(new unstructure_Receiver {
320  
            void set(O o) {
321  
              bs.set((Integer) o);
322  
              if (eq(t(), ",")) consume();
323  
            }
324  
          });
325  
        }
326  
      });
327  
    }
328  
    
329  
    void parseList(final unstructure_Receiver out) {
330  
      consume("[");
331  
      final new ArrayList list;
332  
      stack.add(r {
333  
        if (eq(t(), "]")) {
334  
          consume("]");
335  
          out.set(list);
336  
        } else {
337  
          stack.add(this);
338  
          parse(new unstructure_Receiver {
339  
            void set(O o) {
340  
              //if (debug) print("List element type: " + getClassName(o));
341  
              list.add(o);
342  
              if (eq(t(), ",")) consume();
343  
            }
344  
          });
345  
        }
346  
      });
347  
    }
348  
    
349  
    void parseArray(final unstructure_Receiver out) {
350  
      final S type = tpp();
351  
      consume("{");
352  
      final List list = new ArrayList;
353  
      
354  
      stack.add(r {
355  
        if (eq(t(), "}")) {
356  
          consume("}");
357  
          out.set(type.equals("intarray") ? toIntArray(list) : list.toArray());
358  
        } else {
359  
          stack.add(this);
360  
          parse(new unstructure_Receiver {
361  
            void set(O o) {
362  
              list.add(o);
363  
              if (eq(t(), ",")) consume();
364  
            }
365  
          });
366  
        }
367  
      });
368  
    }
369  
    
370  
    Object parseClass() {
371  
      consume("class");
372  
      consume("(");
373  
      S name = tpp();
374  
      consume(")");
375  
      Class c = allDynamic ? null : findClass(name);
376  
      if (c != null) ret c;
377  
      new DynamicObject dO;
378  
      dO.className = "java.lang.Class";
379  
      dO.fieldValues.put("name", name);
380  
      ret dO;
381  
    }
382  
    
383  
    Object parseBigInt() {
384  
      consume("bigint");
385  
      consume("(");
386  
      S val = tpp();
387  
      if (eq(val, "-"))
388  
        val = "-" + tpp();
389  
      consume(")");
390  
      ret new BigInteger(val);
391  
    }
392  
    
393  
    Object parseDouble() {
394  
      consume("d");
395  
      consume("(");
396  
      S val = unquote(tpp());
397  
      consume(")");
398  
      ret Double.parseDouble(val);
399  
    }
400  
    
401  
    Object parseFloat() {
402  
      consume("fl");
403  
      S val;
404  
      if (eq(t(), "(")) {
405  
        consume("(");
406  
        val = unquote(tpp());
407  
        consume(")");
408  
      } else {
409  
        val = unquote(tpp());
410  
      }
411  
      ret Float.parseFloat(val);
412  
    }
413  
    
414  
    void parseHashMap(unstructure_Receiver out) {
415  
      consume();
416  
      parseMap(new HashMap, out);
417  
    }
418  
    
419  
    void parseHashSet(unstructure_Receiver out) {
420  
      consume("hashset");
421  
      parseSet(new HashSet, out);
422  
    }
423  
    
424  
    void parseTreeSet(unstructure_Receiver out) {
425  
      consume("treeset");
426  
      parseSet(new TreeSet, out);
427  
    }
428  
    
429  
    void parseMap(unstructure_Receiver out) {
430  
      parseMap(new TreeMap, out);
431  
    }
432  
    
433  
    void parseMap(final Map map, final unstructure_Receiver out) {
434  
      consume("{");
435  
      stack.add(new Runnable {
436  
        bool v;
437  
        O key;
438  
        
439  
        public void run() { 
440  
          if (v) {
441  
            v = false;
442  
            stack.add(this);
443  
            consume("=");
444  
            parse(new unstructure_Receiver {
445  
              void set(O value) {
446  
                map.put(key, value);
447  
                if (debug)
448  
                  print("parseMap: Got value " + getClassName(value) + ", next token: " + quote(t()));
449  
                if (eq(t(), ",")) consume();
450  
              }
451  
            });
452  
          } else {
453  
            if (eq(t(), "}")) {
454  
              consume("}");
455  
              out.set(map);
456  
            } else {
457  
              v = true;
458  
              stack.add(this);
459  
              parse(new unstructure_Receiver {
460  
                void set(O o) {
461  
                  key = o;
462  
                }
463  
              });
464  
            }
465  
          } // if v else
466  
        } // run()
467  
      });
468  
    }
469  
    
470  
    /*void parseSub(unstructure_Receiver out) {
471  
      int n = l(stack);
472  
      parse(out);
473  
      while (l(stack) > n)
474  
        stack
475  
    }*/
476  
    
477  
    void consume() { i++; }
478  
    
479  
    void consume(String s) {
480  
      if (!eq(t(), s)) {
481  
        S prevToken = i-1 >= 0 ? tok.get(i-1) : "";
482  
        S nextTokens = join(tok.subList(i, Math.min(i+2, tok.size())));
483  
        fail(quote(s) + " expected: " + prevToken + " " + nextTokens + " (" + i + "/" + tok.size() + ")");
484  
      }
485  
      i++;
486  
    }
487  
    
488  
    void parse_x(unstructure_Receiver out) {
489  
      parse(out);
490  
      while (nempty(stack))
491  
        popLast(stack).run();
492  
    }
493  
  }
494  
  
495  
  final new Var v;
496  
  new X().parse_x(new unstructure_Receiver {
497  
    void set(O o) { v.set(o); }
498  
  });
499  
  ret v.get();
500  
}
501  
502  
static boolean unstructure_debug;

Author comment

Began life as a copy of #1005973

download  show line numbers  debug dex  old transpilations   

Travelled to 14 computer(s): aoiabmzegqzx, bhatertpkbcr, cbybwowwnfue, cfunsshuasjs, gwrvuhgaqvyk, ishqpsrjomds, lpdgvwnxivlt, mqqgnosmbjvj, pyentgdyhuwx, pzhvpgtvlbxg, sawdedvomwva, tslmcundralx, tvejysmllsmz, vouqrxazstgt

No comments. add comment

Snippet ID: #1005975
Snippet name: unstructure (v10, from stream, dev.)
Eternal ID of this version: #1005975/1
Text MD5: e4262774cdd2251e229da2b4df43dfa2
Author: stefan
Category: javax
Type: JavaX fragment (include)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2016-12-13 17:16:52
Source code size: 13871 bytes / 502 lines
Pitched / IR pitched: No / No
Views / Downloads: 476 / 482
Referenced in: [show references]