docs: function(i, query) {
      if(query.charAt(i) == this.ATOM_SET_START) {
        var j=i+1;
        var tokens=[];
        var usedArrayDelimiter = false
        var usedRangeDelimiter = false;
        var readResult;
  
        if(query.charAt(j) == this.ATOM_SET_END) {
          return [j+1, new this()]; // Empty set
        }
  
        while(readResult = SpahQL.Token.parseAt(j, query)) {
          var token = readResult[1];
          var allowedTokens = [SpahQL.Token.Numeric, SpahQL.Token.String, SpahQL.Token.Boolean, SpahQL.Token.SelectionQuery];
          var tokenIsAllowed = false;
          for(var i in allowedTokens) {
            var klass = allowedTokens[i];
            if(token instanceof klass) {
              tokenIsAllowed = true;
              break;
            }
          }
          
          if(tokenIsAllowed) {
            // wind ahead
            j = readResult[0];
            // push token into set
            tokens.push(token);
            // find delimiter
            if(query.charAt(j) == this.ATOM_SET_ARRAY_DELIMITER) {
              if(usedRangeDelimiter) {
                this.throwParseErrorAt(j, query, "Found unexpected ATOM_SET_ARRAY_DELIMITER in set literal that already used the range delimiter.");
              }
              usedArrayDelimiter = true; j++;
            }
            else if(query.substr(j, this.ATOM_SET_RANGE_DELIMITER.length) == this.ATOM_SET_RANGE_DELIMITER) {
              if(usedArrayDelimiter) {
                this.throwParseErrorAt(j, query, "Found unexpected ATOM_SET_RANGE_DELIMITER in set literal that already used the array delimiter.");
              }
              usedRangeDelimiter = true; j+=this.ATOM_SET_RANGE_DELIMITER.length;
            }
            else if(query.charAt(j) == this.ATOM_SET_END) {
              j++; break;
            }
            else {
              this.throwParseErrorAt(j, query, "Found unexpected character '"+query.charAt(j)+"' in set literal, expecting one of ATOM_SET_ARRAY_DELIMITER, ATOM_SET_RANGE_DELIMITER, ATOM_SET_END.");
            }
          }
          else {
            this.throwParseErrorAt(j, query,  "Found unexpected token in set literal. Set literals may only contain string, numeric, boolean and selection query values.");
          }
        }
        return [j, new this(tokens, usedRangeDelimiter)];
      }
      return null;
    }