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

864
LINES

< > BotCompany Repo | #1035798 // unstructure (v20, introducing the Unstructurer class, LIVE)

JavaX fragment (include) [tags: use-pretranspiled]

Transpiled version (11875L) is out of date.

1  
scope unstructure
2  
3  
// TODO: cyclic structures involving certain lists & sets
4  
5  
ifdef UseEclipseCollections
6  
!include once #1027304 // Eclipse Collections
7  
endifdef
8  
9  
sO unstructure(String text) {
10  
  ret unstructure(text, false);
11  
}
12  
13  
sO unstructure(S text, bool allDynamic) {
14  
  ret unstructure(text, allDynamic, null);
15  
}
16  
17  
sO unstructure(S text, IF1<S, Class> classFinder) {
18  
  ret unstructure(text, false, classFinder);
19  
}
20  
21  
static int structure_internStringsLongerThan = 50;
22  
static int unstructure_unquoteBufSize = 100;
23  
24  
static int unstructure_tokrefs; // stats
25  
26  
abstract sclass unstructure_Receiver {
27  
  abstract void set(O o);
28  
}
29  
30  
// classFinder: func(name) -> class (optional)
31  
static Object unstructure(String text, boolean allDynamic,
32  
  O classFinder) {
33  
  if (text == null) ret null;
34  
  ret unstructure_tok(javaTokC_noMLS_iterator(text), allDynamic, classFinder);
35  
}
36  
37  
static O unstructure_reader(BufferedReader reader) {
38  
  ret unstructure_tok(javaTokC_noMLS_onReader(reader), false, null);
39  
}
40  
41  
interface #Handler {
42  
  void parse(int refID, int tokIndex, unstructure_Receiver out);
43  
}
44  
  
45  
sclass Unstructurer {
46  
  settable Producer<S> tok;
47  
  settable bool allDynamic;
48  
  int i = -1;
49  
  O classFinder;
50  
  S mcDollar = actualMCDollar();
51  
  
52  
  selfType classFinder(O _classFinder) {
53  
    classFinder = _classFinder != null ? _classFinder : _defaultClassFinder();
54  
    this;
55  
  }
56  
57  
  // use Eclipse primitive collection if possible (smaller & hopefully faster?)
58  
  ifdef UseEclipseCollections
59  
  new IntObjectHashMap<O> refs;
60  
  new IntObjectHashMap<O> tokrefs;
61  
  endifdef
62  
  ifndef UseEclipseCollections
63  
  new HashMap<Integer, O> refs;
64  
  new HashMap<Integer, O> tokrefs;
65  
  endifndef
66  
  
67  
  new HashSet<S> concepts;
68  
  new L<Runnable> stack;
69  
  new SS baseClassMap;
70  
  new HashMap<Class, Constructor> innerClassConstructors;
71  
  S curT;
72  
  char[] unquoteBuf = new char[unstructure_unquoteBufSize];
73  
  
74  
  // value is a class or a Handler
75  
  final new HashMap<S, O> handlers;
76  
  
77  
  *() {
78  
    pcall {
79  
      Class mc = cast callF(classFinder, "<main>");
80  
      if (mc != null) mcDollar = mc.getName() + "$";
81  
    }
82  
    
83  
    makeHandlers();
84  
  }
85  
  
86  
  replace HandlerArgs with (Handler) (refID, tokIndex, out).
87  
  
88  
  void makeHandlers {
89  
    Handler h;
90  
    
91  
    handlers.put("bigint", HandlerArgs
92  
      -> out.set(parseBigInt()));
93  
      
94  
    handlers.put("d", HandlerArgs
95  
      -> out.set(parseDouble()));
96  
      
97  
    handlers.put("fl", HandlerArgs
98  
      -> out.set(parseFloat()));
99  
      
100  
    handlers.put("sh", HandlerArgs -> {
101  
      consume();
102  
      S t = tpp();
103  
      if (t.equals("-")) {
104  
        t = tpp();
105  
        out.set((short) (-parseInt(t)); ret;
106  
      }
107  
      out.set((short) parseInt(t));
108  
    });
109  
    
110  
    handlers.put("enum", HandlerArgs -> {
111  
      consume();
112  
      S t = tpp();
113  
      assertTrue(isJavaIdentifier(t));
114  
      S fullClassName = mcDollar + t;
115  
      Class _c = findAClass(fullClassName);
116  
      if (_c == null) fail("Enum class not found: " + fullClassName);
117  
      int ordinal = parseInt(tpp());
118  
      out.set(_c.getEnumConstants()[ordinal]);
119  
    });
120  
121  
    handlers.put("false", h = HandlerArgs -> {
122  
      consume(); out.set(false);
123  
    });
124  
    handlers.put("f", h);
125  
    
126  
    handlers.put("true", h = HandlerArgs -> {
127  
      consume(); out.set(true);
128  
    });
129  
    handlers.put("t", h);
130  
    
131  
    handlers.put("{", HandlerArgs -> parseMap(out));
132  
    
133  
    handlers.put("[", HandlerArgs -> {
134  
      new ArrayList l;
135  
      if (refID >= 0) refs.put(refID, l);
136  
      this.parseList(l, out);
137  
    });
138  
    
139  
    handlers.put("bitset", HandlerArgs -> parseBitSet(out));
140  
    
141  
    handlers.put("array", h = HandlerArgs -> parseArray(out));
142  
    handlers.put("intarray", h);
143  
    handlers.put("dblarray", h);
144  
    handlers.put("floatarray", h);
145  
    
146  
    handlers.put("shortarray", HandlerArgs -> {
147  
      consume();
148  
      S hex = trivialUnquote(tpp());
149  
      out.set(shortArrayFromBytes(hexToBytes(hex)));
150  
    });
151  
    
152  
    handlers.put("longarray", HandlerArgs -> {
153  
      consume();
154  
      S hex = trivialUnquote(tpp());
155  
      out.set(longArrayFromBytes(hexToBytes(hex)));
156  
    });
157  
  } // end of makeHandlers - add more handlers here
158  
159  
  Class findAClass(S fullClassName) null on exception {
160  
    ret classFinder != null ? (Class) callF(classFinder, fullClassName) : findClass_fullName(fullClassName);
161  
  }
162  
  
163  
  S unquote(S s) {
164  
    ret unquoteUsingCharArray(s, unquoteBuf); 
165  
  }
166  
167  
  // look at current token
168  
  S t() {
169  
    ret curT;
170  
  }
171  
  
172  
  // get current token, move to next
173  
  S tpp() {
174  
    S t = curT;
175  
    consume();
176  
    ret t;
177  
  }
178  
  
179  
  void parse(final unstructure_Receiver out) {
180  
    S t = t();
181  
    
182  
    int refID;
183  
    if (structure_isMarker(t, 0, l(t))) {
184  
      refID = parseInt(t.substring(1));
185  
      consume();
186  
    } else refID = -1;
187  
    
188  
    // if (debug) print("parse: " + quote(t));
189  
    
190  
    final int tokIndex = i;  
191  
    parse_inner(refID, tokIndex, new unstructure_Receiver {
192  
      void set(O o) {
193  
        if (refID >= 0)
194  
          refs.put(refID, o);
195  
        if (o != null)
196  
          tokrefs.put(tokIndex, o);
197  
        out.set(o);
198  
      }
199  
    });
200  
  }
201  
  
202  
  void parse_inner(int refID, int tokIndex, unstructure_Receiver out) {
203  
    S t = t();
204  
    
205  
    // if (debug) print("parse_inner: " + quote(t));
206  
    
207  
    O handler = handlers.get(t);
208  
    if (handler cast Handler)
209  
      ret with handler.parse(refID, tokIndex, out);
210  
      
211  
    Class c = cast handler;
212  
    if (c == null) {
213  
      if (t.startsWith("\"")) {
214  
        S s = internIfLongerThan(unquote(tpp()), structure_internStringsLongerThan);
215  
        out.set(s); ret;
216  
      }
217  
      
218  
      if (t.startsWith("'")) {
219  
        out.set(unquoteCharacter(tpp())); ret;
220  
      }
221  
      if (t.equals("-")) {
222  
        consume();
223  
        t = tpp();
224  
        out.set(isLongConstant(t) ? (O) (-parseLong(t)) : (O) (-parseInt(t))); ret;
225  
      }
226  
      if (isInteger(t) || isLongConstant(t)) {
227  
        consume();
228  
        //if (debug) print("isLongConstant " + quote(t) + " => " + isLongConstant(t));
229  
        if (isLongConstant(t)) {
230  
          out.set(parseLong(t)); ret;
231  
        }
232  
        long l = parseLong(t);
233  
        bool isInt = l == (int) l;
234  
        ifdef unstructure_debug
235  
          print("l=" + l + ", isInt: " + isInt);
236  
        endifdef
237  
        out.set(isInt ? (O) Integer.valueOf((int) l) : (O) Long.valueOf(l)); ret;
238  
      }
239  
      if (t.equals("-")) {
240  
        consume();
241  
        t = tpp();
242  
        out.set(isLongConstant(t) ? (O) (-parseLong(t)) : (O) (-parseInt(t))); ret;
243  
      }
244  
      if (isInteger(t) || isLongConstant(t)) {
245  
        consume();
246  
        //if (debug) print("isLongConstant " + quote(t) + " => " + isLongConstant(t));
247  
        if (isLongConstant(t)) {
248  
          out.set(parseLong(t)); ret;
249  
        }
250  
        long l = parseLong(t);
251  
        bool isInt = l == (int) l;
252  
        ifdef unstructure_debug
253  
          print("l=" + l + ", isInt: " + isInt);
254  
        endifdef
255  
        out.set(isInt ? (O) Integer.valueOf((int) l) : (O) Long.valueOf(l)); ret;
256  
      }
257  
      
258  
      if (t.equals("File")) {
259  
        consume();
260  
        File f = new File(unquote(tpp()));
261  
        out.set(f); ret;
262  
      }
263  
      
264  
      if (t.startsWith("r") && isInteger(t.substring(1))) {
265  
        consume();
266  
        int ref = Integer.parseInt(t.substring(1));
267  
        O o = refs.get(ref);
268  
        if (o == null)
269  
          warn("unsatisfied back reference " + ref);
270  
        out.set(o); ret;
271  
      }
272  
    
273  
      if (t.startsWith("t") && isInteger(t.substring(1))) {
274  
        consume();
275  
        int ref = Integer.parseInt(t.substring(1));
276  
        O o = tokrefs.get(ref);
277  
        if (o == null)
278  
          warn("unsatisfied token reference " + ref + " at " + tokIndex);
279  
        out.set(o); ret;
280  
      }
281  
      
282  
      if (t.equals("hashset")) ret with parseHashSet(out);
283  
      if (t.equals("lhs")) ret with parseLinkedHashSet(out);
284  
      if (t.equals("treeset")) ret with parseTreeSet(out);
285  
      if (t.equals("ciset")) ret with parseCISet(out);
286  
      
287  
      if (eqOneOf(t, "hashmap", "hm")) {
288  
        consume();
289  
        parseMap(new HashMap, out);
290  
        ret;
291  
      }
292  
      if (t.equals("lhm")) {
293  
        consume();
294  
        parseMap(new LinkedHashMap, out);
295  
        ret;
296  
      }
297  
      if (t.equals("tm")) {
298  
        consume();
299  
        parseMap(new TreeMap, out);
300  
        ret;
301  
      }
302  
      if (t.equals("cimap")) {
303  
        consume();
304  
        parseMap(ciMap(), out);
305  
        ret;
306  
      }
307  
      
308  
      if (t.equals("ll")) {
309  
        consume();
310  
        new LinkedList l;
311  
        if (refID >= 0) refs.put(refID, l);
312  
        ret with parseList(l, out);
313  
      }
314  
315  
      if (t.equals("syncLL")) { // legacy
316  
        consume();
317  
        ret with parseList(synchroLinkedList(), out);
318  
      }
319  
320  
      if (t.equals("sync")) {
321  
        consume();
322  
        ret with parse(new unstructure_Receiver {
323  
          void set(O value) {
324  
            if (value instanceof Map) {
325  
              ifndef Android // Java 7
326  
              if (value cast NavigableMap)
327  
                ret with out.set(synchroNavigableMap(value);
328  
              endifndef
329  
              if (value cast SortedMap)
330  
                ret with out.set(synchroSortedMap(value);
331  
              ret with out.set(synchroMap((Map) value));
332  
            } else
333  
              ret with out.set(synchroList((L) value);
334  
          }
335  
        });
336  
      }
337  
      
338  
      if (t.equals("ba")) {
339  
        consume();
340  
        S hex = trivialUnquote(tpp());
341  
        out.set(hexToBytes(hex)); ret;
342  
      }
343  
      if (t.equals("boolarray")) {
344  
        consume();
345  
        int n = parseInt(tpp());
346  
        S hex = trivialUnquote(tpp());
347  
        out.set(boolArrayFromBytes(hexToBytes(hex), n)); ret;
348  
      }
349  
      if (t.equals("class")) {
350  
        out.set(parseClass()); ret;
351  
      }
352  
      if (t.equals("l")) {
353  
        parseLisp(out); ret;
354  
      }
355  
      if (t.equals("null")) {
356  
        consume(); out.set(null); ret;
357  
      }
358  
      
359  
      if (eq(t, "c")) {
360  
        consume();
361  
        t = t();
362  
        assertTrue(isJavaIdentifier(t));
363  
        concepts.add(t);
364  
      }
365  
      
366  
      // custom deserialization (new static method method)
367  
      if (eq(t, "cu")) {
368  
        consume();
369  
        t = tpp();
370  
        assertTrue(isJavaIdentifier(t));
371  
        S fullClassName = mcDollar + t;
372  
        Class _c = findAClass(fullClassName);
373  
        if (_c == null) fail("Class not found: " + fullClassName);
374  
        parse(new unstructure_Receiver {
375  
          void set(O value) {
376  
            ifdef unstructure_debug
377  
              print("Consumed custom object, next token: " + t());
378  
            endifdef
379  
            out.set(call(_c, "_deserialize", value);
380  
          }
381  
        });
382  
        ret;
383  
      }
384  
    }
385  
    
386  
    if (eq(t, "j")) {
387  
      consume();
388  
      out.set(parseJava()); ret;
389  
    }
390  
    
391  
    if (eq(t, "bc")) {
392  
      consume();
393  
      S c1 = tpp();
394  
      S c2 = tpp();
395  
      baseClassMap.put(c1, c2);
396  
      ret with parse_inner(refID, i, out);
397  
    }
398  
    
399  
    // add more tokens here
400  
401  
    // Now we want to find our target class c
402  
    // Have we failed to look up the class before?
403  
    //bool seenBefore = handlers.containsKey(cname);
404  
405  
    // If we have seen the class before, we skip all of this
406  
    // and simply leave c as null
407  
    // TODO - how do we fill className?
408  
    //if (!seenBefore) {
409  
      if (c == null && !isJavaIdentifier(t))
410  
        throw new RuntimeException("Unknown token " + (i+1) + ": " + quote(t));
411  
        
412  
      // any other class name (or package name)
413  
      consume();
414  
      S className, fullClassName;
415  
      
416  
      // Is it a package name?
417  
      if (eq(t(), ".")) {
418  
        className = t;
419  
        do {
420  
          consume();
421  
          className += "." + assertIdentifier(tpp());
422  
        } while (eq(t(), "."));
423  
        fullClassName = className;
424  
      } else {
425  
        className = t;
426  
        fullClassName = mcDollar + t;
427  
      }
428  
      
429  
      if (c == null && !allDynamic) {
430  
        // First, find class
431  
        c = findAClass(fullClassName);
432  
        handlers.put(className, c);
433  
      }
434  
      
435  
      // check for existing base class
436  
      if (c == null && !allDynamic) {
437  
        new Set<S> seen;
438  
        S parent = className;
439  
        while true {
440  
          S baseName = baseClassMap.get(parent);
441  
          if (baseName == null)
442  
            break;
443  
          if (!seen.add(baseName))
444  
            fail("Cyclic superclass info: " + baseName);
445  
          c = findAClass(mcDollar + baseName);
446  
          if (c == null)
447  
            print("Base class " + baseName + " of " + parent +  " doesn't exist either");
448  
          else if (isAbstract(c))
449  
            print("Can't instantiate abstract base class: " + c);
450  
          else {
451  
            printVars_str("Reverting to base class", +className, +baseName, +c);
452  
            handlers.put(className, c);
453  
            break;
454  
          }
455  
          parent = baseName;
456  
        }
457  
      }
458  
    //}
459  
        
460  
    // Check if it has an outer reference
461  
    bool hasBracket = eq(t(), "(");
462  
    if (hasBracket) consume();
463  
    bool hasOuter = hasBracket && startsWith(t(), "this$");
464  
    
465  
    DynamicObject dO = null;
466  
    O o = null;
467  
    fS thingName = t;
468  
    pcall {
469  
      if (c != null) {
470  
        if (hasOuter) try {
471  
          Constructor ctor = innerClassConstructors.get(c);
472  
          if (ctor == null)
473  
            innerClassConstructors.put(c, ctor = nuStubInnerObject_findConstructor(c, classFinder));
474  
          o = ctor.newInstance(new O[] {null});
475  
        } catch Exception e {
476  
          print("Error deserializing " + c + ": " + e);
477  
          o = nuEmptyObject(c);
478  
        } else
479  
          o = nuEmptyObject(c);
480  
        if (o instanceof DynamicObject) dO = (DynamicObject) o;
481  
      } else {
482  
        if (concepts.contains(t) && (c = findAClass(mcDollar + "Concept")) != null)
483  
          o = dO = (DynamicObject) nuEmptyObject(c);
484  
        else
485  
          dO = new DynamicObject;
486  
        dO.className = className;
487  
        ifdef unstructure_debug
488  
          print("Made dynamic object " + t + " " + shortClassName(dO));
489  
        endifdef
490  
      }
491  
    } // end of pcall
492  
    
493  
    // Creating instance failed? Use DynamicObject
494  
    if (o == null && dO == null)
495  
      dO = new DynamicObject;
496  
    
497  
    // Save in references list early because contents of object
498  
    // might link back to main object
499  
    
500  
    if (refID >= 0)
501  
      refs.put(refID, o != null ? o : dO);
502  
    tokrefs.put(tokIndex, o != null ? o : dO);
503  
    
504  
    // NOW parse the fields!
505  
    
506  
    new /*Linked*/HashMap<S, O> fields; // no longer preserving order (why did we do this?)
507  
    O _o = o;
508  
    DynamicObject _dO = dO;
509  
    if (hasBracket) {
510  
      stack.add(r {
511  
        ifdef unstructure_debug
512  
          print("in object values, token: " + t());
513  
        endifdef
514  
        if (eq(t(), ",")) consume();
515  
        if (eq(t(), ")")) {
516  
          consume(")");
517  
          objRead(_o, _dO, fields, hasOuter);
518  
          out.set(_o != null ? _o : _dO);
519  
        } else {
520  
          final S key = unquote(tpp());
521  
          S t = tpp();
522  
          if (!eq(t, "="))
523  
            fail("= expected, got " + t + " after " + quote(key) + " in object " + thingName /*+ " " + sfu(fields)*/);
524  
          stack.add(this);
525  
          parse(new unstructure_Receiver {
526  
            void set(O value) {
527  
              fields.put(key, value);
528  
              /*ifdef unstructure_debug
529  
                print("Got field value " + value + ", next token: " + t());
530  
              endifdef*/
531  
              //if (eq(t(), ",")) consume();
532  
            }
533  
          });
534  
        }
535  
      });
536  
    } else {
537  
      objRead(o, dO, fields, hasOuter);
538  
      out.set(o != null ? o : dO);
539  
    }
540  
  }
541  
  
542  
  void objRead(O o, DynamicObject dO, MapSO fields, bool hasOuter) {
543  
    ifdef unstructure_debug
544  
    print("objRead " + className(o) + " " + className(dO) + " " + struct(fields));
545  
    endifdef
546  
    
547  
    // translate between diferent compilers (this$0 vs this$1)
548  
    O outer = fields.get("this$0");
549  
    if (outer != null) fields.put("this$1", outer);
550  
    else {
551  
      outer = fields.get("this$1");
552  
      if (outer != null) fields.put("this$0", outer);
553  
    }
554  
    
555  
    if (o != null) {
556  
      if (dO != null) {
557  
        ifdef unstructure_debug
558  
          printStructure("setOptAllDyn", fields);
559  
        endifdef
560  
        setOptAllDyn_pcall(dO, fields);
561  
      } else {
562  
        setOptAll_pcall(o, fields);
563  
        ifdef unstructure_debug
564  
          print("objRead now: " + struct(o));
565  
        endifdef
566  
      }
567  
      if (hasOuter)
568  
        fixOuterRefs(o);
569  
    } else for (Map.Entry<S, O> e : fields.entrySet())
570  
      setDynObjectValue(dO, intern(e.getKey()), e.getValue());
571  
572  
    if (o != null)
573  
      pcallOpt_noArgs(o, "_doneLoading");
574  
  }
575  
  
576  
  void parseSet(final Set set, final unstructure_Receiver out) {
577  
    this.parseList(new ArrayList, new unstructure_Receiver {
578  
      void set(O o) {
579  
        set.addAll((L) o);
580  
        out.set(set);
581  
      }
582  
    });
583  
  }
584  
  
585  
  void parseLisp(final unstructure_Receiver out) {
586  
    ifclass Lisp
587  
      consume("l");
588  
      consume("(");
589  
      final new ArrayList list;
590  
      stack.add(r {
591  
        if (eq(t(), ")")) {
592  
          consume(")");
593  
          out.set(Lisp((S) list.get(0), subList(list, 1)));
594  
        } else {
595  
          stack.add(this);
596  
          parse(new unstructure_Receiver {
597  
            void set(O o) {
598  
              list.add(o);
599  
              if (eq(t(), ",")) consume();
600  
            }
601  
          });
602  
        }
603  
      });
604  
      if (false) // skip fail line
605  
    endif
606  
    
607  
    fail("class Lisp not included");
608  
  }
609  
  
610  
  void parseBitSet(final unstructure_Receiver out) {
611  
    consume("bitset");
612  
    consume("{");
613  
    final new BitSet bs;
614  
    stack.add(r {
615  
      if (eq(t(), "}")) {
616  
        consume("}");
617  
        out.set(bs);
618  
      } else {
619  
        stack.add(this);
620  
        parse(new unstructure_Receiver {
621  
          void set(O o) {
622  
            bs.set((Integer) o);
623  
            if (eq(t(), ",")) consume();
624  
          }
625  
        });
626  
      }
627  
    });
628  
  }
629  
  
630  
  void parseList(final L list, final unstructure_Receiver out) {
631  
    tokrefs.put(i, list);
632  
    consume("[");
633  
    stack.add(r {
634  
      if (eq(t(), "]")) {
635  
        consume();
636  
        ifdef unstructure_debug
637  
          print("Consumed list, next token: " + t());
638  
        endifdef
639  
        out.set(list);
640  
      } else {
641  
        stack.add(this);
642  
        parse(new unstructure_Receiver {
643  
          void set(O o) {
644  
            //if (debug) print("List element type: " + getClassName(o));
645  
            list.add(o);
646  
            if (eq(t(), ",")) consume();
647  
          }
648  
        });
649  
      }
650  
    });
651  
  }
652  
  
653  
  void parseArray(unstructure_Receiver out) {
654  
    S _type = tpp();
655  
    int dims;
656  
657  
    if (eq(t(), "S")) { // string array
658  
      _type = "S";
659  
      consume();
660  
    }
661  
    
662  
    if (eq(t(), "/")) { // multi-dimensional array
663  
      consume();
664  
      dims = parseInt(tpp());
665  
    } else
666  
      dims = 1;
667  
    
668  
    consume("{");
669  
    List list = new ArrayList;
670  
    S type = _type;
671  
    
672  
    stack.add(r {
673  
      if (eq(t(), "}")) {
674  
        consume("}");
675  
        if (dims > 1) {
676  
          Class atype;
677  
          if (type.equals("intarray")) atype = int.class;
678  
          else if (type.equals("S")) atype = S.class;
679  
          else todo("multi-dimensional arrays of other types");
680  
          
681  
          out.set(list.toArray((O[]) newMultiDimensionalOuterArray(atype, dims, l(list))));
682  
        } else
683  
          out.set(
684  
            type.equals("intarray") ? toIntArray(list)
685  
            : type.equals("dblarray") ? toDoubleArray(list)
686  
            : type.equals("floatarray") ? toFloatArray(list)
687  
            : type.equals("S") ? toStringArray(list)
688  
            : list.toArray());
689  
      } else {
690  
        stack.add(this);
691  
        parse(new unstructure_Receiver {
692  
          void set(O o) {
693  
            list.add(o);
694  
            if (eq(t(), ",")) consume();
695  
          }
696  
        });
697  
      }
698  
    });
699  
  }
700  
  
701  
  Object parseClass() {
702  
    consume("class");
703  
    consume("(");
704  
    S name = unquote(tpp());
705  
    consume(")");
706  
    Class c = allDynamic ? null : findAClass(name);
707  
    if (c != null) ret c;
708  
    new DynamicObject dO;
709  
    dO.className = "java.lang.Class";
710  
    name = dropPrefix(mcDollar, name);
711  
    dynamicObject_setRawFieldValue(dO, +name);
712  
    ret dO;
713  
  }
714  
  
715  
  Object parseBigInt() {
716  
    consume("bigint");
717  
    consume("(");
718  
    S val = tpp();
719  
    if (eq(val, "-"))
720  
      val = "-" + tpp();
721  
    consume(")");
722  
    ret new BigInteger(val);
723  
  }
724  
  
725  
  Object parseDouble() {
726  
    consume("d");
727  
    consume("(");
728  
    S val = unquote(tpp());
729  
    consume(")");
730  
    ret Double.parseDouble(val);
731  
  }
732  
  
733  
  Object parseFloat() {
734  
    consume("fl");
735  
    S val;
736  
    if (eq(t(), "(")) {
737  
      consume("(");
738  
      val = unquote(tpp());
739  
      consume(")");
740  
    } else {
741  
      val = unquote(tpp());
742  
    }
743  
    ret Float.parseFloat(val);
744  
  }
745  
  
746  
  void parseHashSet(unstructure_Receiver out) {
747  
    consume("hashset");
748  
    parseSet(new HashSet, out);
749  
  }
750  
  
751  
  void parseLinkedHashSet(unstructure_Receiver out) {
752  
    consume("lhs");
753  
    parseSet(new LinkedHashSet, out);
754  
  }
755  
  
756  
  void parseTreeSet(unstructure_Receiver out) {
757  
    consume("treeset");
758  
    parseSet(new TreeSet, out);
759  
  }
760  
  
761  
  void parseCISet(unstructure_Receiver out) {
762  
    consume("ciset");
763  
    parseSet(ciSet(), out);
764  
  }
765  
  
766  
  void parseMap(unstructure_Receiver out) {
767  
    parseMap(new TreeMap, out);
768  
  }
769  
  
770  
  O parseJava() {
771  
    S j = unquote(tpp());
772  
    new Matches m;
773  
    if (jmatch("java.awt.Color[r=*,g=*,b=*]", j, m))
774  
      ret nuObject("java.awt.Color", parseInt($1), parseInt($2), parseInt($3));
775  
    else {
776  
      warn("Unknown Java object: " + j);
777  
      null;
778  
    }
779  
  }
780  
  
781  
  void parseMap(final Map map, final unstructure_Receiver out) {
782  
    consume("{");
783  
    stack.add(new Runnable {
784  
      bool v;
785  
      O key;
786  
      
787  
      public void run() { 
788  
        if (v) {
789  
          v = false;
790  
          stack.add(this);
791  
          if (!eq(tpp(), "="))
792  
            fail("= expected, got " + t() + " in map of size " + l(map));
793  
794  
          parse(new unstructure_Receiver {
795  
            void set(O value) {
796  
              map.put(key, value);
797  
              ifdef unstructure_debug
798  
                print("parseMap: Got value " + getClassName(value) + ", next token: " + quote(t()));
799  
              endifdef
800  
              if (eq(t(), ",")) consume();
801  
            }
802  
          });
803  
        } else {
804  
          if (eq(t(), "}")) {
805  
            consume("}");
806  
            out.set(map);
807  
          } else {
808  
            v = true;
809  
            stack.add(this);
810  
            parse(new unstructure_Receiver {
811  
              void set(O o) {
812  
                key = o;
813  
              }
814  
            });
815  
          }
816  
        } // if v else
817  
      } // run()
818  
    });
819  
  }
820  
  
821  
  /*void parseSub(unstructure_Receiver out) {
822  
    int n = l(stack);
823  
    parse(out);
824  
    while (l(stack) > n)
825  
      stack
826  
  }*/
827  
  
828  
  void consume() { curT = tok.next(); ++i; }
829  
  
830  
  void consume(S s) {
831  
    if (!eq(t(), s)) {
832  
      /*S prevToken = i-1 >= 0 ? tok.get(i-1) : "";
833  
      S nextTokens = join(tok.subList(i, Math.min(i+2, tok.size())));
834  
      fail(quote(s) + " expected: " + prevToken + " " + nextTokens + " (" + i + "/" + tok.size() + ")");*/
835  
      fail(quote(s) + " expected, got " + quote(t()));
836  
    }
837  
    consume();
838  
  }
839  
  
840  
  // outer wrapper function getting first token and unwinding the stack
841  
  void parse_initial(unstructure_Receiver out) {
842  
    consume(); // get first token
843  
    parse(out);
844  
    while (nempty(stack))
845  
      popLast(stack).run();
846  
  }
847  
}
848  
849  
sO unstructure_tok(Producer<S> tok, bool allDynamic, O classFinder) {
850  
  bool debug = unstructure_debug;
851  
  temp tempSetTL(dynamicObjectIsLoading_threadLocal(), true);
852  
  new Var v;
853  
  var unstructurer = new Unstructurer()
854  
    .tok(tok)
855  
    .allDynamic(allDynamic)
856  
    .classFinder(classFinder);
857  
  unstructurer.parse_initial(new unstructure_Receiver {
858  
    void set(O o) { v.set(o); }
859  
  });
860  
  unstructure_tokrefs = unstructurer.tokrefs.size();
861  
  ret v!;
862  
}
863  
864  
static boolean unstructure_debug;

Author comment

Began life as a copy of #1035484

download  show line numbers  debug dex  old transpilations   

Travelled to 1 computer(s): mqqgnosmbjvj

No comments. add comment

Snippet ID: #1035798
Snippet name: unstructure (v20, introducing the Unstructurer class, LIVE)
Eternal ID of this version: #1035798/12
Text MD5: c922d06d23970887ad522d3f99d34836
Author: stefan
Category: javax
Type: JavaX fragment (include)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2023-03-20 20:54:33
Source code size: 24347 bytes / 864 lines
Pitched / IR pitched: No / No
Views / Downloads: 150 / 198
Version history: 11 change(s)
Referenced in: [show references]