code: def parse(text: str) -> Docstring:
      ret = Docstring()
      if not text:
          return ret
      text = inspect.cleandoc(text)
      match = _titles_re.search(text)
      if match:
          desc_chunk = text[: match.start()]
          meta_chunk = text[match.start() :]
      else:
          desc_chunk = text
          meta_chunk = ""
      parts = desc_chunk.split("\n", 1)
      ret.short_description = parts[0] or None
      if len(parts) > 1:
          long_desc_chunk = parts[1] or ""
          ret.blank_after_short_description = long_desc_chunk.startswith("\n")
          ret.blank_after_long_description = long_desc_chunk.endswith("\n\n")
          ret.long_description = long_desc_chunk.strip() or None
      matches = list(_titles_re.finditer(meta_chunk))
      if not matches:
          return ret
      splits = []
      for j in range(len(matches) - 1):
          splits.append((matches[j].end(), matches[j + 1].start()))
      splits.append((matches[-1].end(), len(meta_chunk)))
      chunks = {}
      for j, (start, end) in enumerate(splits):
          title = matches[j].group(1)
          if title not in _valid:
              continue
          chunks[title] = meta_chunk[start:end].strip("\n")
      if not chunks:
          return ret
      for title, chunk in chunks.items():
          indent_match = re.search(r"^\s+", chunk)
          if not indent_match:
              raise ParseError(f'Can\'t infer indent from "{chunk}"')
          indent = indent_match.group()
          if _sections[title] in ("returns", "yields"):
              part = inspect.cleandoc(chunk)
              ret.meta.append(_build_meta(part, title))
              continue
          _re = "^" + indent + r"(?=\S)"
          c_matches = list(re.finditer(_re, chunk, flags=re.M))
          if not c_matches:
              raise ParseError(f'No specification for "{title}": "{chunk}"')
          c_splits = []
          for j in range(len(c_matches) - 1):
              c_splits.append((c_matches[j].end(), c_matches[j + 1].start()))
          c_splits.append((c_matches[-1].end(), len(chunk)))
          for j, (start, end) in enumerate(c_splits):
              part = chunk[start:end].strip("\n")
              ret.meta.append(_build_meta(part, title))
      return ret