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

848
LINES

< > BotCompany Repo | #1035484 // unstructure (v19, LIVE)

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

Libraryless. Click here for Pure Java version (11836L/67K).

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

Author comment

Began life as a copy of #1034649

download  show line numbers  debug dex  old transpilations   

Travelled to 2 computer(s): mowyntqkapby, mqqgnosmbjvj

No comments. add comment

Snippet ID: #1035484
Snippet name: unstructure (v19, LIVE)
Eternal ID of this version: #1035484/4
Text MD5: a48da68b32e358f26d4c119f022b0ab2
Transpilation MD5: b2cf123a4dde8763bc74e600bb02a5cb
Author: stefan
Category: javax
Type: JavaX fragment (include)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2022-07-29 20:02:33
Source code size: 25342 bytes / 848 lines
Pitched / IR pitched: No / No
Views / Downloads: 75 / 98
Version history: 3 change(s)
Referenced in: [show references]