docs: def loads(s, _dict=dict):
      """Parses string as toml
  
      Args:
          s: String to be parsed
          _dict: (optional) Specifies the class of the returned toml dictionary
  
      Returns:
          Parsed toml file represented as a dictionary
  
      Raises:
          TypeError: When a non-string is passed
          TomlDecodeError: Error while decoding toml
      """
  
      implicitgroups = []
      retval = _dict()
      currentlevel = retval
      if not isinstance(s, basestring):
          raise TypeError("Expecting something like a string")
  
      if not isinstance(s, unicode):
          s = s.decode('utf8')
  
      sl = list(s)
      openarr = 0
      openstring = False
      openstrchar = ""
      multilinestr = False
      arrayoftables = False
      beginline = True
      keygroup = False
      keyname = 0
      for i, item in enumerate(sl):
          if item == '\r' and sl[i + 1] == '\n':
              sl[i] = ' '
              continue
          if keyname:
              if item == '\n':
                  raise TomlDecodeError("Key name found without value."
                                        " Reached end of line.")
              if openstring:
                  if item == openstrchar:
                      keyname = 2
                      openstring = False
                      openstrchar = ""
                  continue
              elif keyname == 1:
                  if item.isspace():
                      keyname = 2
                      continue
                  elif item.isalnum() or item == '_' or item == '-':
                      continue
              elif keyname == 2 and item.isspace():
                  continue
              if item == '=':
                  keyname = 0
              else:
                  raise TomlDecodeError("Found invalid character in key name: '" +
                                        item + "'. Try quoting the key name.")
          if item == "'" and openstrchar != '"':
              k = 1
              try:
                  while sl[i - k] == "'":
                      k += 1
                      if k == 3:
                          break
              except IndexError:
                  pass
              if k == 3:
                  multilinestr = not multilinestr
                  openstring = multilinestr
              else:
                  openstring = not openstring
              if openstring:
                  openstrchar = "'"
              else:
                  openstrchar = ""
          if item == '"' and openstrchar != "'":
              oddbackslash = False
              k = 1
              tripquote = False
              try:
                  while sl[i - k] == '"':
                      k += 1
                      if k == 3:
                          tripquote = True
                          break
                  if k == 1 or (k == 3 and tripquote):
                      while sl[i - k] == '\\':
                          oddbackslash = not oddbackslash
                          k += 1
              except IndexError:
                  pass
              if not oddbackslash:
                  if tripquote:
                      multilinestr = not multilinestr
                      openstring = multilinestr
                  else:
                      openstring = not openstring
              if openstring:
                  openstrchar = '"'
              else:
                  openstrchar = ""
          if item == '#' and (not openstring and not keygroup and
                              not arrayoftables):
              j = i
              try:
                  while sl[j] != '\n':
                      sl[j] = ' '
                      j += 1
              except IndexError:
                  break
          if item == '[' and (not openstring and not keygroup and
                              not arrayoftables):
              if beginline:
                  if sl[i + 1] == '[':
                      arrayoftables = True
                  else:
                      keygroup = True
              else:
                  openarr += 1
          if item == ']' and not openstring:
              if keygroup:
                  keygroup = False
              elif arrayoftables:
                  if sl[i - 1] == ']':
                      arrayoftables = False
              else:
                  openarr -= 1
          if item == '\n':
              if openstring or multilinestr:
                  if not multilinestr:
                      raise TomlDecodeError("Unbalanced quotes")
                  if ((sl[i - 1] == "'" or sl[i - 1] == '"') and (
                          sl[i - 2] == sl[i - 1])):
                      sl[i] = sl[i - 1]
                      if sl[i - 3] == sl[i - 1]:
                          sl[i - 3] = ' '
              elif openarr:
                  sl[i] = ' '
              else:
                  beginline = True
          elif beginline and sl[i] != ' ' and sl[i] != '\t':
              beginline = False
              if not keygroup and not arrayoftables:
                  if sl[i] == '=':
                      raise TomlDecodeError("Found empty keyname. ")
                  keyname = 1
      s = ''.join(sl)
      s = s.split('\n')
      multikey = None
      multilinestr = ""
      multibackslash = False
      for line in s:
          if not multilinestr or multibackslash or '\n' not in multilinestr:
              line = line.strip()
          if line == "" and (not multikey or multibackslash):
              continue
          if multikey:
              if multibackslash:
                  multilinestr += line
              else:
                  multilinestr += line
              multibackslash = False
              if len(line) > 2 and (line[-1] == multilinestr[0] and
                                    line[-2] == multilinestr[0] and
                                    line[-3] == multilinestr[0]):
                  value, vtype = _load_value(multilinestr, _dict)
                  currentlevel[multikey] = value
                  multikey = None
                  multilinestr = ""
              else:
                  k = len(multilinestr) - 1
                  while k > -1 and multilinestr[k] == '\\':
                      multibackslash = not multibackslash
                      k -= 1
                  if multibackslash:
                      multilinestr = multilinestr[:-1]
                  else:
                      multilinestr += "\n"
              continue
          if line[0] == '[':
              arrayoftables = False
              if line[1] == '[':
                  arrayoftables = True
                  line = line[2:].split(']]', 1)
              else:
                  line = line[1:].split(']', 1)
              if line[1].strip() != "":
                  raise TomlDecodeError("Key group not on a line by itself.")
              groups = line[0].split('.')
              i = 0
              while i < len(groups):
                  groups[i] = groups[i].strip()
                  if groups[i][0] == '"' or groups[i][0] == "'":
                      groupstr = groups[i]
                      j = i + 1
                      while not groupstr[0] == groupstr[-1]:
                          j += 1
                          groupstr = '.'.join(groups[i:j])
                      groups[i] = groupstr[1:-1]
                      groups[i + 1:j] = []
                  else:
                      if not _groupname_re.match(groups[i]):
                          raise TomlDecodeError("Invalid group name '" +
                                                groups[i] + "'. Try quoting it.")
                  i += 1
              currentlevel = retval
              for i in _range(len(groups)):
                  group = groups[i]
                  if group == "":
                      raise TomlDecodeError("Can't have a keygroup with an empty "
                                            "name")
                  try:
                      currentlevel[group]
                      if i == len(groups) - 1:
                          if group in implicitgroups:
                              implicitgroups.remove(group)
                              if arrayoftables:
                                  raise TomlDecodeError("An implicitly defined "
                                                        "table can't be an array")
                          elif arrayoftables:
                              currentlevel[group].append(_dict())
                          else:
                              raise TomlDecodeError("What? " + group +
                                                    " already exists?" +
                                                    str(currentlevel))
                  except TypeError:
                      currentlevel = currentlevel[-1]
                      try:
                          currentlevel[group]
                      except KeyError:
                          currentlevel[group] = _dict()
                          if i == len(groups) - 1 and arrayoftables:
                              currentlevel[group] = [_dict()]
                  except KeyError:
                      if i != len(groups) - 1:
                          implicitgroups.append(group)
                      currentlevel[group] = _dict()
                      if i == len(groups) - 1 and arrayoftables:
                          currentlevel[group] = [_dict()]
                  currentlevel = currentlevel[group]
                  if arrayoftables:
                      try:
                          currentlevel = currentlevel[-1]
                      except KeyError:
                          pass
          elif line[0] == "{":
              if line[-1] != "}":
                  raise TomlDecodeError("Line breaks are not allowed in inline"
                                        "objects")
              _load_inline_object(line, currentlevel, _dict, multikey,
                                  multibackslash)
          elif "=" in line:
              ret = _load_line(line, currentlevel, _dict, multikey,
                               multibackslash)
              if ret is not None:
                  multikey, multilinestr, multibackslash = ret
      return retval