Skip to main content

badness_parser/
lib.rs

1//! badness-parser — the lossless CST parser, semantic model, and
2//! command-signature database behind [badness](https://badness.dev/), for
3//! LaTeX (`.tex`, `.sty`/`.cls`, `.dtx`, `.ins`) and BibTeX (`.bib`).
4//!
5//! The parser treats input as generic TeX surface syntax and always produces a
6//! lossless rowan tree: `reconstruct(text) == text`, byte for byte. Semantics
7//! (arity, verbatim-ness, sectioning) are layered on top in [`semantic`],
8//! never inside the grammar.
9
10#![deny(clippy::debug_assert_with_mut_call)]
11
12macro_rules! impl_rowan_lang {
13    ($language:ty, $kind:ty, $name:literal) => {
14        const _: () = assert!(
15            <$kind>::ROOT as u16 + 1 == <$kind>::__LAST as u16,
16            "ROOT must be the final syntax kind"
17        );
18
19        impl From<$kind> for rowan::SyntaxKind {
20            fn from(kind: $kind) -> Self {
21                Self(kind as u16)
22            }
23        }
24
25        impl rowan::Language for $language {
26            type Kind = $kind;
27
28            fn kind_from_raw(raw: rowan::SyntaxKind) -> $kind {
29                assert!(
30                    raw.0 <= <$kind>::ROOT as u16,
31                    "invalid {} SyntaxKind discriminant: {}",
32                    $name,
33                    raw.0
34                );
35                // SAFETY: the kind is a contiguous `#[repr(u16)]` enum from zero
36                // through `ROOT`, and the assertion bounds the raw value to it.
37                unsafe { std::mem::transmute::<u16, $kind>(raw.0) }
38            }
39
40            fn kind_to_raw(kind: $kind) -> rowan::SyntaxKind {
41                kind.into()
42            }
43        }
44    };
45}
46
47pub mod ast;
48pub mod bib;
49pub mod declarations;
50pub mod directives;
51mod error;
52pub mod parser;
53pub mod semantic;
54pub mod syntax;
55
56pub use error::SyntaxError;
57
58// Re-export rowan so embedders can name the exact tree types this crate is
59// built against without pinning a matching rowan version themselves.
60pub use rowan;