def _parse_nodes(
        self,
        nodes: Sequence[BaseNode],
        show_progress: bool = False,
        **kwargs: Any,
    ) -> List[BaseNode]:
        """
        The main public method of this class.

        Parse documents into nodes.
        """
        out: List[BaseNode] = []

        try:
            import tree_sitter_language_pack
        except ImportError:
            raise ImportError(
                "Please install tree_sitter_language_pack to use CodeSplitter."
            )

        try:
            parser = tree_sitter_language_pack.get_parser(self.language)
            language = tree_sitter_language_pack.get_language(self.language)

            # Construct the path to the SCM file
            scm_fname = os.path.join(
                os.path.dirname(os.path.abspath(__file__)),
                "pytree-sitter-queries",
                f"tree-sitter-{self.language}-tags.scm",
            )
        except Exception as e:
            print(
                f"Could not get parser for language {self.language}. Check "
                "https://github.com/Goldziher/tree-sitter-language-pack?tab=readme-ov-file#available-languages "
                "for a list of valid languages."
            )
            raise e  # noqa: TRY201

        query = None
        if self.signature_identifiers is None:
            assert os.path.exists(scm_fname), f"Could not find {scm_fname}"
            fp = open(scm_fname)
            query_scm = fp.read()
            query = language.query(query_scm)

        nodes_with_progress = get_tqdm_iterable(
            nodes, show_progress, "Parsing documents into nodes"
        )

        for node in nodes_with_progress:
            text = node.text
            tree = parser.parse(bytes(text, "utf-8"))

            if self.signature_identifiers is None:
                assert query is not None
                self.signature_identifiers = {}
                tag_to_type = {}
                captures = query.captures(tree.root_node)
                for _node, _tag in captures:
                    tag_to_type[_tag] = _node.type
                    if _tag.startswith("name.definition"):
                        # ignore name.
                        parent_tag = _tag[5:]
                        assert parent_tag in tag_to_type
                        parent_type = tag_to_type[parent_tag]
                        if parent_type not in self.signature_identifiers:
                            self.signature_identifiers[parent_type] = (
                                _SignatureCaptureOptions(name_identifier=_node.type)
                            )

            if (
                not tree.root_node.children
                or tree.root_node.children[0].type != "ERROR"
            ):
                # Chunk the code
                _chunks = self._chunk_node(tree.root_node, node.text)
                assert _chunks.this_document is not None, "Root node must be a chunk"
                chunks = _chunks.all_documents

                # Add your metadata to the chunks here
                for chunk in chunks:
                    chunk.metadata = {
                        "language": self.language,
                        **chunk.metadata,
                        **node.metadata,
                    }
                    chunk.relationships[NodeRelationship.SOURCE] = (
                        node.as_related_node_info()
                    )

                if self.skeleton:
                    self._skeletonize_list(chunks)

                # Now further split the code by lines and characters
                # TODO: Test this and the relationships it creates
                if self.code_splitter:
                    new_nodes = []
                    for original_node in chunks:
                        new_split_nodes = self.code_splitter.get_nodes_from_documents(
                            [original_node], show_progress=show_progress, **kwargs
                        )

                        if not new_split_nodes:
                            continue

                        # Force the first new_split_node to have the
                        # same id as the original_node
                        new_split_nodes[0].id_ = original_node.id_

                        # Add the UUID of the next node to the end of all nodes
                        for i, new_split_node in enumerate(new_split_nodes[:-1]):
                            new_split_node.text = (
                                new_split_node.text
                                + "\n"
                                + self._create_comment_line(new_split_nodes[i + 1], 0)
                            ).strip()

                        # Add the UUID of the previous node to the beginning of all nodes
                        for i, new_split_node in enumerate(new_split_nodes[1:]):
                            new_split_node.text = (
                                self._create_comment_line(new_split_nodes[i])
                                + new_split_node.text
                            ).strip()

                        # Add the parent child info to all the new_nodes_
                        # derived from node
                        for new_split_node in new_split_nodes:
                            new_split_node.relationships[NodeRelationship.CHILD] = (
                                original_node.child_nodes
                            )  # type: ignore
                            new_split_node.relationships[NodeRelationship.PARENT] = (
                                original_node.parent_node
                            )  # type: ignore

                        # Go through chunks and replace all
                        # instances of node.node_id in relationships
                        # with new_nodes_[0].node_id
                        for old_node in chunks:
                            # Handle child nodes, which are a list
                            new_children = []
                            for old_nodes_child in old_node.child_nodes or []:
                                if old_nodes_child.node_id == original_node.node_id:
                                    new_children.append(
                                        new_split_nodes[0].as_related_node_info()
                                    )
                                new_children.append(old_nodes_child)
                            old_node.relationships[NodeRelationship.CHILD] = (
                                new_children
                            )

                            # Handle parent node
                            if (
                                old_node.parent_node
                                and old_node.parent_node.node_id
                                == original_node.node_id
                            ):
                                old_node.relationships[NodeRelationship.PARENT] = (
                                    new_split_nodes[0].as_related_node_info()
                                )

                        # Now save new_nodes_
                        new_nodes += new_split_nodes

                    chunks = new_nodes

                # Or just extract metadata
                if self.metadata_extractor:
                    chunks = self.metadata_extractor.process_nodes(  # type: ignore
                        chunks
                    )

                out += chunks
            else:
                raise ValueError(f"Could not parse code with language {self.language}.")

        return out

        The main public method of this class.

        Parse documents into nodes.
        
llama-index-packs/llama-index-packs-code-hierarchy/llama_index/packs/code_hierarchy/code_hierarchy.py