Skip to main content

lang-parsing-substrate

A shared language-parsing substrate for static-analysis tools: tree-sitter grammar dispatch, language detection, and a growing set of language-agnostic analysis primitives (import/call graphs, control-flow graphs, structural fingerprinting, suppression comments) built on top of a unified LanguageInfo registry across 16 languages — compiled in at build time via Cargo feature flags.

What's in the substrate

Module Provides
registry Language detection by extension, the LanguageInfo table, SLOC comment-style metadata
classify Cheap heuristic pre-parse file classification from a bounded byte prefix + size: SourceText / Binary / Oversize / Empty, so consumers can skip a 2 GB zip named .c before it reaches tree-sitter
query Iterative (non-recursive) tree-sitter traversal helpers: find_descendants, find_first_descendant, node_text, ancestor lookups
flat A whole parse tree as flat, index-linked columns (flatten → FlatTree), so a consumer that cannot hold a tree_sitter::Node (Python) can still walk every node
tsquery Run a tree-sitter query and return owned captures (run_query), plus each grammar's bundled tags query (tags_query)
imports Per-file import/use-statement extraction, for building efferent-coupling (Ce) edges
calls Per-file call-graph edge extraction (caller → callee), with external-call detection
cfg Control-flow graph / basic-block construction for a function body (c, cpp, rust)
c_standard Best-effort lower bound on the C standard (C99/C11/C23) a file's syntax requires
fingerprint Structural hashing of function-like subtrees, for duplicate/clone detection across a corpus
regions tools:off / tools:on ignored-region markers
suppressions tools:suppress TOOL:RULE single-line suppression comments
dead_code Preprocessor dead-code regions for C/C++ (#if 0, __cplusplus-gated branches, locally-provable macro definedness)
dead_code_swift Dead-code regions for Swift's #if/#elseif/#else conditional compilation (compile-time-constant boolean conditions only — see module docs for why the C/C++ macro-definedness sub-problem doesn't apply to Swift)
dead_code_csharp Dead-code regions for C#'s #if/#elif/#else conditional compilation — AST-based like dead_code_swift, but ports both C/C++ sub-problems (constant conditions and locally-provable #define/#undef symbol definedness) since C# has real nested preprocessor nodes and real #define
path_ignore Compiled glob ignore-pattern sets for path filtering

Everything below the registry is deliberately per-file: a module extracts what one parse tree contains, and leaves assembling a corpus-wide graph, dedup report, or coupling metric to the caller. This keeps the substrate's job narrow (one authoritative, correct answer per file) and lets each consumer choose its own storage model (in-memory, SQLite, whatever) without the substrate needing to know about it.

Language coverage varies by module — the registry knows about all 16 languages, but modules like cfg only model the languages they've been built out for. A module never fabricates a result for a language it doesn't support; it returns None (or an empty result) instead of guessing.

Feature flags

Not every consumer needs all 16 languages. Each language is an optional Cargo feature; the all-languages convenience feature (enabled by default) pulls in the full set.

Feature Language Grammar crate
lang-c C tree-sitter-c
lang-cpp C++ tree-sitter-cpp
lang-rust Rust tree-sitter-rust
lang-python Python tree-sitter-python
lang-javascript JavaScript tree-sitter-javascript
lang-typescript TypeScript tree-sitter-typescript
lang-go Go tree-sitter-go
lang-java Java tree-sitter-java
lang-csharp C# tree-sitter-c-sharp
lang-kotlin Kotlin tree-sitter-kotlin-ng
lang-swift Swift tree-sitter-swift
lang-php PHP tree-sitter-php
lang-ada Ada tree-sitter-ada
lang-fortran Fortran (free-form) tree-sitter-fortran
lang-scala Scala tree-sitter-scala
lang-lua Lua tree-sitter-lua
all-languages All of the above —

A consumer that only cares about C/C++, for example, would declare:

lang-parsing-substrate = { version = "0.5", default-features = false, features = ["lang-c", "lang-cpp"] }

Usage

# Cargo.toml — full language set (default)
lang-parsing-substrate = "0.5"

# Cargo.toml — C/C++ only
lang-parsing-substrate = { version = "0.5", default-features = false, features = ["lang-c", "lang-cpp"] }
use lang_parsing_substrate::{language_for_file, languages, supported_languages_report};
use std::path::Path;

// Detect language for a file
if let Some(lang) = language_for_file(Path::new("main.c")) {
    let mut parser = tree_sitter::Parser::new();
    parser.set_language(&lang).unwrap();
    // parse...
}

// Enumerate compiled-in languages (reflects feature flags)
for info in languages() {
    println!("{}: {:?}", info.name, info.extensions);
}

// Human-readable summary (for --supported-languages flags)
print!("{}", supported_languages_report());

Grammar crates are re-exported so consumers reach them transitively:

// No direct tree-sitter-rust dependency needed in your Cargo.toml
use lang_parsing_substrate::tree_sitter_rust;

Early exit before parsing

language_for_file trusts the extension. To skip archives, executables, images and oversized files before they reach tree-sitter, classify first — it reads only a bounded prefix, never the whole file:

use lang_parsing_substrate::{classify_file, ClassifyLimits, FileClass};

// The size limit is the caller's policy; the default is no limit.
let limits = ClassifyLimits { max_size: Some(16 << 20), ..Default::default() };
match classify_file(path, &limits)? {
    FileClass::SourceText(_) => { /* parse it */ }
    FileClass::Binary { kind, mime } => { /* skip-and-report, or try anyway */ }
    FileClass::Oversize { size, limit } => { /* caller's call */ }
    _ => { /* Empty, or a future variant */ }
}

The result is a heuristic and can be wrong in both directions (see the classify module docs). Magic numbers come from the dependency-free infer crate. Short ASCII-looking signatures such as MZ or BM only count when the bytes also look binary. classify(path, prefix, size, &limits) is the I/O-free core, for callers that have already read the bytes. The thresholds are calibrated in docs/classify-calibration.md; re-run that check on a new corpus with cargo run --release --example classify_calibrate -- ROOT....

Analysis primitives

use lang_parsing_substrate::{call_edges, import_sources, build_function_cfg, structural_hash};

// Call-graph edges for every named function/macro in a parsed file
let edges = call_edges(tree.root_node(), source);

// Import/use-statement sources, for Ce/Ca coupling metrics
let imports = import_sources(&tree, source.as_bytes(), "rust");

// Control-flow graph for a single function body (c/cpp/rust)
if let Some(cfg) = build_function_cfg(func_node, source, "rust") {
    println!("{} basic blocks", cfg.block_count());
}

// Best-effort lower bound on the C standard a file requires
if let Some(standard) = detect_min_c_standard(&tree, source.as_bytes()) {
    println!("requires at least {standard:?}");
}

API

  • languages() -> &'static [LanguageInfo] — compiled-in language set
  • language_for_file(path: &Path) -> Option<Language> — grammar dispatch by extension
  • language_for_key(key: &str) -> Option<Language> — grammar dispatch by registry key
  • language_info_for_file(path: &Path) -> Option<&'static LanguageInfo>
  • classify / classify_file / FileClass / BinaryKind / TextEncoding / SourceText / ClassifyLimits — heuristic pre-parse file classification (classify)
  • is_source_extension / is_parseable_extension(ext: &OsStr) -> bool — recursive-discovery gates
  • supported_languages_report() -> String — human-readable language summary
  • LanguageInfo / SlocMode — registry metadata and comment-style enum (drives SLOC calculation)
  • find_descendants / find_first_descendant / find_ancestor / node_text and friends — traversal helpers (query)
  • flatten / FlatTree — a whole tree as flat columns (flat)
  • run_query / Capture / tags_query — tree-sitter queries and bundled tags queries (tsquery)
  • import_sources / distinct_import_count — import extraction (imports)
  • call_edges / CallEdge / is_function_kind / get_function_name — call-graph extraction (calls)
  • build_function_cfg / FunctionCfg / BasicBlock / CfgEdge — control-flow graphs (cfg)
  • detect_min_c_standard / CStandard — C standard lower-bound detection (c_standard)
  • function_fingerprints / duplicate_groups / Fingerprint / CorpusFingerprint — structural hashing (fingerprint)
  • ignored_regions / IgnoredRegion — tools:off/tools:on markers (regions)
  • suppressions / Suppression — tools:suppress comments (suppressions)
  • dead_code_ranges / DeadCodeRegion / DeadCodeReason — preprocessor dead-code regions, C/C++ only (dead_code)
  • swift_dead_code_regions / SwiftDeadCodeRegion — Swift #if/#elseif/#else dead-code regions (dead_code_swift)
  • csharp_dead_code_regions / CSharpDeadCodeRegion — C# #if/#elif/#else dead-code regions (dead_code_csharp)
  • PathIgnore — compiled glob ignore sets (path_ignore)

Building

cargo build                                          # all languages (default)
cargo build --no-default-features --features lang-c,lang-cpp  # subset
cargo test

Requires no C compiler — tree-sitter grammar crates ship pre-generated C sources and compile via the cc crate.

Python bindings

The pyo3 Cargo feature (off by default) exposes the substrate's language-agnostic analysis primitives as a Python extension module, published to PyPI as prebuilt abi3 wheels (CPython 3.10+, one wheel per platform — see docs/releasing.md):

pip install lang-parsing-substrate

Building it yourself from source uses maturin:

pip install maturin
maturin build --release          # writes target/wheels/lang_parsing_substrate-*.whl
pip install target/wheels/lang_parsing_substrate-*.whl
import lang_parsing_substrate as lps

src = "fn helper(x: i32) -> i32 { x + 1 }\nfn main() { helper(41); }\n"
edges = lps.call_edges("rust", src)          # [CallEdge(caller='main', callee='helper', ...)]
cfg = lps.function_cfg("rust", src, "main")  # FunctionCfg | None
fps = lps.function_fingerprints("rust", src, min_nodes=1)
caps = lps.query("rust", src, "(function_item name: (identifier) @name)")  # [Capture]
tags = lps.tags_query("tsx")                 # the grammar's bundled tags query, or None
tree = lps.parse_tree("rust", src.encode())  # FlatTree: every node as columns

Python can't hand this crate a tree_sitter::Node/Tree directly — this crate's tree-sitter version has no ABI relationship to tree-sitter's own, separate Python bindings — so every bound function takes (language_key, source), parses internally, and returns owned data (CallEdge, FunctionCfg, Fingerprint, Suppression, IgnoredRegion, LanguageInfo, Capture, FlatTree, all plain attribute-holding classes).

A consumer that walks the tree itself (e.g. for domain-specific semantics this crate doesn't model) uses parse_tree. It returns every node, named or not, in pre-order (row 0 is the root). Each column (kind, field, flags, parent, first_child, next_sibling, prev_sibling, start_byte, end_byte, start_row, start_col, end_row, end_col, child_offset, child_list) is native-endian u32 bytes, so memoryview(tree.kind).cast("I")[i] is node i's kind. kind and field index into the kinds / fields string tables, and links are lps.NONE when absent. A node's children are child_list[child_offset[i]:child_offset[i + 1]]. tree.root_node returns a native Node that answers the walking subset of py-tree-sitter's Node API (type, children, child_by_field_name, parent, siblings, positions, text, id, error flags), so a walker written for py-tree-sitter runs on it unchanged. clew parses Python and Rust this way. parse_tree, query and function_cfg also accept "tsx" for the JSX-aware TypeScript grammar.

invoke build-wheel builds the wheel locally for testing. The actual PyPI release happens in CI on a vX.Y.Z tag push, via Trusted Publishing (OIDC, no API token) — see docs/releasing.md.

License

MIT — see LICENSE.

Metadata

Release files for lang-parsing-substrate 0.11.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for lang-parsing-substrate 0.11.0
File Size Uploaded Provenance
lang_parsing_substrate-0.11.0.tar.gz 146.5 kB With provenance Details

Built distributions (wheels)

Table of built distributions (wheels) for lang-parsing-substrate 0.11.0
File
lang_parsing_substrate-0.11.0-cp310-abi3-win_amd64.whl CPython 3.10 abi3 Windows x86-64 Details
lang_parsing_substrate-0.11.0-cp310-abi3-musllinux_1_2_x86_64.whl CPython 3.10 abi3 Linux musl 1.2+ x86-64 Details
lang_parsing_substrate-0.11.0-cp310-abi3-musllinux_1_2_aarch64.whl CPython 3.10 abi3 Linux musl 1.2+ ARM64 Details
lang_parsing_substrate-0.11.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.10 abi3 Linux glibc 2.17+ x86-64 Details
lang_parsing_substrate-0.11.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl CPython 3.10 abi3 Linux glibc 2.17+ ARM64 Details
lang_parsing_substrate-0.11.0-cp310-abi3-macosx_11_0_arm64.whl CPython 3.10 abi3 macOS 11.0+ ARM64 Details
lang_parsing_substrate-0.11.0-cp310-abi3-macosx_10_12_x86_64.whl CPython 3.10 abi3 macOS 10.12+ x86-64 Details

Total release size: 29.8 MB

Release files / lang_parsing_substrate-0.11.0.tar.gz

Download URL lang_parsing_substrate-0.11.0.tar.gz
Size 146.5 kB
Tags Source
SHA-256 checksum
How to use checksums
6e2c4ef22e27b8406398c00339adbc4b63f15794b3bdf6455618724c60c1ea7a
BLAKE2b-256 checksum
How to use checksums
b970ad0edfdf07df73943d2dc6e005455f4d28c99dbf441aec928b376e4ec375
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 6, 2026.

Transparency log

Release files / lang_parsing_substrate-0.11.0-cp310-abi3-win_amd64.whl

Download URL lang_parsing_substrate-0.11.0-cp310-abi3-win_amd64.whl
Size 3.9 MB
Tags CPython 3.10 Windows x86-64 abi3
SHA-256 checksum
How to use checksums
88f9d43f3787ee85b39b717b1dddc516f7fbf90b1d1c48e0edf3b648015cc85a
BLAKE2b-256 checksum
How to use checksums
d73e8b3e41e3fec1c3640a6fe831ca6b06109ebf20708e69ebe0623e9a28c47b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 6, 2026.

Transparency log

Release files / lang_parsing_substrate-0.11.0-cp310-abi3-musllinux_1_2_x86_64.whl

Download URL lang_parsing_substrate-0.11.0-cp310-abi3-musllinux_1_2_x86_64.whl
Size 4.5 MB
Tags CPython 3.10 Linux musl 1.2+ x86-64 abi3
SHA-256 checksum
How to use checksums
77accae4752d1c0d574be32e189363289b560c3b2d01c4883225753c43c2e860
BLAKE2b-256 checksum
How to use checksums
dd632def562e493d713f333c9aa8d2faab7257aca85946ff6a58768ba6cb0735
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 6, 2026.

Transparency log

Release files / lang_parsing_substrate-0.11.0-cp310-abi3-musllinux_1_2_aarch64.whl

Download URL lang_parsing_substrate-0.11.0-cp310-abi3-musllinux_1_2_aarch64.whl
Size 4.4 MB
Tags CPython 3.10 Linux musl 1.2+ ARM64 abi3
SHA-256 checksum
How to use checksums
348f8bc1020acd38aa6e317e42fffc4c4c50e6608a57e899a07a45ba7f2e06ad
BLAKE2b-256 checksum
How to use checksums
77a14f6d665c3fa6ccbfa6ba32e2070a05f716aa087abdfffb0343b99eed2f03
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 6, 2026.

Transparency log

Release files / lang_parsing_substrate-0.11.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL lang_parsing_substrate-0.11.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 4.2 MB
Tags CPython 3.10 Linux glibc 2.17+ x86-64 abi3
SHA-256 checksum
How to use checksums
61acbb97fb8f8533a6d7eae3e63d94797bc55090bb430f9686608411932c9d9a
BLAKE2b-256 checksum
How to use checksums
e6648614ade6e7a50481a4f26f1d51767d38bc3d78d9322a4634a6766bfb0b3f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 6, 2026.

Transparency log

Release files / lang_parsing_substrate-0.11.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl

Download URL lang_parsing_substrate-0.11.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Size 4.3 MB
Tags CPython 3.10 Linux glibc 2.17+ ARM64 abi3
SHA-256 checksum
How to use checksums
12d0d3652eff9d5469e2170024586e20be9d9dcfff88a7206386b5e32f75905d
BLAKE2b-256 checksum
How to use checksums
45b4e8c015d50608c87129db651baddb4e6c635576333aa24e373e4f74ea46f1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 6, 2026.

Transparency log

Release files / lang_parsing_substrate-0.11.0-cp310-abi3-macosx_11_0_arm64.whl

Download URL lang_parsing_substrate-0.11.0-cp310-abi3-macosx_11_0_arm64.whl
Size 4.3 MB
Tags CPython 3.10 abi3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
c2952ed102ad19a2ccb4b918188291fafefff95679abd7e499f90977b8bf6f9d
BLAKE2b-256 checksum
How to use checksums
4d41c9f45fc97cd50922b8a21b0f1adf47b1da54c8abbc02e41d270ce2f0e58d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 6, 2026.

Transparency log

Release files / lang_parsing_substrate-0.11.0-cp310-abi3-macosx_10_12_x86_64.whl

Download URL lang_parsing_substrate-0.11.0-cp310-abi3-macosx_10_12_x86_64.whl
Size 4.1 MB
Tags CPython 3.10 abi3 macOS 10.12+ x86-64
SHA-256 checksum
How to use checksums
a69848db04aabc4e023465c7600874fca9798683a6dff548bf65182d756460e7
BLAKE2b-256 checksum
How to use checksums
a3d8b32cce6159920b699cf2e14bf6b7c78eb5d62c318aeb1584edb1abb59822
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 6, 2026.

Transparency log

Security for lang-parsing-substrate 0.11.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 8 files in this release have been uploaded with provenance metadata.

Select from 8 files

Attestation for lang_parsing_substrate-0.11.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 6, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page