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

498
LINES

< > BotCompany Repo | #1005973 // unstructure (v9, working virtual stack)

JavaX fragment (include)

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  
11  
abstract sclass unstructure_Receiver {
12  
  abstract void set(O o);
13  
}
14  
15  
// classFinder: func(name) -> class (optional)
16  
static Object unstructure(String text, boolean allDynamic,
17  
  O classFinder) {
18  
  if (text == null) ret null;
19  
  final L<S> tok = javaTokC(text);
20  
  ret unstructure_tok(tok, allDynamic, classFinder);
21  
}
22  
23  
// so text can be freed
24  
static Object unstructure_tempVar(Var<S> text) {
25  
  L<S> tok = javaTokC(text.get());
26  
  text.clear();
27  
  ret unstructure_tok(tok, false, null);
28  
}
29  
30  
static O unstructure_tok(final L<S> tok, final boolean allDynamic, final O classFinder) {
31  
  final boolean debug = unstructure_debug;
32  
  
33  
  class X {
34  
    int i = 0;
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  
41  
    void parse(final unstructure_Receiver out) {
42  
      S t = tok.get(i);
43  
      
44  
      int refID = 0;
45  
      if (structure_isMarker(t, 0, l(t))) {
46  
        refID = parseInt(t.substring(1));
47  
        i++;
48  
      }
49  
      final int _refID = refID;
50  
      
51  
      // if (debug) print("parse: " + quote(t));
52  
      
53  
      final int tokIndex = i;  
54  
      parse_inner(refID, tokIndex, new unstructure_Receiver {
55  
        void set(O o) {
56  
          if (_refID != 0)
57  
            refs.put(_refID, o);
58  
          if (o != null)
59  
            tokrefs.put(tokIndex, o);
60  
          out.set(o);
61  
        }
62  
      });
63  
    }
64  
    
65  
    void parse_inner(int refID, int tokIndex, final unstructure_Receiver out) {
66  
      S t = tok.get(i);
67  
      
68  
      // if (debug) print("parse_inner: " + quote(t));
69  
      
70  
      Class c = classesMap.get(t);
71  
      if (c == null) {
72  
        if (t.startsWith("\"")) {
73  
          S s = internIfLongerThan(unquote(tok.get(i)), structure_internStringsLongerThan);
74  
          i++;
75  
          out.set(s); ret;
76  
        }
77  
        
78  
        if (t.startsWith("'")) {
79  
          out.set(unquoteCharacter(tok.get(i++))); ret;
80  
        }
81  
        if (t.equals("bigint")) {
82  
          out.set(parseBigInt()); ret;
83  
        }
84  
        if (t.equals("d")) {
85  
          out.set(parseDouble()); ret;
86  
        }
87  
        if (t.equals("fl")) {
88  
          out.set(parseFloat()); ret;
89  
        }
90  
        if (t.equals("false") || t.equals("f")) {
91  
          i++; out.set(false); ret;
92  
        }
93  
        if (t.equals("true") || t.equals("t")) {
94  
          i++; out.set(true); ret;
95  
        }
96  
        if (t.equals("-")) {
97  
          t = tok.get(i+1);
98  
          i += 2;
99  
          out.set(isLongConstant(t) ? (O) (-parseLong(t)) : (O) (-parseInt(t))); ret;
100  
        }
101  
        if (isInteger(t) || isLongConstant(t)) {
102  
          i++;
103  
          //if (debug) print("isLongConstant " + quote(t) + " => " + isLongConstant(t));
104  
          if (isLongConstant(t)) {
105  
            out.set(parseLong(t)); ret;
106  
          }
107  
          long l = parseLong(t);
108  
          bool isInt = l == (int) l;
109  
          if (debug)
110  
            print("l=" + l + ", isInt: " + isInt);
111  
          out.set(isInt ? (O) new Integer((int) l) : (O) new Long(l)); ret;
112  
        }
113  
        
114  
        if (t.equals("File")) {
115  
          File f = new File(unquote(tok.get(i+1)));
116  
          i += 2;
117  
          out.set(f); ret;
118  
        }
119  
        
120  
        if (t.startsWith("r") && isInteger(t.substring(1))) {
121  
          i++;
122  
          int ref = Integer.parseInt(t.substring(1));
123  
          O o = refs.get(ref);
124  
          if (o == null)
125  
            print("Warning: unsatisfied back reference " + ref);
126  
          out.set(o); ret;
127  
        }
128  
      
129  
        if (t.startsWith("t") && isInteger(t.substring(1))) {
130  
          i++;
131  
          int ref = Integer.parseInt(t.substring(1));
132  
          O o = tokrefs.get(ref);
133  
          if (o == null)
134  
            print("Warning: unsatisfied token reference " + ref);
135  
          out.set(o); ret;
136  
        }
137  
        
138  
        if (t.equals("hashset")) {
139  
          parseHashSet(out); ret;
140  
        }
141  
        if (t.equals("treeset")) {
142  
          parseTreeSet(out); ret;
143  
        }
144  
        if (eqOneOf(t, "hashmap", "hm")) {
145  
          parseHashMap(out); ret;
146  
        }
147  
        if (t.equals("{")) {
148  
          parseMap(out); ret;
149  
        }
150  
        if (t.equals("[")) {
151  
          parseList(out); ret;
152  
        }
153  
        if (t.equals("bitset")) {
154  
          parseBitSet(out); ret;
155  
        }
156  
        if (t.equals("array") || t.equals("intarray")) {
157  
          parseArray(out); ret;
158  
        }
159  
        if (t.equals("ba")) {
160  
          S hex = unquote(tok.get(i+1));
161  
          i += 2;
162  
          out.set(hexToBytes(hex)); ret;
163  
        }
164  
        if (t.equals("boolarray")) {
165  
          int n = parseInt(tok.get(i+1));
166  
          S hex = unquote(tok.get(i+2));
167  
          i += 6;
168  
          out.set(boolArrayFromBytes(hexToBytes(hex), n)); ret;
169  
        }
170  
        if (t.equals("class")) {
171  
          out.set(parseClass()); ret;
172  
        }
173  
        if (t.equals("l")) {
174  
          parseLisp(out); ret;
175  
        }
176  
        if (t.equals("null")) {
177  
          i++; out.set(null); ret;
178  
        }
179  
        
180  
        if (eq(t, "c")) {
181  
          consume("c");
182  
          t = tok.get(i);
183  
          assertTrue(isJavaIdentifier(t));
184  
          concepts.add(t);
185  
        }
186  
      }
187  
      
188  
      if (c == null && !isJavaIdentifier(t))
189  
        throw new RuntimeException("Unknown token " + (i+1) + ": " + t);
190  
191  
      // any other class name
192  
      if (c == null) {
193  
        // First, find class
194  
        if (allDynamic) c = null;
195  
        else if (classFinder != null)
196  
          c = (Class) callF(classFinder, t);
197  
        else
198  
          c = findClass(t);
199  
        if (c != null)
200  
          classesMap.put(t, c);
201  
      }
202  
          
203  
      // Check if it has an outer reference
204  
      i++;
205  
      bool hasOuter = eq(get(tok, i), "(") && eq(get(tok, i+1), "this$1");
206  
      
207  
      DynamicObject dO = null;
208  
      O o = null;
209  
      if (c != null)
210  
        o = hasOuter ? nuStubInnerObject(c) : nuEmptyObject(c);
211  
      else {
212  
        if (concepts.contains(t) && (c = findClass("Concept")) != null)
213  
          o = dO = (DynamicObject) nuEmptyObject(c);
214  
        else
215  
          dO = new DynamicObject;
216  
        dO.className = t;
217  
        if (debug) print("Made dynamic object " + t + " " + shortClassName(dO));
218  
      }
219  
      
220  
      // Save in references list early because contents of object
221  
      // might link back to main object
222  
      
223  
      if (refID != 0)
224  
        refs.put(refID, o != null ? o : dO);
225  
      tokrefs.put(tokIndex, o != null ? o : dO);
226  
      
227  
      // NOW parse the fields!
228  
      
229  
      final new HashMap<S, O> fields;
230  
      final O _o = o;
231  
      final DynamicObject _dO = dO;
232  
      if (i < tok.size() && tok.get(i).equals("(")) {
233  
        consume("(");
234  
        stack.add(r {
235  
          if (tok.get(i).equals(")")) {
236  
            consume(")");
237  
            objRead(_o, _dO, fields);
238  
            out.set(_o != null ? _o : _dO);
239  
          } else {
240  
            final S key = unquote(tok.get(i++));
241  
            consume("=");
242  
            stack.add(this);
243  
            parse(new unstructure_Receiver {
244  
              void set(O value) {
245  
                fields.put(key, value);
246  
                if (tok.get(i).equals(",")) i++;
247  
              }
248  
            });
249  
          }
250  
        });
251  
      } else
252  
        objRead(o, dO, fields);
253  
    }
254  
    
255  
    void objRead(O o, DynamicObject dO, Map<S, O> fields) {
256  
      if (o != null)
257  
        if (dO != null) {
258  
          if (debug)
259  
            printStructure("setOptAllDyn", fields);
260  
          setOptAllDyn(dO, fields);
261  
        } else
262  
          setOptAll(o, fields);
263  
      else for (S field : keys(fields))
264  
        dO.fieldValues.put(field.intern(), fields.get(field));
265  
266  
      if (o != null)
267  
        pcallOpt_noArgs(o, "_doneLoading");
268  
    }
269  
    
270  
    void parseSet(final Set set, final unstructure_Receiver out) {
271  
      parseList(new unstructure_Receiver {
272  
        void set(O o) {
273  
          set.addAll((L) o);
274  
          out.set(set);
275  
        }
276  
      });
277  
    }
278  
    
279  
    void parseLisp(final unstructure_Receiver out) {
280  
      consume("l");
281  
      consume("(");
282  
      final new ArrayList list;
283  
      stack.add(r {
284  
        if (tok.get(i).equals(")")) {
285  
          consume(")");
286  
          out.set(newObject("main$Lisp", (S) list.get(0), subList(list, 1)));
287  
        } else {
288  
          stack.add(this);
289  
          parse(new unstructure_Receiver {
290  
            void set(O o) {
291  
              list.add(o);
292  
              if (tok.get(i).equals(",")) i++;
293  
            }
294  
          });
295  
        }
296  
      });
297  
    }
298  
    
299  
    void parseBitSet(final unstructure_Receiver out) {
300  
      consume("bitset");
301  
      consume("{");
302  
      final new BitSet bs;
303  
      stack.add(r {
304  
        if (tok.get(i).equals("}")) {
305  
          consume("}");
306  
          out.set(bs);
307  
        } else {
308  
          stack.add(this);
309  
          parse(new unstructure_Receiver {
310  
            void set(O o) {
311  
              bs.set((Integer) o);
312  
              if (tok.get(i).equals(",")) i++;
313  
            }
314  
          });
315  
        }
316  
      });
317  
    }
318  
    
319  
    void parseList(final unstructure_Receiver out) {
320  
      consume("[");
321  
      final new ArrayList list;
322  
      stack.add(r {
323  
        if (tok.get(i).equals("]")) {
324  
          consume("]");
325  
          out.set(list);
326  
        } else {
327  
          stack.add(this);
328  
          parse(new unstructure_Receiver {
329  
            void set(O o) {
330  
              //if (debug) print("List element type: " + getClassName(o));
331  
              list.add(o);
332  
              if (tok.get(i).equals(",")) i++;
333  
            }
334  
          });
335  
        }
336  
      });
337  
    }
338  
    
339  
    void parseArray(final unstructure_Receiver out) {
340  
      final S type = tok.get(i);
341  
      i++;
342  
      consume("{");
343  
      final List list = new ArrayList;
344  
      
345  
      stack.add(r {
346  
        if (tok.get(i).equals("}")) {
347  
          consume("}");
348  
          out.set(type.equals("intarray") ? toIntArray(list) : list.toArray());
349  
        } else {
350  
          stack.add(this);
351  
          parse(new unstructure_Receiver {
352  
            void set(O o) {
353  
              list.add(o);
354  
              if (tok.get(i).equals(",")) i++;
355  
            }
356  
          });
357  
        }
358  
      });
359  
    }
360  
    
361  
    Object parseClass() {
362  
      consume("class");
363  
      consume("(");
364  
      S name = tok.get(i);
365  
      i++;
366  
      consume(")");
367  
      Class c = allDynamic ? null : findClass(name);
368  
      if (c != null) ret c;
369  
      new DynamicObject dO;
370  
      dO.className = "java.lang.Class";
371  
      dO.fieldValues.put("name", name);
372  
      ret dO;
373  
    }
374  
    
375  
    Object parseBigInt() {
376  
      consume("bigint");
377  
      consume("(");
378  
      S val = tok.get(i);
379  
      i++;
380  
      if (eq(val, "-")) {
381  
        val = "-" + tok.get(i);
382  
        i++;
383  
      }
384  
      consume(")");
385  
      ret new BigInteger(val);
386  
    }
387  
    
388  
    Object parseDouble() {
389  
      consume("d");
390  
      consume("(");
391  
      S val = unquote(tok.get(i));
392  
      i++;
393  
      consume(")");
394  
      ret Double.parseDouble(val);
395  
    }
396  
    
397  
    Object parseFloat() {
398  
      consume("fl");
399  
      S val;
400  
      if (eq(tok.get(i), "(")) {
401  
        consume("(");
402  
        val = unquote(tok.get(i));
403  
        i++;
404  
        consume(")");
405  
      } else {
406  
        val = unquote(tok.get(i));
407  
        i++;
408  
      }
409  
      ret Float.parseFloat(val);
410  
    }
411  
    
412  
    void parseHashMap(unstructure_Receiver out) {
413  
      i++;
414  
      parseMap(new HashMap, out);
415  
    }
416  
    
417  
    void parseHashSet(unstructure_Receiver out) {
418  
      consume("hashset");
419  
      parseSet(new HashSet, out);
420  
    }
421  
    
422  
    void parseTreeSet(unstructure_Receiver out) {
423  
      consume("treeset");
424  
      parseSet(new TreeSet, out);
425  
    }
426  
    
427  
    void parseMap(unstructure_Receiver out) {
428  
      parseMap(new TreeMap, out);
429  
    }
430  
    
431  
    void parseMap(final Map map, final unstructure_Receiver out) {
432  
      consume("{");
433  
      stack.add(new Runnable {
434  
        bool v;
435  
        O key;
436  
        
437  
        public void run() { 
438  
          if (v) {
439  
            v = false;
440  
            stack.add(this);
441  
            consume("=");
442  
            parse(new unstructure_Receiver {
443  
              void set(O value) {
444  
                map.put(key, value);
445  
                if (debug)
446  
                  print("parseMap: Got value " + getClassName(value) + ", next token: " + quote(tok.get(i)));
447  
                if (tok.get(i).equals(",")) i++;
448  
              }
449  
            });
450  
          } else {
451  
            if (tok.get(i).equals("}")) {
452  
              consume("}");
453  
              out.set(map);
454  
            } else {
455  
              v = true;
456  
              stack.add(this);
457  
              parse(new unstructure_Receiver {
458  
                void set(O o) {
459  
                  key = o;
460  
                }
461  
              });
462  
            }
463  
          } // if v else
464  
        } // run()
465  
      });
466  
    }
467  
    
468  
    /*void parseSub(unstructure_Receiver out) {
469  
      int n = l(stack);
470  
      parse(out);
471  
      while (l(stack) > n)
472  
        stack
473  
    }*/
474  
    
475  
    void consume(String s) {
476  
      if (!tok.get(i).equals(s)) {
477  
        S prevToken = i-1 >= 0 ? tok.get(i-1) : "";
478  
        S nextTokens = join(tok.subList(i, Math.min(i+2, tok.size())));
479  
        fail(quote(s) + " expected: " + prevToken + " " + nextTokens + " (" + i + "/" + tok.size() + ")");
480  
      }
481  
      i++;
482  
    }
483  
    
484  
    void parse_x(unstructure_Receiver out) {
485  
      parse(out);
486  
      while (nempty(stack))
487  
        popLast(stack).run();
488  
    }
489  
  }
490  
  
491  
  final new Var v;
492  
  new X().parse_x(new unstructure_Receiver {
493  
    void set(O o) { v.set(o); }
494  
  });
495  
  ret v.get();
496  
}
497  
498  
static boolean unstructure_debug;

Author comment

Began life as a copy of #1005658

download  show line numbers  debug dex  old transpilations   

Travelled to 15 computer(s): aoiabmzegqzx, bhatertpkbcr, cbybwowwnfue, cfunsshuasjs, gwrvuhgaqvyk, ishqpsrjomds, lpdgvwnxivlt, mqqgnosmbjvj, onxytkatvevr, pyentgdyhuwx, pzhvpgtvlbxg, sawdedvomwva, tslmcundralx, tvejysmllsmz, vouqrxazstgt

No comments. add comment

Snippet ID: #1005973
Snippet name: unstructure (v9, working virtual stack)
Eternal ID of this version: #1005973/1
Text MD5: 412a9ac718f792869377c92067832700
Author: stefan
Category: javax
Type: JavaX fragment (include)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2016-12-13 18:20:20
Source code size: 13925 bytes / 498 lines
Pitched / IR pitched: No / No
Views / Downloads: 597 / 595
Referenced in: [show references]