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

777
LINES

< > BotCompany Repo | #1031746 // unstructure (v18, with compact maps & public X class, dev.)

JavaX fragment (include)

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

Author comment

Began life as a copy of #1030946

download  show line numbers  debug dex  old transpilations   

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

No comments. add comment

Snippet ID: #1031746
Snippet name: unstructure (v18, with compact maps & public X class, dev.)
Eternal ID of this version: #1031746/3
Text MD5: a7be0a036fee6984db4537cacf7ea342
Author: stefan
Category: javax
Type: JavaX fragment (include)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2021-06-29 04:08:48
Source code size: 23294 bytes / 777 lines
Pitched / IR pitched: No / No
Views / Downloads: 135 / 153
Version history: 2 change(s)
Referenced in: [show references]