Commit graph

179 commits

Author SHA1 Message Date
Will Lillis 65e8b25413
wip(generate): emit 3-way per-state parse table layout (plan B)
Replace the per-grammar CSR-vs-hybrid choice with a per-state picker
that places each state in the smallest of dense / CSR / small. State
ids are partitioned into contiguous tiers [Dense | CSR | Small] driven
by `large_state_count` and a new `csr_state_count` field on
TSLanguage. The runtime dispatches on two range checks; the rest of
the lookup logic per tier is unchanged.

States 0 (error) and 1 (start state) are pinned to the Dense tier so
they remain at indices 0 and 1, matching the runtime's hard-coded
expectations. Cost is bounded at ~2 * SYMBOL_COUNT * 2 bytes per
grammar.

Cleanup: drop --table-fmt CLI, OptLevel::ForceHybridTable /
ForceCompressedTable, RenderError::ConflictingParseTableFlags,
heuristic_should_compress, and use_compressed_tables since the free
picker provably picks the smallest representation per state.

Tests pass against the regenerated fixtures. The size savings are
measured in a follow-up corpus run.
2026-05-19 18:18:20 -04:00
Will Lillis ea90489d7a
perf(generate): add CSR-compressed parse tables (ABI 16)
Apply Compressed Sparse Row (CSR) compression to the parse table for
grammars that benefit, replacing the original dense + small split with
three flat arrays:

  uint32_t parse_table_row_offsets[STATE_COUNT + 1]
  uint16_t parse_table_columns[TOTAL_NNZ]
  uint16_t parse_table_values[TOTAL_NNZ]

Heuristic for enabling CSR (per grammar, all three must hold):

  1. LARGE_STATE_COUNT * SYMBOL_COUNT > STATE_COUNT * 40
     Ensures the dense table is large enough relative to total state
     count that savings outweigh the small-state grouping penalty.

  2. dense table density < 45%
     Ensures CSR actually saves space. Above ~50% density, CSR's
     per-entry column indices cost more than the zeros they eliminate.
     45% adds margin below the theoretical crossover.

  3. LARGE_STATE_COUNT * SYMBOL_COUNT > 50,000
     Avoids applying a format change to tiny grammars where fixed
     overhead dominates.

Co-authored-by: Tuomas Hietanen <thorium@iki.fi>
2026-05-19 17:57:49 -04:00
Will Lillis f535c3bb97 fix(test): write fixture headers once
Several test functions compile the same grammar fixture.
Tests sharing a grammar name also share a src_dir. Each test also
unconditionally writes the three tree-sitter headers into
src_dir/tree_sitter/, leading to a race.

Write the three headers exactly once per src_dir, controlled via a
global `HashSet`.
2026-05-17 19:55:37 -04:00
Will Lillis 71040925fe perf(cli): stream CST rendering via Display wrappers
Co-authored-by: Amaan Qureshi <git@amaanq.com>
2026-05-17 15:02:08 -04:00
Will Lillis ffea4e8e58 fix(cli): rework coloring abstraction and fix NO_COLOR handling
Co-authored-by: Amaan Qureshi <git@amaanq.com>
2026-05-17 15:02:08 -04:00
Will Lillis 5cac4316db fix(cli): account for process versions > 5 in the parse command's pretty
debug output.

The initial implementation of `--debug pretty` assumed process version
was bounded by `MAX_VERSION_COUNT`. However, we also have to account for
`MAX_VERSION_COUNT_OVERFLOW` as well as `halted_version_count`.
2026-05-05 18:17:07 -04:00
Daniel Jalkut 0f6780b9a3 lexer: pass code-unit length to U16_NEXT in UTF-16 decoders
`ts_decode_utf16_le` and `ts_decode_utf16_be` passed a byte length to
`U16_NEXT_LE` and `U16_NEXT_BE`, but those macros count `uint16_t` code
units. If a lead surrogate was the last code unit in a chunk, the decoder
could peek past the chunk and combine it with adjacent memory.

This commit passes the code-unit length to the UTF-16 macros, and fails
with `TS_DECODE_ERROR` when a chunk is too short to contain even one full
code unit. This lets the lexer retry with a fresh chunk or advance through
the invalid byte as it already does.

Co-authored-by: Will Lillis <will.lillis24@gmail.com>
Co-authored-by: Amaan Qureshi <git@amaanq.com>
2026-04-26 03:38:47 -04:00
Volker Mische 4cb11acd46
fix(loader): allow filenames with dots (#5529) 2026-04-22 03:41:04 -04:00
Chinmay Dalal 20bdf3a8a0
feat(bindings): update zig template to 0.16 2026-04-20 09:31:18 +02:00
changw98ic aff9b9d92e fix: update broken link to Parser.Language in template
The link `https://tree-sitter.github.io/node-tree-sitter/interfaces/Parser.Language.html` returns a 404 error.

In the current typedoc output, the Language interface is at `/interfaces/Language.html` (without the `Parser.` prefix), as the documentation flattens namespace members.

Fixes #5525
2026-04-17 08:20:05 +02:00
Will Lillis 8eafafaa16 fix(test): split up cli testing test
Now that the loader race condition is resolved, these tests no longer
need to be grouped together.
2026-03-31 04:00:43 -04:00
Will Lillis 3294a64027 perf(cli): replace regex with manual parsing in test file parser
This started as a simple one to one rewrite, just removing the regexes,
and quickly devolved into a rewrite of the test parsing logic. In
addition to the memory enhancements, the general flow should be much
clearer now. A few data points:

- JS:   walltime -1.3%, peak rss -10.2%
- C:    walltime -5.7%, peak rss -4.5%
- Rust: walltime -3.8%, peak rss -2.2%
2026-03-31 04:00:43 -04:00
Max Brunsfeld d3ff0ce81d
Fix wasm loading of languages w/ multiple reserved word sets (#5475) 2026-03-30 22:27:57 -07:00
Will Lillis 791d7cead4 perf(cli): minor allocation and write call reductions
- Cache tree byte range length to avoid redundant FFI calls per test
- Combine 5 separate XML attribute write! calls into one
- Pre-allocate format_sexp output buffer to avoid repeated growth
2026-03-31 01:27:05 -04:00
Will Lillis 827bcdabd9 perf(cli): buffer stdout in parse and query output
Wrap stdout in a 64KB BufWriter when writing `parse` output. The tree
walking loop makes many small write calls (parentheses, indentation,
node kinds, ranges, etc.) which are expensive without buffering.

When parsing the jquery.js corpus file, cuts the total time roughly in
half. These savings only show when piping the result to a file,
otherwise terminal rendering time usually dominates, hiding all gains.

Also do the same for the `query` command's output.
2026-03-31 01:27:05 -04:00
Will Lillis 1ec3b3aabe generate: remove comment cleaning for grammar.json
A quick search through github shows that nobody utilizes this, so it's
effectively dead code.
2026-03-31 01:23:15 -04:00
Will Lillis cf8719f132 fix(rust): correct various typos 2026-03-28 05:23:10 -04:00
Will Lillis 1a82df3cac fix(rust): address new nightly lints 2026-03-28 05:23:10 -04:00
Riley Bruins cf302b07d1 fix(query): don't add copies for quantifier steps outside alternations 2026-03-04 10:32:50 +01:00
John Eismeier 1f9b274dfb
chore: fix typos in messages and documentation
Signed-off-by: John E <jeis4wpi@outlook.com>
2026-03-01 11:40:15 +01:00
MFS-code 146ea6e12b fix: skip missing Makefile in version command 2026-02-27 10:01:59 +01:00
Amaan Qureshi 0561079b6e cli(init): extract per-binding generators and named update functions
This commit just refactors the init command's update code, as it's quite messy. The main changes are that most bindings now go through their own generate_{lang} function.
2026-02-27 02:13:03 -05:00
Will Lillis 6ae37120b3 fix(cli): correct condition to perform __init__.py replacement for
`tree-sitter init -u` command
2026-02-23 22:53:06 -05:00
Will Lillis 5210ca0b51 fix(cli): update tree-sitter init -u for recent Package.swift
changes
2026-02-23 22:53:06 -05:00
Will Lillis f1f493e59e fix(cli): actually write updated Package.swift file 2026-02-23 22:53:06 -05:00
Amaan Qureshi 787800dda6 cli(init): fix Package.swift scanner detection when used as a dependency
The template used `FileManager.default.fileExists(atPath: "src/scanner.c")` with a relative path, which resolves against the process cwd. When SwiftPM evaluates a dependency's manifest, the cwd is the consumer's directory, so the check returns `false` even when `scanner.c` exists, causing undefined symbol linker errors.

This commit uses `Context.packageDirectory`, which is available since `swift-tools-version:5.6`, to resolve the path against the package root. This does bump the minimum tools version from 5.3 to 5.6.
2026-02-22 10:55:16 -05:00
Will Lillis 256df9304f rust: explicitly align CLI's encoding enum with constants from
tree_sitter::ffi
2026-02-18 01:54:20 -05:00
Will Lillis 27e1199387 feat(highlight)!: utf16 support 2026-02-18 01:54:20 -05:00
Amaan Qureshi b8fcf27661 build(rust): update deps 2026-02-18 00:59:34 -05:00
Amaan Qureshi ebd2a56b5d treewide: add taplo config and reformat toml files 2026-02-18 00:59:34 -05:00
Amaan Qureshi 7deb5092c6 cli: fix clippy warnings from edition bump 2026-02-18 00:59:34 -05:00
Will Lillis 596a4d69bb fix(query): prevent cross-branch capture contamination in alternations with quantifiers
When a branch inside an alternation has a + or * quantifier, the
quantifier's pass_through step loops back to the branch's first step.
The alternation linking also sets that step's alternative_index to
point to the next branch. This causes the quantifier loop-back to
incorrectly explore other branches in the case of a failed match that
follows a successful match, contaminating captures.

This is corrected by redirecting the quantifier loop-back to a
"clean" copy of the target step without the alternative index pointing
to the next alternation branch.

Co-authored-by: Riley Bruins <ribru17@hotmail.com>
2026-02-09 21:57:29 -05:00
Will Lillis 48e921883a fix(rust)!: return u32 from Node::child_count
This matches the type returned from the underlying C library, and also
composes more cleanly with other functions like `Node::child`
2026-02-09 21:05:48 -05:00
Will Lillis 9dd09fec1e fix(cli): require tree-sitter CLI in CMake template 2026-02-08 18:40:57 -05:00
Will Lillis 73b2f981d5 fix(cli): allow for both debug logs and graphs 2026-02-07 17:03:56 -05:00
Will Lillis eab567a02d fix(rust): place std::env::set_var inside unsafe blocks
This is optional for the 2021 but required for 2024. The function is
unsafe either way and should be marked as such.
2026-02-02 04:29:13 -05:00
Will Lillis 7e1d8add13 feat(cli): add --verbose flag to build command
This displays the working directory of the command (if present),
compiler used, all of its arguments, any environment variables set,
and anything written to stdout/stderr by the compilation tool.
2026-02-01 13:00:02 -05:00
Will Lillis 0b8f124453 fix(cli): include default values for --edits and --iterations in
`fuzz` command help
2026-02-01 12:31:13 -05:00
Will Lillis c9d9ce6cbb fix(cli): use --edits value for fuzz tests 2026-02-01 12:31:13 -05:00
Will Lillis 337e20e0f2 fix(wasm): when reallocating the last allocated region, properly grow
the region in place.

Previous changes to `malloc` caused `realloc` to sometimes pull regions
off of the free list during this optimization. Because no `memcpy` is
performed, this resulted in corrupted data returning to the caller.

Co-authored-by: trim21 <i@trim21.me>
2026-01-31 18:24:31 -05:00
Will Lillis 8fe076695f test: rename wasm corpus test "wasm_realloc"->"wasm_realloc_overflow_heap" 2026-01-31 18:24:31 -05:00
Will Lillis 634ba3a1f7 fix(wasm): correct several bugs in realloc
- free memory if 0 size is passed in
- Don't `memcpy` contents if new pointer is `NULL`
- Copy old region's contents only up to size of new region
- free old region

Co-authored-by: trim21 <i@trim21.me>
2026-01-26 21:14:14 -05:00
Will Lillis 8f4df58983 fix(init): correct paths in rust bindings on Windows 2026-01-25 17:18:43 -05:00
Tam1SH ae8184b8b9 docs(playground): highlight full row for highlighted nodes 2026-01-18 23:48:58 -05:00
DanikVitek b12009a746 fix: Clarify/fix lifetimes
- One has to think about lifetimes if a type has one:
  - `<&'a Node<'tree>>::language` now returns `LanguageRef<'tree>` instead of
    `LanguageRef<'a>`, as it should;
- Remove explicit "outlives" requirements from `QueryMatches`, `QueryCaptures`,
  and their impl blocks, because they're inferred
- Removed unnecessary `&mut` from `cst_render_node`'s `cursor` parameter
2026-01-17 00:14:21 -05:00
Kevin Wang 630fa52717 fix(templates): fix python free-threading compatibility 2026-01-09 11:44:41 +02:00
skewb1k 17e3c7a5c5 fix(cli): restore test summary output for tree-sitter test
Problem:
After commit f02d7e7e33
the `tree-sitter test` command no longer printed the final test summary,
leaving empty line. The `Stats` struct was embedded into `TestSummary`,
and the explicit call to print it was removed.

Solution:
Print `parse_stats` from `TestSummary.fmt()` implementation.
2026-01-04 21:31:11 -08:00
WillLillis dd60d5cff0 feat(cli): fill in missing fields to tree-sitter.json when running
`tree-sitter init -u`
2025-12-31 14:08:09 -05:00
WillLillis f1288ea5c9 fix(cli): increase verbosity of tree-sitter init -u updates
Also, use `info` logs rather than `warn`
2025-12-31 14:08:09 -05:00
skewb1k 0d4d854809 feat(cli): make test --update rewrite all corpus files 2025-12-31 01:43:48 -05:00