def __alterDocstring(self, tail='', writer=None):
        """
        Runs eternally, processing docstring lines.

        Parses docstring lines as they get fed in via send, applies appropriate
        Doxygen tags, and passes them along in batches for writing.
        """
        assert isinstance(tail, str) and isinstance(writer, GeneratorType)

        lines = []
        timeToSend = False
        inCodeBlock = False
        inCodeBlockObj = [False]
        inSection = False
        prefix = ''
        firstLineNum = -1
        sectionHeadingIndent = 0
        codeChecker = self._checkIfCode(inCodeBlockObj)
        while True:
            lineNum, line = (yield)
            if firstLineNum < 0:
                firstLineNum = lineNum
            # Don't bother doing extra work if it's a sentinel.
            if line is not None:
                # Also limit work if we're not parsing the docstring.
                if self.options.autobrief:
                    for doxyTag, tagRE in AstWalker.__singleLineREs.items():
                        match = tagRE.search(line)
                        if match:
                            # We've got a simple one-line Doxygen command
                            lines[-1], inCodeBlock = self._endCodeIfNeeded(
                                lines[-1], inCodeBlock)
                            inCodeBlockObj[0] = inCodeBlock
                            writer.send((firstLineNum, lineNum - 1, lines))
                            lines = []
                            firstLineNum = lineNum
                            line = line.replace(match.group(1), doxyTag)
                            timeToSend = True

                    if inSection:
                        # The last line belonged to a section.
                        # Does this one too? (Ignoring empty lines.)
                        match = AstWalker.__blanklineRE.match(line)
                        if not match:
                            indent = len(line.expandtabs(self.options.tablength)) - \
                                len(line.expandtabs(self.options.tablength).lstrip())
                            if indent <= sectionHeadingIndent:
                                inSection = False
                            else:
                                if lines[-1] == '#':
                                    # If the last line was empty, but we're still in a section
                                    # then we need to start a new paragraph.
                                    lines[-1] = '# @par'

                    match = AstWalker.__returnsStartRE.match(line)
                    if match:
                        # We've got a "returns" section
                        lines[-1], inCodeBlock = self._endCodeIfNeeded(
                            lines[-1], inCodeBlock)
                        inCodeBlockObj[0] = inCodeBlock
                        line = line.replace(match.group(0), ' @return\t').rstrip()
                        prefix = '@return\t'
                    else:
                        match = AstWalker.__argsStartRE.match(line)
                        if match:
                            # We've got an "arguments" section
                            line = line.replace(match.group(0), '').rstrip()
                            if 'attr' in match.group(0).lower():
                                prefix = '@property\t'
                            else:
                                prefix = '@param\t'
                            lines[-1], inCodeBlock = self._endCodeIfNeeded(
                                lines[-1], inCodeBlock)
                            inCodeBlockObj[0] = inCodeBlock
                            lines.append('#' + line)
                            continue
                        else:
                            match = AstWalker.__argsRE.match(line)
                            if match and not inCodeBlock:
                                # We've got something that looks like an item /
                                # description pair.
                                if 'property' in prefix:
                                    line = '# {0}\t{1[name]}{2}# {1[desc]}'.format(
                                        prefix, match.groupdict(), linesep)
                                else:
                                    line = ' {0}\t{1[name]}\t{1[desc]}'.format(
                                        prefix, match.groupdict())
                            else:
                                match = AstWalker.__raisesStartRE.match(line)
                                if match:
                                    line = line.replace(match.group(0), '').rstrip()
                                    if 'see' in match.group(1).lower():
                                        # We've got a "see also" section
                                        prefix = '@sa\t'
                                    else:
                                        # We've got an "exceptions" section
                                        prefix = '@exception\t'
                                    lines[-1], inCodeBlock = self._endCodeIfNeeded(
                                        lines[-1], inCodeBlock)
                                    inCodeBlockObj[0] = inCodeBlock
                                    lines.append('#' + line)
                                    continue
                                else:
                                    match = AstWalker.__listRE.match(line)
                                    if match and not inCodeBlock:
                                        # We've got a list of something or another
                                        itemList = []
                                        for itemMatch in AstWalker.__listItemRE.findall(self._stripOutAnds(
                                                                                        match.group(0))):
                                            itemList.append('# {0}\t{1}{2}'.format(
                                                prefix, itemMatch, linesep))
                                        line = ''.join(itemList)[1:]
                                    else:
                                        match = AstWalker.__examplesStartRE.match(line)
                                        if match and lines[-1].strip() == '#' \
                                           and self.options.autocode:
                                            # We've got an "example" section
                                            inCodeBlock = True
                                            inCodeBlockObj[0] = True
                                            line = line.replace(match.group(0),
                                                                ' @b Examples{0}# @code'.format(linesep))
                                        else:
                                            match = AstWalker.__sectionStartRE.match(line)
                                            if match:
                                                # We've got an arbitrary section
                                                prefix = ''
                                                inSection = True
                                                # What's the indentation of the section heading?
                                                sectionHeadingIndent = len(line.expandtabs(self.options.tablength)) \
                                                    - len(line.expandtabs(self.options.tablength).lstrip())
                                                line = line.replace(
                                                    match.group(0),
                                                    ' @par {0}'.format(match.group(1))
                                                )
                                                if lines[-1] == '# @par':
                                                    lines[-1] = '#'
                                                lines[-1], inCodeBlock = self._endCodeIfNeeded(
                                                    lines[-1], inCodeBlock)
                                                inCodeBlockObj[0] = inCodeBlock
                                                lines.append('#' + line)
                                                continue
                                            elif prefix:
                                                match = AstWalker.__singleListItemRE.match(line)
                                                if match and not inCodeBlock:
                                                    # Probably a single list item
                                                    line = ' {0}\t{1}'.format(
                                                        prefix, match.group(0))
                                                elif self.options.autocode:
                                                    codeChecker.send(
                                                        (
                                                            line, lines,
                                                            lineNum - firstLineNum
                                                        )
                                                    )
                                                    inCodeBlock = inCodeBlockObj[0]
                                            else:
                                                if self.options.autocode:
                                                    codeChecker.send(
                                                        (
                                                            line, lines,
                                                            lineNum - firstLineNum
                                                        )
                                                    )
                                                    inCodeBlock = inCodeBlockObj[0]

                # If we were passed a tail, append it to the docstring.
                # Note that this means that we need a docstring for this
                # item to get documented.
                if tail and lineNum == len(self.docLines) - 1:
                    line = '{0}{1}# {2}'.format(line.rstrip(), linesep, tail)

                # Add comment marker for every line.
                line = '#{0}'.format(line.rstrip())
                # Ensure the first line has the Doxygen double comment.
                if lineNum == 0:
                    line = '#' + line

                lines.append(line.replace(' ' + linesep, linesep))
            else:
                # If we get our sentinel value, send out what we've got.
                timeToSend = True

            if timeToSend:
                lines[-1], inCodeBlock = self._endCodeIfNeeded(lines[-1],
                                                               inCodeBlock)
                inCodeBlockObj[0] = inCodeBlock
                writer.send((firstLineNum, lineNum, lines))
                lines = []
                firstLineNum = -1
                timeToSend = False