static Object unstructure(String text) { ret unstructure(text, false); } static Object unstructure(String text, final boolean allDynamic) { ret unstructure(text, allDynamic, null); } static int structure_internStringsLongerThan = 50; abstract sclass unstructure_Receiver { abstract void set(O o); } // classFinder: func(name) -> class (optional) static Object unstructure(String text, boolean allDynamic, O classFinder) { if (text == null) ret null; final L<S> tok = javaTokC(text); ret unstructure_tok(tok, allDynamic, classFinder); } // so text can be freed static Object unstructure_tempVar(Var<S> text) { L<S> tok = javaTokC(text.get()); text.clear(); ret unstructure_tok(tok, false, null); } static O unstructure_tok(final L<S> tok, final boolean allDynamic, final O classFinder) { final boolean debug = unstructure_debug; class X { int i = 0; new HashMap<Integer, O> refs; new HashMap<Integer, O> tokrefs; new HashSet<S> concepts; new HashMap<S, Class> classesMap; new L<Runnable> stack; void parse(final unstructure_Receiver out) { S t = tok.get(i); int refID = 0; if (structure_isMarker(t, 0, l(t))) { refID = parseInt(t.substring(1)); i++; } final int _refID = refID; // if (debug) print("parse: " + quote(t)); final int tokIndex = i; parse_inner(refID, tokIndex, new unstructure_Receiver { void set(O o) { if (_refID != 0) refs.put(_refID, o); if (o != null) tokrefs.put(tokIndex, o); out.set(o); } }); } void parse_inner(int refID, int tokIndex, final unstructure_Receiver out) { S t = tok.get(i); // if (debug) print("parse_inner: " + quote(t)); Class c = classesMap.get(t); if (c == null) { if (t.startsWith("\"")) { S s = internIfLongerThan(unquote(tok.get(i)), structure_internStringsLongerThan); i++; out.set(s); ret; } if (t.startsWith("'")) { out.set(unquoteCharacter(tok.get(i++))); ret; } if (t.equals("bigint")) { out.set(parseBigInt()); ret; } if (t.equals("d")) { out.set(parseDouble()); ret; } if (t.equals("fl")) { out.set(parseFloat()); ret; } if (t.equals("false") || t.equals("f")) { i++; out.set(false); ret; } if (t.equals("true") || t.equals("t")) { i++; out.set(true); ret; } if (t.equals("-")) { t = tok.get(i+1); i += 2; out.set(isLongConstant(t) ? (O) (-parseLong(t)) : (O) (-parseInt(t))); ret; } if (isInteger(t) || isLongConstant(t)) { i++; //if (debug) print("isLongConstant " + quote(t) + " => " + isLongConstant(t)); if (isLongConstant(t)) { out.set(parseLong(t)); ret; } long l = parseLong(t); bool isInt = l == (int) l; if (debug) print("l=" + l + ", isInt: " + isInt); out.set(isInt ? (O) new Integer((int) l) : (O) new Long(l)); ret; } if (t.equals("File")) { File f = new File(unquote(tok.get(i+1))); i += 2; out.set(f); ret; } if (t.startsWith("r") && isInteger(t.substring(1))) { i++; int ref = Integer.parseInt(t.substring(1)); O o = refs.get(ref); if (o == null) print("Warning: unsatisfied back reference " + ref); out.set(o); ret; } if (t.startsWith("t") && isInteger(t.substring(1))) { i++; int ref = Integer.parseInt(t.substring(1)); O o = tokrefs.get(ref); if (o == null) print("Warning: unsatisfied token reference " + ref); out.set(o); ret; } if (t.equals("hashset")) { parseHashSet(out); ret; } if (t.equals("treeset")) { parseTreeSet(out); ret; } if (eqOneOf(t, "hashmap", "hm")) { parseHashMap(out); ret; } if (t.equals("{")) { parseMap(out); ret; } if (t.equals("[")) { parseList(out); ret; } if (t.equals("bitset")) { parseBitSet(out); ret; } if (t.equals("array") || t.equals("intarray")) { parseArray(out); ret; } if (t.equals("ba")) { S hex = unquote(tok.get(i+1)); i += 2; out.set(hexToBytes(hex)); ret; } if (t.equals("boolarray")) { int n = parseInt(tok.get(i+1)); S hex = unquote(tok.get(i+2)); i += 6; out.set(boolArrayFromBytes(hexToBytes(hex), n)); ret; } if (t.equals("class")) { out.set(parseClass()); ret; } if (t.equals("l")) { parseLisp(out); ret; } if (t.equals("null")) { i++; out.set(null); ret; } if (eq(t, "c")) { consume("c"); t = tok.get(i); assertTrue(isJavaIdentifier(t)); concepts.add(t); } } if (c == null && !isJavaIdentifier(t)) throw new RuntimeException("Unknown token " + (i+1) + ": " + t); // any other class name if (c == null) { // First, find class if (allDynamic) c = null; else if (classFinder != null) c = (Class) callF(classFinder, t); else c = findClass(t); if (c != null) classesMap.put(t, c); } // Check if it has an outer reference i++; bool hasOuter = eq(get(tok, i), "(") && eq(get(tok, i+1), "this$1"); DynamicObject dO = null; O o = null; if (c != null) o = hasOuter ? nuStubInnerObject(c) : nuEmptyObject(c); else { if (concepts.contains(t) && (c = findClass("Concept")) != null) o = dO = (DynamicObject) nuEmptyObject(c); else dO = new DynamicObject; dO.className = t; if (debug) print("Made dynamic object " + t + " " + shortClassName(dO)); } // Save in references list early because contents of object // might link back to main object if (refID != 0) refs.put(refID, o != null ? o : dO); tokrefs.put(tokIndex, o != null ? o : dO); // NOW parse the fields! final new HashMap<S, O> fields; final O _o = o; final DynamicObject _dO = dO; if (i < tok.size() && tok.get(i).equals("(")) { consume("("); stack.add(r { if (tok.get(i).equals(")")) { consume(")"); objRead(_o, _dO, fields); out.set(_o != null ? _o : _dO); } else { final S key = unquote(tok.get(i++)); consume("="); stack.add(this); parse(new unstructure_Receiver { void set(O value) { fields.put(key, value); if (tok.get(i).equals(",")) i++; } }); } }); } else objRead(o, dO, fields); } void objRead(O o, DynamicObject dO, Map<S, O> fields) { if (o != null) if (dO != null) { if (debug) printStructure("setOptAllDyn", fields); setOptAllDyn(dO, fields); } else setOptAll(o, fields); else for (S field : keys(fields)) dO.fieldValues.put(field.intern(), fields.get(field)); if (o != null) pcallOpt_noArgs(o, "_doneLoading"); } void parseSet(final Set set, final unstructure_Receiver out) { parseList(new unstructure_Receiver { void set(O o) { set.addAll((L) o); out.set(set); } }); } void parseLisp(final unstructure_Receiver out) { consume("l"); consume("("); final new ArrayList list; stack.add(r { if (tok.get(i).equals(")")) { consume(")"); out.set(newObject("main$Lisp", (S) list.get(0), subList(list, 1))); } else { stack.add(this); parse(new unstructure_Receiver { void set(O o) { list.add(o); if (tok.get(i).equals(",")) i++; } }); } }); } void parseBitSet(final unstructure_Receiver out) { consume("bitset"); consume("{"); final new BitSet bs; stack.add(r { if (tok.get(i).equals("}")) { consume("}"); out.set(bs); } else { stack.add(this); parse(new unstructure_Receiver { void set(O o) { bs.set((Integer) o); if (tok.get(i).equals(",")) i++; } }); } }); } void parseList(final unstructure_Receiver out) { consume("["); final new ArrayList list; stack.add(r { if (tok.get(i).equals("]")) { consume("]"); out.set(list); } else { stack.add(this); parse(new unstructure_Receiver { void set(O o) { //if (debug) print("List element type: " + getClassName(o)); list.add(o); if (tok.get(i).equals(",")) i++; } }); } }); } void parseArray(final unstructure_Receiver out) { final S type = tok.get(i); i++; consume("{"); final List list = new ArrayList; stack.add(r { if (tok.get(i).equals("}")) { consume("}"); out.set(type.equals("intarray") ? toIntArray(list) : list.toArray()); } else { stack.add(this); parse(new unstructure_Receiver { void set(O o) { list.add(o); if (tok.get(i).equals(",")) i++; } }); } }); } Object parseClass() { consume("class"); consume("("); S name = tok.get(i); i++; consume(")"); Class c = allDynamic ? null : findClass(name); if (c != null) ret c; new DynamicObject dO; dO.className = "java.lang.Class"; dO.fieldValues.put("name", name); ret dO; } Object parseBigInt() { consume("bigint"); consume("("); S val = tok.get(i); i++; if (eq(val, "-")) { val = "-" + tok.get(i); i++; } consume(")"); ret new BigInteger(val); } Object parseDouble() { consume("d"); consume("("); S val = unquote(tok.get(i)); i++; consume(")"); ret Double.parseDouble(val); } Object parseFloat() { consume("fl"); S val; if (eq(tok.get(i), "(")) { consume("("); val = unquote(tok.get(i)); i++; consume(")"); } else { val = unquote(tok.get(i)); i++; } ret Float.parseFloat(val); } void parseHashMap(unstructure_Receiver out) { i++; parseMap(new HashMap, out); } void parseHashSet(unstructure_Receiver out) { consume("hashset"); parseSet(new HashSet, out); } void parseTreeSet(unstructure_Receiver out) { consume("treeset"); parseSet(new TreeSet, out); } void parseMap(unstructure_Receiver out) { parseMap(new TreeMap, out); } void parseMap(final Map map, final unstructure_Receiver out) { consume("{"); stack.add(new Runnable { bool v; O key; public void run() { if (v) { v = false; stack.add(this); consume("="); parse(new unstructure_Receiver { void set(O value) { map.put(key, value); if (debug) print("parseMap: Got value " + getClassName(value) + ", next token: " + quote(tok.get(i))); if (tok.get(i).equals(",")) i++; } }); } else { if (tok.get(i).equals("}")) { consume("}"); out.set(map); } else { v = true; stack.add(this); parse(new unstructure_Receiver { void set(O o) { key = o; } }); } } // if v else } // run() }); } /*void parseSub(unstructure_Receiver out) { int n = l(stack); parse(out); while (l(stack) > n) stack }*/ void consume(String s) { if (!tok.get(i).equals(s)) { S prevToken = i-1 >= 0 ? tok.get(i-1) : ""; S nextTokens = join(tok.subList(i, Math.min(i+2, tok.size()))); fail(quote(s) + " expected: " + prevToken + " " + nextTokens + " (" + i + "/" + tok.size() + ")"); } i++; } void parse_x(unstructure_Receiver out) { parse(out); while (nempty(stack)) popLast(stack).run(); } } final new Var v; new X().parse_x(new unstructure_Receiver { void set(O o) { v.set(o); } }); ret v.get(); } static boolean unstructure_debug;
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: | 598 / 595 |
Referenced in: | #1005975 - unstructure (v10, from stream, dev.) |