libtree-sitter) for runtime parsing, and a Rust-based CLI for parser generation.
Architecture Overview
The C Library (libtree-sitter)
The runtime library is written in plain C for maximum portability and embeddability.Core API
The public interface is defined intree_sitter/api.h:
Key Components
The library source is organized into focused modules:parser.c- Main parsing algorithm and state managementlexer.c- Lexical analysis and token generationnode.c- Syntax tree node operationslanguage.c- Language definition and version managementget_changed_ranges.c- Incremental parsing supportalloc.c- Memory allocation with custom allocators
Memory Management
Tree-sitter uses reference counting for tree sharing:Incremental Parsing
Tree-sitter achieves efficiency through incremental parsing:The CLI (tree-sitter)
The CLI is written in Rust and available via:Parser Generation Pipeline
Thetree-sitter generate command transforms grammars through several stages:
1. Grammar Parsing
Implemented inparse_grammar.rs:
Grammar format is formally specified in
grammar.schema.json.2. Grammar Rules
Grammars are composed of rule types defined inrules.rs:
3. Grammar Preparation
Theprepare_grammar module transforms grammars:
Transformations include:
- Inlining - Expand inline rules
- Precedence extraction - Identify operator precedence
- Associativity handling - Process left/right associativity
- Token extraction - Separate tokens from syntax rules
- Conflict resolution - Handle ambiguities
- Syntax grammar - How non-terminals combine
- Lexical grammar - How terminals (tokens) are formed
4. Parse Table Generation
The CLI generates LR parsing tables:5. Code Generation
The final step emitsparser.c:
Grammar DSL Deep Dive
The grammar DSL provides several powerful constructs:Fields
Precedence
Conflicts
When the grammar is ambiguous:External Scanner
For context-sensitive lexing:scanner.c or scanner.cc.
Query System Architecture
Queries use a separate compilation process:Query Compilation
- Parse query S-expression
- Validate against language symbols
- Compile to pattern-matching bytecode
- Index by capture names
Query Execution
Predicate System
Predicates are evaluated at runtime:#eq?,#not-eq?- String equality#match?,#not-match?- Regex matching#any-of?,#not-any-of?- Set membership#is?,#is-not?- Property checks#set!- Set properties
Language ABI Versioning
Parsers declare their ABI version:Error Recovery
Tree-sitter performs automatic error recovery:ERROR Node Insertion
When parsing fails, anERROR node is inserted:
MISSING Node Insertion
For expected but absent tokens:Recovery Strategy
The parser:- Detects an unexpected token
- Inserts ERROR node
- Skips tokens until finding a recovery point
- Resumes parsing
Performance Characteristics
Time Complexity
- Full parse: O(n) where n = source length
- Incremental parse: O(e log n) where e = edit size
- Query execution: O(n × p) where p = pattern complexity
Space Complexity
- Syntax tree: O(n) nodes
- Parse stack: O(d) where d = max nesting depth
- Shared subtrees: Zero extra cost due to reference counting
Optimization Techniques
- Subtree reuse - Unchanged regions share nodes
- Lazy node materialization - Nodes created on access
- Arena allocation - Batch allocations reduce overhead
- Stack-based parsing - No heap allocation during parse
Related Resources
Performance
Learn optimization techniques
Creating Parsers
Build your own parser