In applications like text editors, you often need to re-parse a file after its source code has changed. Tree-sitter is designed to support this use case efficiently through incremental parsing.
When you edit a syntax tree, the positions of its nodes will change. If you have stored any TSNode instances outside of the TSTree, you must update them separately:
void ts_node_edit(TSNode *, const TSInputEdit *);
The ts_node_edit function is only needed when you have retrieved TSNode instances before editing the tree and want to continue using those specific instances afterward. Often, you’ll just re-fetch nodes from the edited tree, in which case ts_node_edit is not needed.
Sometimes, different parts of a file may be written in different languages. For example, templating languages like EJS and ERB allow you to generate HTML by writing a mixture of HTML and another language like JavaScript or Ruby.Tree-sitter handles these types of documents by allowing you to create a syntax tree based on the text in certain ranges of a file.
This API allows for great flexibility in how languages can be composed. Tree-sitter is not responsible for mediating the interactions between languages — you’re free to do that using arbitrary application-specific logic.
Tree-sitter supports multi-threaded use cases by making syntax trees very cheap to copy.
TSTree *ts_tree_copy(const TSTree *);
Internally, copying a syntax tree just entails incrementing an atomic reference count. Conceptually, it provides you a new tree which you can freely query, edit, reparse, or delete on a new thread while continuing to use the original tree on a different thread.
#include <pthread.h>#include <tree_sitter/api.h>void *analyze_tree(void *tree_ptr) { TSTree *tree = (TSTree *)tree_ptr; TSNode root = ts_tree_root_node(tree); // Perform analysis... ts_tree_delete(tree); return NULL;}int main() { TSParser *parser = ts_parser_new(); // ... setup and parse ... TSTree *tree = ts_parser_parse_string(parser, NULL, source, len); // Create a copy for use in another thread TSTree *tree_copy = ts_tree_copy(tree); pthread_t thread; pthread_create(&thread, NULL, analyze_tree, tree_copy); // Continue using the original tree TSNode root = ts_tree_root_node(tree); // ... pthread_join(thread, NULL); ts_tree_delete(tree); ts_parser_delete(parser); return 0;}
Individual TSTree instances are not thread safe. You must copy a tree if you want to use it on multiple threads simultaneously.
This function returns an array of ranges whose syntactic structure has changed between the old and new trees. The returned array is allocated using malloc and must be freed by the caller.
The returned ranges indicate areas where the hierarchical structure of syntax nodes (from root to leaf) has changed. Characters outside these ranges have identical ancestor nodes in both trees. The ranges may be slightly larger than the exact changed areas, but Tree-sitter attempts to make them as small as possible.