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

655
LINES

< > BotCompany Repo | #1024869 // unstructure (v13, with custom serialization)

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

Libraryless. Click here for Pure Java version (4412L/27K).

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")) {
215  
          consume();
216  
          ret with parseList(synchroLinkedList(), out);
217  
        }
218  
219  
        if (t.equals("sync")) {
220  
          consume();
221  
          if (t().equals("tm")) {
222  
            consume();
223  
            ret with parseMap(synchronizedTreeMap(), out);
224  
          }
225  
          if (t().equals("["))
226  
            ret with parseList(synchroList(), out);
227  
          ret with parseMap(synchronizedMap(), out);
228  
        }
229  
        if (t.equals("{")) {
230  
          parseMap(out); ret;
231  
        }
232  
        if (t.equals("[")) {
233  
          this.parseList(new ArrayList, out); ret;
234  
        }
235  
        if (t.equals("bitset")) {
236  
          parseBitSet(out); ret;
237  
        }
238  
        if (t.equals("array") || t.equals("intarray")) {
239  
          parseArray(out); ret;
240  
        }
241  
        if (t.equals("ba")) {
242  
          consume();
243  
          S hex = unquote(tpp());
244  
          out.set(hexToBytes(hex)); ret;
245  
        }
246  
        if (t.equals("boolarray")) {
247  
          consume();
248  
          int n = parseInt(tpp());
249  
          S hex = unquote(tpp());
250  
          out.set(boolArrayFromBytes(hexToBytes(hex), n)); ret;
251  
        }
252  
        if (t.equals("class")) {
253  
          out.set(parseClass()); ret;
254  
        }
255  
        if (t.equals("l")) {
256  
          parseLisp(out); ret;
257  
        }
258  
        if (t.equals("null")) {
259  
          consume(); out.set(null); ret;
260  
        }
261  
        
262  
        if (eq(t, "c")) {
263  
          consume();
264  
          t = t();
265  
          assertTrue(isJavaIdentifier(t));
266  
          concepts.add(t);
267  
        }
268  
        
269  
        // custom deserialization
270  
        if (eq(t, "cu")) {
271  
          consume();
272  
          t = tpp();
273  
          assertTrue(isJavaIdentifier(t));
274  
          S fullClassName = "main$" + t;
275  
          c = classFinder != null ? (Class) callF(classFinder, fullClassName) : findClass_fullName(fullClassName);
276  
          if (c == null) fail("Class not found: " + fullClassName);
277  
          O o = nuEmptyObject(c);
278  
          out.set(o);
279  
          parse(new unstructure_Receiver {
280  
            void set(O value) {
281  
              call(o, "_deserialize", value);
282  
            }
283  
          });
284  
          ret;
285  
        }
286  
      }
287  
      
288  
      if (eq(t, "j")) {
289  
        consume("j");
290  
        out.set(parseJava()); ret;
291  
      }
292  
293  
      if (c == null && !isJavaIdentifier(t))
294  
        throw new RuntimeException("Unknown token " + (i+1) + ": " + t);
295  
        
296  
      // any other class name (or package name)
297  
      consume();
298  
      S className, fullClassName;
299  
      
300  
      // Is it a package name?
301  
      if (eq(t(), ".")) {
302  
        consume();
303  
        className = fullClassName = t + "." + assertIdentifier(tpp());
304  
      } else {
305  
        className = t;
306  
        fullClassName = "main$" + t;
307  
      }
308  
      
309  
      if (c == null) {
310  
        // First, find class
311  
        if (allDynamic) c = null;
312  
        else c = classFinder != null ? (Class) callF(classFinder, fullClassName) : findClass_fullName(fullClassName);
313  
        if (c != null)
314  
          classesMap.put(className, c);
315  
      }
316  
          
317  
      // Check if it has an outer reference
318  
      bool hasBracket = eq(t(), "(");
319  
      if (hasBracket) consume();
320  
      bool hasOuter = hasBracket && eq(t(), "this$1");
321  
      
322  
      DynamicObject dO = null;
323  
      O o = null;
324  
      fS thingName = t;
325  
      if (c != null) {
326  
        o = hasOuter ? nuStubInnerObject(c, classFinder) : nuEmptyObject(c);
327  
        if (o instanceof DynamicObject) dO = (DynamicObject) o;
328  
      } else {
329  
        if (concepts.contains(t) && (c = findClass("Concept")) != null)
330  
          o = dO = (DynamicObject) nuEmptyObject(c);
331  
        else
332  
          dO = new DynamicObject;
333  
        dO.className = className;
334  
        ifdef unstructure_debug
335  
          print("Made dynamic object " + t + " " + shortClassName(dO));
336  
        endifdef
337  
      }
338  
      
339  
      // Save in references list early because contents of object
340  
      // might link back to main object
341  
      
342  
      if (refID != 0)
343  
        refs.put(refID, o != null ? o : dO);
344  
      tokrefs.put(tokIndex, o != null ? o : dO);
345  
      
346  
      // NOW parse the fields!
347  
      
348  
      final new LinkedHashMap<S, O> fields; // preserve order
349  
      final O _o = o;
350  
      final DynamicObject _dO = dO;
351  
      if (hasBracket) {
352  
        stack.add(r {
353  
          if (eq(t(), ")")) {
354  
            consume(")");
355  
            objRead(_o, _dO, fields);
356  
            out.set(_o != null ? _o : _dO);
357  
          } else {
358  
            final S key = unquote(tpp());
359  
            if (!eq(tpp(), "="))
360  
              fail("= expected, got " + t() + " after " + quote(key) + " in object " + thingName /*+ " " + sfu(fields)*/);
361  
            stack.add(this);
362  
            parse(new unstructure_Receiver {
363  
              void set(O value) {
364  
                fields.put(key, value);
365  
                if (eq(t(), ",")) consume();
366  
              }
367  
            });
368  
          }
369  
        });
370  
      } else {
371  
        objRead(o, dO, fields);
372  
        out.set(o != null ? o : dO);
373  
      }
374  
    }
375  
    
376  
    void objRead(O o, DynamicObject dO, Map<S, O> fields) {
377  
      ifdef unstructure_debug
378  
      print("objRead " + className(o) + " " + className(dO) + " " + struct(fields));
379  
      endifdef
380  
      if (o != null)
381  
        if (dO != null) {
382  
          ifdef unstructure_debug
383  
            printStructure("setOptAllDyn", fields);
384  
          endifdef
385  
          setOptAllDyn(dO, fields);
386  
        } else {
387  
          setOptAll_pcall(o, fields);
388  
          ifdef unstructure_debug
389  
            print("objRead now: " + struct(o));
390  
          endifdef
391  
        }
392  
      else for (Map.Entry<S, O> e : fields.entrySet())
393  
        setDynObjectValue(dO, intern(e.getKey()), e.getValue());
394  
395  
      if (o != null)
396  
        pcallOpt_noArgs(o, "_doneLoading");
397  
    }
398  
    
399  
    void parseSet(final Set set, final unstructure_Receiver out) {
400  
      this.parseList(new ArrayList, new unstructure_Receiver {
401  
        void set(O o) {
402  
          set.addAll((L) o);
403  
          out.set(set);
404  
        }
405  
      });
406  
    }
407  
    
408  
    void parseLisp(final unstructure_Receiver out) {
409  
      ifclass Lisp
410  
        consume("l");
411  
        consume("(");
412  
        final new ArrayList list;
413  
        stack.add(r {
414  
          if (eq(t(), ")")) {
415  
            consume(")");
416  
            out.set(Lisp((S) list.get(0), subList(list, 1)));
417  
          } else {
418  
            stack.add(this);
419  
            parse(new unstructure_Receiver {
420  
              void set(O o) {
421  
                list.add(o);
422  
                if (eq(t(), ",")) consume();
423  
              }
424  
            });
425  
          }
426  
        });
427  
        if (false) // skip fail line
428  
      endif
429  
      
430  
      fail("class Lisp not included");
431  
    }
432  
    
433  
    void parseBitSet(final unstructure_Receiver out) {
434  
      consume("bitset");
435  
      consume("{");
436  
      final new BitSet bs;
437  
      stack.add(r {
438  
        if (eq(t(), "}")) {
439  
          consume("}");
440  
          out.set(bs);
441  
        } else {
442  
          stack.add(this);
443  
          parse(new unstructure_Receiver {
444  
            void set(O o) {
445  
              bs.set((Integer) o);
446  
              if (eq(t(), ",")) consume();
447  
            }
448  
          });
449  
        }
450  
      });
451  
    }
452  
    
453  
    void parseList(final L list, final unstructure_Receiver out) {
454  
      consume("[");
455  
      stack.add(r {
456  
        if (eq(t(), "]")) {
457  
          consume("]");
458  
          out.set(list);
459  
        } else {
460  
          stack.add(this);
461  
          parse(new unstructure_Receiver {
462  
            void set(O o) {
463  
              //if (debug) print("List element type: " + getClassName(o));
464  
              list.add(o);
465  
              if (eq(t(), ",")) consume();
466  
            }
467  
          });
468  
        }
469  
      });
470  
    }
471  
    
472  
    void parseArray(final unstructure_Receiver out) {
473  
      final S type = tpp();
474  
      consume("{");
475  
      final List list = new ArrayList;
476  
      
477  
      stack.add(r {
478  
        if (eq(t(), "}")) {
479  
          consume("}");
480  
          out.set(type.equals("intarray") ? toIntArray(list) : list.toArray());
481  
        } else {
482  
          stack.add(this);
483  
          parse(new unstructure_Receiver {
484  
            void set(O o) {
485  
              list.add(o);
486  
              if (eq(t(), ",")) consume();
487  
            }
488  
          });
489  
        }
490  
      });
491  
    }
492  
    
493  
    Object parseClass() {
494  
      consume("class");
495  
      consume("(");
496  
      S name = unquote(tpp());
497  
      consume(")");
498  
      Class c = allDynamic ? null : classFinder != null ? (Class) callF(classFinder, name) : findClass_fullName(name);
499  
      if (c != null) ret c;
500  
      new DynamicObject dO;
501  
      dO.className = "java.lang.Class";
502  
      name = dropPrefix("main$", name);
503  
      dO.fieldValues.put("name", name);
504  
      ret dO;
505  
    }
506  
    
507  
    Object parseBigInt() {
508  
      consume("bigint");
509  
      consume("(");
510  
      S val = tpp();
511  
      if (eq(val, "-"))
512  
        val = "-" + tpp();
513  
      consume(")");
514  
      ret new BigInteger(val);
515  
    }
516  
    
517  
    Object parseDouble() {
518  
      consume("d");
519  
      consume("(");
520  
      S val = unquote(tpp());
521  
      consume(")");
522  
      ret Double.parseDouble(val);
523  
    }
524  
    
525  
    Object parseFloat() {
526  
      consume("fl");
527  
      S val;
528  
      if (eq(t(), "(")) {
529  
        consume("(");
530  
        val = unquote(tpp());
531  
        consume(")");
532  
      } else {
533  
        val = unquote(tpp());
534  
      }
535  
      ret Float.parseFloat(val);
536  
    }
537  
    
538  
    void parseHashSet(unstructure_Receiver out) {
539  
      consume("hashset");
540  
      parseSet(new HashSet, out);
541  
    }
542  
    
543  
    void parseLinkedHashSet(unstructure_Receiver out) {
544  
      consume("lhs");
545  
      parseSet(new LinkedHashSet, out);
546  
    }
547  
    
548  
    void parseTreeSet(unstructure_Receiver out) {
549  
      consume("treeset");
550  
      parseSet(new TreeSet, out);
551  
    }
552  
    
553  
    void parseCISet(unstructure_Receiver out) {
554  
      consume("ciset");
555  
      parseSet(ciSet(), out);
556  
    }
557  
    
558  
    void parseMap(unstructure_Receiver out) {
559  
      parseMap(new TreeMap, out);
560  
    }
561  
    
562  
    O parseJava() {
563  
      S j = unquote(tpp());
564  
      new Matches m;
565  
      if (jmatch("java.awt.Color[r=*,g=*,b=*]", j, m))
566  
        ret nuObject("java.awt.Color", parseInt($1), parseInt($2), parseInt($3));
567  
      else {
568  
        warn("Unknown Java object: " + j);
569  
        null;
570  
      }
571  
    }
572  
    
573  
    void parseMap(final Map map, final unstructure_Receiver out) {
574  
      consume("{");
575  
      stack.add(new Runnable {
576  
        bool v;
577  
        O key;
578  
        
579  
        public void run() { 
580  
          if (v) {
581  
            v = false;
582  
            stack.add(this);
583  
            if (!eq(tpp(), "="))
584  
              fail("= expected, got " + t() + " in map of size " + l(map));
585  
586  
            parse(new unstructure_Receiver {
587  
              void set(O value) {
588  
                map.put(key, value);
589  
                ifdef unstructure_debug
590  
                  print("parseMap: Got value " + getClassName(value) + ", next token: " + quote(t()));
591  
                endifdef
592  
                if (eq(t(), ",")) consume();
593  
              }
594  
            });
595  
          } else {
596  
            if (eq(t(), "}")) {
597  
              consume("}");
598  
              out.set(map);
599  
            } else {
600  
              v = true;
601  
              stack.add(this);
602  
              parse(new unstructure_Receiver {
603  
                void set(O o) {
604  
                  key = o;
605  
                }
606  
              });
607  
            }
608  
          } // if v else
609  
        } // run()
610  
      });
611  
    }
612  
    
613  
    /*void parseSub(unstructure_Receiver out) {
614  
      int n = l(stack);
615  
      parse(out);
616  
      while (l(stack) > n)
617  
        stack
618  
    }*/
619  
    
620  
    void consume() { curT = tok.next(); ++i; }
621  
    
622  
    void consume(S s) {
623  
      if (!eq(t(), s)) {
624  
        /*S prevToken = i-1 >= 0 ? tok.get(i-1) : "";
625  
        S nextTokens = join(tok.subList(i, Math.min(i+2, tok.size())));
626  
        fail(quote(s) + " expected: " + prevToken + " " + nextTokens + " (" + i + "/" + tok.size() + ")");*/
627  
        fail(quote(s) + " expected, got " + quote(t()));
628  
      }
629  
      consume();
630  
    }
631  
    
632  
    void parse_x(unstructure_Receiver out) {
633  
      consume(); // get first token
634  
      parse(out);
635  
      while (nempty(stack))
636  
        popLast(stack).run();
637  
    }
638  
  }
639  
  
640  
  Bool b = DynamicObject_loading!;
641  
  DynamicObject_loading.set(true);
642  
  try {
643  
    final new Var v;
644  
    new X x;
645  
    x.parse_x(new unstructure_Receiver {
646  
      void set(O o) { v.set(o); }
647  
    });
648  
    unstructure_tokrefs = x.tokrefs.size();
649  
    ret v.get();
650  
  } finally {
651  
    DynamicObject_loading.set(b);
652  
  }
653  
}
654  
655  
static boolean unstructure_debug;

Author comment

Began life as a copy of #1020754

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: #1024869
Snippet name: unstructure (v13, with custom serialization)
Eternal ID of this version: #1024869/8
Text MD5: a8b25b5081794630c6a6df8550b9d820
Transpilation MD5: 508b5140cc5f308027e5f73cad5897b1
Author: stefan
Category: javax
Type: JavaX fragment (include)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2019-08-28 12:35:42
Source code size: 19117 bytes / 655 lines
Pitched / IR pitched: No / No
Views / Downloads: 171 / 260
Version history: 7 change(s)
Referenced in: [show references]