panproto_grammars/lib.rs
1#![allow(unsafe_code)]
2//! Pre-compiled tree-sitter grammars for panproto.
3//!
4//! This crate bundles up to 248 tree-sitter grammars, compiled from vendored C sources.
5//! Each grammar is gated behind a `lang-{name}` feature flag. Group features like
6//! `group-core`, `group-web`, `group-all` etc. enable sets of languages at once.
7//!
8//! The default feature is `group-core` (GitHub's top 10 languages + Rust).
9
10#[allow(
11 clippy::vec_init_then_push,
12 clippy::match_same_arms,
13 clippy::must_use_candidate,
14 clippy::redundant_pub_crate,
15 unreachable_pub
16)]
17mod generated {
18 include!(concat!(env!("OUT_DIR"), "/grammar_table.rs"));
19}
20use generated::{enabled_grammars, ext_to_lang};
21
22/// A compiled tree-sitter grammar with its metadata.
23pub struct Grammar {
24 /// Protocol name (e.g. `"python"`, `"typescript"`).
25 pub name: &'static str,
26 /// File extensions this grammar handles (e.g. `["py", "pyi"]`).
27 pub extensions: &'static [&'static str],
28 /// The tree-sitter `Language` object for parsing.
29 pub language: tree_sitter::Language,
30 /// Raw `node-types.json` bytes for theory extraction.
31 pub node_types: &'static [u8],
32}
33
34/// Return all grammars enabled by feature flags.
35///
36/// Each grammar provides a `Language` for parsing and `node_types` JSON for
37/// theory extraction. The returned list is sorted by grammar name.
38#[must_use]
39pub fn grammars() -> Vec<Grammar> {
40 enabled_grammars()
41 .into_iter()
42 .map(|e| {
43 let language = unsafe {
44 // SAFETY: `tree_sitter_{name}()` is an extern "C" function that returns
45 // a valid `TSLanguage*` pointer from the compiled C grammar. We cast the
46 // raw pointer back to the correct function pointer type. This is the
47 // standard tree-sitter FFI pattern used by every grammar crate.
48 let f: unsafe extern "C" fn() -> *const () = std::mem::transmute(e.language_fn_ptr);
49 tree_sitter_language::LanguageFn::from_raw(f).into()
50 };
51 Grammar {
52 name: e.name,
53 extensions: e.extensions,
54 language,
55 node_types: e.node_types,
56 }
57 })
58 .collect()
59}
60
61/// Check if a specific grammar is available (enabled by feature flags).
62#[must_use]
63pub fn has_grammar(name: &str) -> bool {
64 enabled_grammars().iter().any(|e| e.name == name)
65}
66
67/// Map a file extension to its grammar name.
68///
69/// Returns `None` if the extension is not recognized among enabled grammars.
70#[must_use]
71pub fn extension_to_language(ext: &str) -> Option<&'static str> {
72 ext_to_lang(ext)
73}
74
75/// Return the number of enabled grammars.
76#[must_use]
77pub fn grammar_count() -> usize {
78 enabled_grammars().len()
79}