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

372
LINES

< > BotCompany Repo | #1005600 // unstructure (v6)

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

Author comment

Began life as a copy of #1005597

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: #1005600
Snippet name: unstructure (v6)
Eternal ID of this version: #1005600/1
Text MD5: 10044411ed08aba0eb0b1053c6820a1a
Author: stefan
Category: javax
Type: JavaX fragment (include)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2016-11-29 15:50:35
Source code size: 10011 bytes / 372 lines
Pitched / IR pitched: No / No
Views / Downloads: 437 / 418
Referenced in: [show references]