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

254
LINES

< > BotCompany Repo | #1003021 // unstructure with back references

JavaX fragment (include)

static class DynamicObject {
  S className;
  new Map<S, O> fieldValues;
}

static Object unstructure(String text) {
  ret unstructure(text, false);
}

static Object unstructure(String text, boolean allDynamic) {
  ret unstructure(text, allDynamic, new HashMap<Integer, O>());
}

static Object unstructure(String text, final boolean allDynamic,
  final HashMap<Integer, O> seen) {
  final L<S> tok = javaTok(text);
  final boolean debug = true;
  
  class X {
    int i = 1;

    Object parse() {
      // the non-backreference things
      
      String t = tok.get(i);
      
      if (debug)
        print("parse: " + quote(t));
        
      if (t.startsWith("\"")) {
        String s = unquote(tok.get(i));
        i += 2;
        return s;
      }
      if (t.equals("bigint"))
        return parseBigInt();
      if (t.equals("d"))
        return parseDouble();
      if (t.equals("false")) {
        i += 2; return false;
      }
      if (t.equals("true")) {
        i += 2; return true;
      }
      if (t.equals("-")) {
        t = tok.get(i+2);
        i += 4;
        t = dropSuffix("L", t);
        long l = -Long.parseLong(t);
        ret l == (int) l ? (int) l : l;
      }
      if (isInteger(t) || isLongConstant(t)) {
        i += 2;
        t = dropSuffix("L", t);
        long l = Long.parseLong(t);
        ret l == (int) l ? (int) l : l;
      }
      
      if (t.startsWith("r") && isInteger(t.substring(1))) {
        i += 2;
        int ref = Integer.parseInt(t.substring(1));
        O o = seen.get(ref);
        if (o == null)
          print("Warning: unsatisfied back reference " + ref);
        ret o;
      }
      
      O o = parse_inner();
      seen.put(seen.size()+1, o);
      ret o;
    }
    
    // everything that can be backreferenced
    O parse_inner() {
      String t = tok.get(i);
      
      if (debug)
        print("parse_inner: " + quote(t));
        
      if (t.equals("hashset"))
        return parseHashSet();
      if (t.equals("treeset"))
        return parseTreeSet();
      if (t.equals("hashmap"))
        return parseHashMap();
      if (t.equals("{"))
        return parseMap();
      if (t.equals("["))
        return parseList();
      if (t.equals("array"))
        return parseArray();
      if (t.equals("class"))
        return parseClass();
      if (t.equals("l"))
        return parseLisp();
      if (t.equals("null")) {
        i += 2; return null;
      }
      if (isJavaIdentifier(t)) {
        Class c = allDynamic ? null : findClass(t);
        DynamicObject dO = null;
        O o = null;
        if (c != null)
          o = nuObject(c);
        else {
          dO = new DynamicObject;
          dO.className = t;
        }
        i += 2;
        if (i < tok.size() && tok.get(i).equals("(")) {
          consume("(");
          while (!tok.get(i).equals(")")) {
            // It's like parsing a map.
            //Object key = parse();
            //if (tok.get(i).equals(")"))
            //  key = onlyField();
            String key = unquote(tok.get(i));
            i += 2;
            consume("=");
            Object value = parse();
            if (o != null)
              setOpt(o, key, value);
            else
              dO.fieldValues.put(key, value);
            if (tok.get(i).equals(",")) i += 2;
          }
          consume(")");
        }
        return o != null ? o : dO;
      }
      throw new RuntimeException("Unknown token " + (i+1) + ": " + t);
    }
    
    Object parseSet(Set set) {
      set.addAll((L) parseList());
      return set;
    }
    
    Object parseLisp() {
      consume("l");
      consume("(");
      List list = new ArrayList;
      while (!tok.get(i).equals(")")) {
        list.add(parse());
        if (tok.get(i).equals(",")) i += 2;
      }
      consume(")");
      return newObject("main$Lisp", (S) list.get(0), subList(list, 1));
    }
    
    Object parseList() {
      consume("[");
      List list = new ArrayList;
      while (!tok.get(i).equals("]")) {
        list.add(parse());
        if (tok.get(i).equals(",")) i += 2;
      }
      consume("]");
      return list;
    }
    
    Object parseArray() {
      consume("array");
      consume("{");
      List list = new ArrayList;
      while (!tok.get(i).equals("}")) {
        list.add(parse());
        if (tok.get(i).equals(",")) i += 2;
      }
      consume("}");
      return list.toArray();
    }
    
    Object parseClass() {
      consume("class");
      consume("(");
      S name = tok.get(i);
      i += 2;
      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 += 2;
      if (eq(val, "-")) {
        val = "-" + tok.get(i);
        i += 2;
      }
      consume(")");
      ret new BigInteger(val);
    }
    
    Object parseDouble() {
      consume("d");
      consume("(");
      S val = unquote(tok.get(i));
      i += 2;
      consume(")");
      ret Double.parseDouble(val);
    }
    
    Object parseHashMap() {
      consume("hashmap");
      return parseMap(new HashMap);
    }
    
    Object parseHashSet() {
      consume("hashset");
      return parseSet(new HashSet);
    }
    
    Object parseTreeSet() {
      consume("treeset");
      return parseSet(new TreeSet);
    }
    
    Object parseMap() {
      return parseMap(new TreeMap);
    }
    
    Object parseMap(Map map) {
      consume("{");
      while (!tok.get(i).equals("}")) {
        //O key = unstructure(tok.get(i));
        O key = parse();
        consume("=");
        Object value = parse();
        map.put(key, value);
        if (tok.get(i).equals(",")) i += 2;
      }
      consume("}");
      return map;
    }
    
    void consume(String s) {
      if (!tok.get(i).equals(s)) {
        S prevToken = i-2 >= 0 ? tok.get(i-2) : "";
        S nextTokens = join(tok.subList(i, Math.min(i+4, tok.size())));
        fail(quote(s) + " expected: " + prevToken + " " + nextTokens + " (" + i + "/" + tok.size() + ")");
      }
      i += 2;
    }
  }
  
  return new X().parse();
}

Author comment

Began life as a copy of #1001355

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: #1003021
Snippet name: unstructure with back references
Eternal ID of this version: #1003021/1
Text MD5: 884f1927332db4a091c356c8f6fb8056
Author: stefan
Category: javax
Type: JavaX fragment (include)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2016-04-19 17:54:07
Source code size: 6531 bytes / 254 lines
Pitched / IR pitched: No / No
Views / Downloads: 585 / 801
Referenced in: #1003020 - Test Opposites Bot Load Bug
#1003039 - unstructure with new new back references and fixed int/long (v4, outdated)
#3000382 - Answer for ferdie (>> t = 1, f = 0)
#3000383 - Answer for funkoverflow (>> t=1, f=0 okay)