private static HashMap parseJSHash(StringParser jsHash) {
        LinkedHashMap rv = new LinkedHashMap();
        jsHash.trim();
        if (jsHash.peek()=='}') {
            jsHash.forward(1);
            return rv;
        }
        while (!jsHash.isEmpty()) {
            Object key;
            if (isIdStart(jsHash.peek())) {
                key = parseId(jsHash);
            } else {
                key = parseJSExpr(jsHash);
            }
            jsHash.trim();
            if (!jsHash.isEmpty()) {
                if (jsHash.peek() != ':')
                    throw new RuntimeException(jsHash.toString());
                jsHash.forward(1);
                jsHash.trim();
            } else
                throw new IllegalArgumentException();
            Object value = parseJSExpr(jsHash);
            jsHash.trim();
            if (!jsHash.isEmpty()) {
                char ch = jsHash.poll();
                if (ch == '}') {
                    rv.put(key, value);
                    return rv;
                }
                if (ch != ',')
                    throw new RuntimeException(jsHash.toString());
                jsHash.trim();
            }
            rv.put(key, value);
        }
        return rv;
    }