code: private String string() {
      char quote = peek(0);
      int start = ++_x;
      boolean has_escapes = false;
      while (_x < _str.length()) {
        char c = peek(0);
        if (c == '\\') {
          has_escapes = true;
          char cc = peek(1);
          if (simpleEscapeSequences.containsKey(cc)) {
            _x += 2;
          } else if (cc == 'x') {
            _x += 4;   // e.g: \x5A
          } else if (cc == 'u') {
            _x += 6;   // e.g: \u1234
          } else if (cc == 'U') {
            _x += 10;  // e.g: \U0010FFFF
          } else
            throw new IllegalASTException("Invalid escape sequence \\" + cc);
        } else if (c == quote) {
          _x++;
          if (has_escapes) {
            StringBuilder sb = new StringBuilder();
            for (int i = start; i < _x - 1; i++) {
              char ch = _str.charAt(i);
              if (ch == '\\') {
                char cc = _str.charAt(++i);
                if (simpleEscapeSequences.containsKey(cc)) {
                  sb.append(simpleEscapeSequences.get(cc));
                } else {
                  int n = (cc == 'x')? 2 : (cc == 'u')? 4 : (cc == 'U')? 8 : -1;
                  int hex = -1;
                  try {
                    hex = StringUtils.unhex(_str.substring(i + 1, i + 1 + n));
                  } catch (NumberFormatException e) {
                    throw new IllegalASTException(e.toString());
                  }
                  if (hex > 0x10FFFF)
                    throw new IllegalASTException("Illegal unicode codepoint " + hex);
                  sb.append(Character.toChars(hex));
                  i += n;
                }
              } else {
                sb.append(ch);
              }
            }
            return sb.toString();
          } else {
            return _str.substring(start, _x - 1);
          }
        } else {
          _x++;
        }
      }
      throw new IllegalASTException("Unterminated string at " + start);
    }
docs: Parse a string from the token stream.