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

637
LINES

< > BotCompany Repo | #1020754 // unstructure (v12, with packages)

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

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

Author comment

Began life as a copy of #1005980

download  show line numbers  debug dex  old transpilations   

Travelled to 10 computer(s): bhatertpkbcr, cfunsshuasjs, gwrvuhgaqvyk, mqqgnosmbjvj, pyentgdyhuwx, pzhvpgtvlbxg, tvejysmllsmz, vouqrxazstgt, whxojlpjdney, yanjaxplzisb

No comments. add comment

Snippet ID: #1020754
Snippet name: unstructure (v12, with packages)
Eternal ID of this version: #1020754/20
Text MD5: 127a995ef91d3d7765425c36954f58d3
Transpilation MD5: a05c32bcdbe3568605cd1ba2dc585d96
Author: stefan
Category: javax
Type: JavaX fragment (include)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2019-08-27 22:34:10
Source code size: 18493 bytes / 637 lines
Pitched / IR pitched: No / No
Views / Downloads: 253 / 464
Version history: 19 change(s)
Referenced in: [show references]