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

369
LINES

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

Author comment

Began life as a copy of #1003039

download  show line numbers  debug dex  old transpilations   

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

No comments. add comment

Snippet ID: #1005597
Snippet name: unstructure (v5, dev.)
Eternal ID of this version: #1005597/1
Text MD5: 8b0b636dc496820710e356863cb0c887
Author: stefan
Category: javax
Type: JavaX fragment (include)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2016-11-29 00:04:09
Source code size: 9792 bytes / 369 lines
Pitched / IR pitched: No / No
Views / Downloads: 485 / 478
Referenced in: [show references]