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

385
LINES

< > BotCompany Repo | #1005604 // unstructure (v7, matches structure v10)

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

Author comment

Began life as a copy of #1005600

download  show line numbers  debug dex  old transpilations   

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

No comments. add comment

Snippet ID: #1005604
Snippet name: unstructure (v7, matches structure v10)
Eternal ID of this version: #1005604/1
Text MD5: 5aa0ba4a90883f25a2b9fa97811301d0
Author: stefan
Category: javax
Type: JavaX fragment (include)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2016-12-13 17:01:40
Source code size: 10513 bytes / 385 lines
Pitched / IR pitched: No / No
Views / Downloads: 401 / 381
Referenced in: [show references]