'Parse a sentence.
:param extractor: a function that given a tuple of cells returns a
7-tuple, where the values are ``word, lemma, ctag, tag, feats, head,
rel``.
:param str cell_separator: the cell separator. If not provided, cells
are split by whitespace.
:param str top_relation_label: the label by which the top relation is
identified, for examlple, `ROOT`, `null` or `TOP`.'

def _parse(self, input_, cell_extractor=None, zero_based=False, cell_separator=None, top_relation_label=u'ROOT'):

    def extract_3_cells(cells, index):
        (word, tag, head) = cells
        return (index, word, word, tag, tag, u'', head, u'')
    def extract_4_cells(cells, index):
        (word, tag, head, rel) = cells
        return (index, word, word, tag, tag, u'', head, rel)
    def extract_7_cells(cells, index):
        (line_index, word, lemma, tag, _, head, rel) = cells
        try:
            index = int(line_index)
        except ValueError:
            pass
        return (index, word, lemma, tag, tag, u'', head, rel)
    def extract_10_cells(cells, index):
        (line_index, word, lemma, ctag, tag, feats, head, rel, _, _) = cells
        try:
            index = int(line_index)
        except ValueError:
            pass
        return (index, word, lemma, ctag, tag, feats, head, rel)
    extractors = {3: extract_3_cells, 4: extract_4_cells, 7: extract_7_cells, 10: extract_10_cells}
    if isinstance(input_, string_types):
        input_ = (line for line in input_.split(u'\n'))
    lines = (l.rstrip() for l in input_)
    lines = (l for l in lines if l)
    cell_number = None
    for (index, line) in enumerate(lines, start=1):
        cells = line.split(cell_separator)
        if (cell_number is None):
            cell_number = len(cells)
        else:
            assert (cell_number == len(cells))
        if (cell_extractor is None):
            try:
                cell_extractor = extractors[cell_number]
            except KeyError:
                raise ValueError(u'Number    of    tab-delimited    fields    ({0})    not    supported    by    CoNLL(10)    or    Malt-Tab(4)    format'.format(cell_number))
        try:
            (index, word, lemma, ctag, tag, feats, head, rel) = cell_extractor(cells, index)
        except (TypeError, ValueError):
            (word, lemma, ctag, tag, feats, head, rel) = cell_extractor(cells)
        if (head == u'_'):
            continue
        head = int(head)
        if zero_based:
            head += 1
        self.nodes[index].update({u'address': index, u'word': word, u'lemma': lemma, u'ctag': ctag, u'tag': tag, u'feats': feats, u'head': head, u'rel': rel})
        if ((cell_number == 3) and (head == 0)):
            rel = top_relation_label
        self.nodes[head][u'deps'][rel].append(index)
    if self.nodes[0][u'deps'][top_relation_label]:
        root_address = self.nodes[0][u'deps'][top_relation_label][0]
        self.root = self.nodes[root_address]
        self.top_relation_label = top_relation_label
    else:
        warnings.warn(u"The    graph    doesn't    contain    a    node    that    depends    on    the    root    element.")
