':return: A list of lines composing a string representation of
this feature dictionary.
:param reentrances: A dictionary that maps from the ``id`` of
each feature value in self, indicating whether that value
is reentrant or not.
:param reentrance_ids: A dictionary mapping from each ``id``
of a feature value to a unique identifier.  This is modified
by ``repr``: the first time a reentrant feature value is
displayed, an identifier is added to ``reentrance_ids`` for
it.'

def _str(self, reentrances, reentrance_ids):

    if reentrances[id(self)]:
        assert (id(self) not in reentrance_ids)
        reentrance_ids[id(self)] = repr((len(reentrance_ids) + 1))
    if (len(self) == 0):
        if reentrances[id(self)]:
            return [(u'(%s)    []' % reentrance_ids[id(self)])]
        else:
            return [u'[]']
    maxfnamelen = max((len((u'%s' % k)) for k in self.keys()))
    lines = []
    for (fname, fval) in sorted(self.items()):
        fname = (u'%s' % fname).ljust(maxfnamelen)
        if isinstance(fval, Variable):
            lines.append((u'%s    =    %s' % (fname, fval.name)))
        elif isinstance(fval, Expression):
            lines.append((u'%s    =    <%s>' % (fname, fval)))
        elif isinstance(fval, FeatList):
            fval_repr = fval._repr(reentrances, reentrance_ids)
            lines.append((u'%s    =    %s' % (fname, unicode_repr(fval_repr))))
        elif (not isinstance(fval, FeatDict)):
            lines.append((u'%s    =    %s' % (fname, unicode_repr(fval))))
        elif (id(fval) in reentrance_ids):
            lines.append((u'%s    ->    (%s)' % (fname, reentrance_ids[id(fval)])))
        else:
            if (lines and (lines[(-1)] != u'')):
                lines.append(u'')
            fval_lines = fval._str(reentrances, reentrance_ids)
            fval_lines = [((u'    ' * (maxfnamelen + 3)) + l) for l in fval_lines]
            nameline = ((len(fval_lines) - 1) // 2)
            fval_lines[nameline] = ((fname + u'    =') + fval_lines[nameline][(maxfnamelen + 2):])
            lines += fval_lines
            lines.append(u'')
    if (lines[(-1)] == u''):
        lines.pop()
    maxlen = max((len(line) for line in lines))
    lines = [(u'[    %s%s    ]' % (line, (u'    ' * (maxlen - len(line))))) for line in lines]
    if reentrances[id(self)]:
        idstr = (u'(%s)    ' % reentrance_ids[id(self)])
        lines = [((u'    ' * len(idstr)) + l) for l in lines]
        idline = ((len(lines) - 1) // 2)
        lines[idline] = (idstr + lines[idline][len(idstr):])
    return lines
