tree-sitter/lib/binding_rust
James McCoy 889015f03b
build(rust): use $CARGO_PKG_RUST_VERSION when generating bindings (#4512)
Since cargo 1.63, $CARGO_PKG_RUST_VERSION is set in the build
environment to the value of the rust-version Cargo.toml field.

This removes the need to manually invoke cargo from build.rs during a
build of the tree-sitter crate with the bindgen feature enabled.

Removing the cargo invocation also ensures the build doesn't write to
the current directory when the target directory has been redirected
elsewhere. "cargo metadata" will attempt to update Cargo.lock, which
will fail if the source tree is read-only.
2025-06-13 11:11:22 -07:00
..
bindings.rs feat: add error information in the progress callback 2025-01-25 02:47:39 -05:00
build.rs build(rust): use $CARGO_PKG_RUST_VERSION when generating bindings (#4512) 2025-06-13 11:11:22 -07:00
ffi.rs fix(rust): use core crates for no_std 2025-03-25 14:30:32 +01:00
lib.rs fix(bindings): report wasm store error in rust bindings set_language 2025-04-14 22:15:40 -04:00
README.md docs(rust): remove adding cc as a build dependency for consumers 2025-04-28 18:30:45 -04:00
util.rs feat(lib): support no_std 2024-07-28 11:34:26 +03:00
wasm_language.rs feat(lib): implement Send + Sync for WasmStore 2025-01-21 00:21:35 -05:00

Rust Tree-sitter

crates.io badge

Rust bindings to the Tree-sitter parsing library.

Basic Usage

First, create a parser:

use tree_sitter::{InputEdit, Language, Parser, Point};

let mut parser = Parser::new();

Then, add a language as a dependency:

[dependencies]
tree-sitter = "0.24"
tree-sitter-rust = "0.23"

To use a language, you assign them to the parser.

parser.set_language(&tree_sitter_rust::LANGUAGE.into()).expect("Error loading Rust grammar");

Now you can parse source code:

let source_code = "fn test() {}";
let mut tree = parser.parse(source_code, None).unwrap();
let root_node = tree.root_node();

assert_eq!(root_node.kind(), "source_file");
assert_eq!(root_node.start_position().column, 0);
assert_eq!(root_node.end_position().column, 12);

Editing

Once you have a syntax tree, you can update it when your source code changes. Passing in the previous edited tree makes parse run much more quickly:

let new_source_code = "fn test(a: u32) {}";

tree.edit(&InputEdit {
  start_byte: 8,
  old_end_byte: 8,
  new_end_byte: 14,
  start_position: Point::new(0, 8),
  old_end_position: Point::new(0, 8),
  new_end_position: Point::new(0, 14),
});

let new_tree = parser.parse(new_source_code, Some(&tree));

Text Input

The source code to parse can be provided either as a string, a slice, a vector, or as a function that returns a slice. The text can be encoded as either UTF8 or UTF16:

// Store some source code in an array of lines.
let lines = &[
    "pub fn foo() {",
    "  1",
    "}",
];

// Parse the source code using a custom callback. The callback is called
// with both a byte offset and a row/column offset.
let tree = parser.parse_with(&mut |_byte: usize, position: Point| -> &[u8] {
    let row = position.row as usize;
    let column = position.column as usize;
    if row < lines.len() {
        if column < lines[row].as_bytes().len() {
            &lines[row].as_bytes()[column..]
        } else {
            b"\n"
        }
    } else {
        &[]
    }
}, None).unwrap();

assert_eq!(
  tree.root_node().to_sexp(),
  "(source_file (function_item (visibility_modifier) (identifier) (parameters) (block (number_literal))))"
);

Using WASM Grammar Files

Requires the feature wasm to be enabled.

First, create a parser with a WASM store:

use tree_sitter::{wasmtime::Engine, Parser, WasmStore};

let engine = Engine::default();
let store = WasmStore::new(&engine).unwrap();

let mut parser = Parser::new();
parser.set_wasm_store(store).unwrap();

Then, load the language from a WASM file:

const JAVASCRIPT_GRAMMAR: &[u8] = include_bytes!("path/to/tree-sitter-javascript.wasm");

let mut store = WasmStore::new(&engine).unwrap();
let javascript = store
    .load_language("javascript", JAVASCRIPT_GRAMMAR)
    .unwrap();

// The language may be loaded from a different WasmStore than the one set on
// the parser but it must use the same underlying WasmEngine.
parser.set_language(&javascript).unwrap();

Now you can parse source code:

let source_code = "let x = 1;";
let tree = parser.parse(source_code, None).unwrap();

assert_eq!(
    tree.root_node().to_sexp(),
    "(program (lexical_declaration (variable_declarator name: (identifier) value: (number))))"
);

Features

  • std - This feature is enabled by default and allows tree-sitter to use the standard library.
    • Error types implement the std::error:Error trait.
    • regex performance optimizations are enabled.
    • The DOT graph methods are enabled.
  • wasm - This feature allows tree-sitter to be built for Wasm targets using the wasmtime-c-api crate.