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

802
LINES

< > BotCompany Repo | #1030946 // unstructure (v17, with base classes)

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

Transpiled version (7164L) is out of date.

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

Author comment

Began life as a copy of #1025231

download  show line numbers  debug dex  old transpilations   

Travelled to 4 computer(s): bhatertpkbcr, mqqgnosmbjvj, pyentgdyhuwx, vouqrxazstgt

No comments. add comment

Snippet ID: #1030946
Snippet name: unstructure (v17, with base classes)
Eternal ID of this version: #1030946/40
Text MD5: d43545385b373a29041ae7f5e340d757
Author: stefan
Category: javax
Type: JavaX fragment (include)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2022-02-28 18:45:15
Source code size: 24079 bytes / 802 lines
Pitched / IR pitched: No / No
Views / Downloads: 282 / 513
Version history: 39 change(s)
Referenced in: [show references]