'Parse a file and add/update inventory entries for the doctree.
If srcpath is given, read from a different source file.'

def read_doc(self, docname, src_path=None, save_parsed=True, app=None):

    if app:
        app.emit('env-purge-doc', self, docname)
    self.clear_doc(docname)
    if (src_path is None):
        src_path = self.doc2path(docname)
    if self.config.default_role:
        (role_fn, messages) = roles.role(self.config.default_role, english, 0, dummy_reporter)
        if role_fn:
            roles._roles[''] = role_fn
        else:
            self.warn(docname, ('default    role    %s    not    found' % self.config.default_role))
    self.docname = docname
    self.settings['input_encoding'] = self.config.source_encoding
    self.settings['trim_footnote_reference_space'] = self.config.trim_footnote_reference_space
    codecs.register_error('sphinx', self.warn_and_replace)
    codecs.register_error('sphinx', self.warn_and_replace)
    class SphinxSourceClass(FileInput, ):
        def decode(self_, data):
            return data.decode(self_.encoding, 'sphinx')
        def read(self_):
            data = FileInput.read(self_)
            if app:
                arg = [data]
                app.emit('source-read', docname, arg)
                data = arg[0]
            if self.config.rst_epilog:
                return (((data + '\n') + self.config.rst_epilog) + '\n')
            else:
                return data
    pub = Publisher(reader=SphinxStandaloneReader(), writer=SphinxDummyWriter(), source_class=SphinxSourceClass, destination_class=NullOutput)
    pub.set_components(None, 'restructuredtext', None)
    pub.process_programmatic_settings(None, self.settings, None)
    pub.set_source(None, src_path)
    pub.set_destination(None, None)
    try:
        pub.publish()
        doctree = pub.document
    except UnicodeError as err:
        raise SphinxError(str(err))
    self.filter_messages(doctree)
    self.process_dependencies(docname, doctree)
    self.process_images(docname, doctree)
    self.process_downloads(docname, doctree)
    self.process_metadata(docname, doctree)
    self.create_title_from(docname, doctree)
    self.note_labels_from(docname, doctree)
    self.note_indexentries_from(docname, doctree)
    self.note_citations_from(docname, doctree)
    self.build_toc_from(docname, doctree)
    self.all_docs[docname] = time.time()
    if app:
        app.emit('doctree-read', doctree)
    doctree.reporter = None
    doctree.transformer = None
    doctree.settings.warning_stream = None
    doctree.settings.env = None
    doctree.settings.record_dependencies = None
    for metanode in doctree.traverse(MetaBody.meta):
        metanode.__class__ = addnodes.meta
    self.docname = None
    self.currmodule = None
    self.currclass = None
    self.gloss_entries = set()
    if save_parsed:
        doctree_filename = self.doc2path(docname, self.doctreedir, '.doctree')
        dirname = path.dirname(doctree_filename)
        if (not path.isdir(dirname)):
            os.makedirs(dirname)
        f = open(doctree_filename, 'wb')
        try:
            pickle.dump(doctree, f, pickle.HIGHEST_PROTOCOL)
        finally:
            f.close()
    else:
        return doctree
