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

680
LINES

< > BotCompany Repo | #1024877 // unstructure (v14, better sync maps)

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

Libraryless. Click here for Pure Java version (4677L/29K).

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

Author comment

Began life as a copy of #1024869

download  show line numbers  debug dex  old transpilations   

Travelled to 6 computer(s): bhatertpkbcr, mqqgnosmbjvj, pyentgdyhuwx, pzhvpgtvlbxg, tvejysmllsmz, vouqrxazstgt

No comments. add comment

Snippet ID: #1024877
Snippet name: unstructure (v14, better sync maps)
Eternal ID of this version: #1024877/15
Text MD5: 10fcf0318cacd6ba02f144f9b609efee
Transpilation MD5: 990d76c485b5408ab9dd46ace471e808
Author: stefan
Category: javax
Type: JavaX fragment (include)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2019-09-14 16:59:36
Source code size: 20299 bytes / 680 lines
Pitched / IR pitched: No / No
Views / Downloads: 338 / 495
Version history: 14 change(s)
Referenced in: [show references]