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

421
LINES

< > BotCompany Repo | #1005658 // unstructure (v8, virtual stack, dev.)

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

Author comment

Began life as a copy of #1005604

download  show line numbers  debug dex  old transpilations   

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

No comments. add comment

Snippet ID: #1005658
Snippet name: unstructure (v8, virtual stack, dev.)
Eternal ID of this version: #1005658/1
Text MD5: c838217897ac97113ac26a743137c1e8
Author: stefan
Category: javax
Type: JavaX fragment (include)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2016-12-13 15:56:28
Source code size: 11328 bytes / 421 lines
Pitched / IR pitched: No / No
Views / Downloads: 469 / 468
Referenced in: [show references]