1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
//! # fmd-math — the clean-room TeX-mathematics layout engine
//!
//! A math-*layout* engine in the KaTeX/Typst class, not a TeX macro
//! processor: the TeX mathematics grammar as actually used, TeX's published
//! layout rules (the eight atom classes, the inter-atom spacing table,
//! display/text/script/scriptscript style propagation), and — with the
//! placement beads — Appendix-G construction mathematics over metrics
//! calibrated for the bundled faces.
//!
//! This crate is contributed and consumed by the franken_manim program (its
//! Scribe subsystem typesets `Tex`/`TexText` through it; see that repo's
//! `UPSTREAM_LEDGER.md` row 2) and serves fmd's own native `$…$`
//! mathematics. The public API is **frozen to the shape recorded in
//! franken_manim's `docs/g0/G0-3-fmd-math-ratification.md`** until its G2
//! gate.
//!
//! ## The pipeline
//!
//! ```text
//! source &str
//! → parse tokens → Node tree; EVERY node carries its byte span
//! → classify the eight atom classes; Bin→Ord degradation in context
//! → layout(Ctx) style (D/T/S/SS × cramped) threaded top-down;
//! Appendix-G constructions build boxes bottom-up
//! → Layout positioned {glyphs, rules, drawn paths}, each glyph
//! naming its FACE and carrying its source span
//! ```
//!
//! This crate release carries the front of the pipeline: [`parse`] /
//! [`parse_text`], the atom engine ([`atom`]), the style machinery
//! ([`style`]), and the fixed node model plus output types ([`Layout`] and
//! friends). `Engine::new(faces…)` / `typeset` land with the placement
//! bead on exactly these shapes.
//!
//! ## Modes
//!
//! [`parse`] reads a whole string as mathematics (the `Tex` surface; `&`
//! and `\\` are legal at top level because the Reference wraps whole
//! strings in an `align*`-class environment). [`parse_text`] reads the
//! TexText contract: a text mainland with `$…$` math islands,
//! `\textbf`/`\emph`/`\underline`, and the escape set.
//!
//! ## Fragment tolerance (per-argument `SingleStringTex` semantics)
//!
//! The Tex surface's multi-argument idiom makes each literal argument its
//! own string, so a string may legitimately be a *piece of a balanced
//! whole* (`"{a"`, `"\over"`, `"b}"`, `"\left("`, `"a^"`). The grammar
//! therefore (a) lets **end of input close whatever is open** — groups,
//! `\left`, `$` islands, arguments still to come (they become empty
//! lists) — and (b) accepts, at the top level, an unmatched `}`, a stray
//! `\right`, or a redundant `$` as an explicit
//! [`node::FragmentKind`] marker, never silently. Mid-string structural
//! faults (wrong closer, double scripts, `&` in prose) remain precise
//! errors. In text mode, the Reference-era LaTeX missing-`$` recovery is
//! kept deliberately: a self-contained math command or a bare script in
//! the mainland becomes an explicit implicit [`NodeKind::MathIsland`],
//! and `$$…$$` display mathematics is recognized.
//!
//! ## The span map (§11.3)
//!
//! Every output primitive carries its source byte span, exactly: text-run
//! characters per character, primes per `'` token, command-produced
//! glyphs the producing command's span (the expansion site). The
//! [`spanmap`] module turns that provenance into the consumption surface:
//! [`spanmap::find_occurrences`] + [`Layout::select`] (containment
//! semantics) is the native replacement for the Reference's
//! render-twice-and-align hack — `isolate`, `tex_to_color_map`, substring
//! slicing, and `TransformMatchingTex` match by source identity.
//!
//! ## The error contract (the coverage ratchet's unit)
//!
//! There is deliberately no fallback typesetter, so coverage discipline
//! replaces fallback discipline: an unsupported construct is a **precise,
//! named error** ([`MathError::UnsupportedCommand`] with the construct's
//! G0-4 table name and a tier tag in its message), and arbitrary input
//! errors cleanly — never hangs, never garbles, never panics (the chaos
//! suite locks this). [`construct_status`] answers, for any construct in
//! the table's naming scheme, whether the parse surface supports it.
pub use ;
pub use MathError;
pub use FaceSet;
pub use Engine;
pub use MacroSet;
pub use ;
pub use ;
pub use MathConstants;
pub use ;
pub use ;
pub use ;
/// Parse a whole source string as mathematics (the `Tex` surface). The
/// result is a [`NodeKind::List`] node spanning the whole input; every
/// descendant carries its byte span.
///
/// # Errors
///
/// [`MathError::UnsupportedCommand`] for constructs outside the implemented
/// surface (named precisely, tier-tagged); [`MathError::Malformed`] for
/// structural faults (unbalanced groups, double scripts, stray `\right`,
/// over-deep nesting), with the byte offset of the offense.
/// Parse a whole source string under the TexText contract: a text mainland
/// with `$…$` math islands.
///
/// # Errors
///
/// As [`parse`]; additionally, math-only material in the text mainland
/// (`^`, `_`, `&`, math-mode commands) is a precise [`MathError::Malformed`]
/// telling the caller to wrap it in `$…$`.
/// [`parse`], against a macro set (a preamble pack and/or caller
/// definitions): calls expand at the token level before the grammar runs,
/// with body-produced tokens carrying their call site's span (see
/// [`macros`]).
///
/// # Errors
///
/// As [`parse`], plus the macro-expansion errors ([`macros`]): recursion
/// refusal, budget overruns, malformed definitions — every one precise.
/// [`parse_text`], against a macro set.
///
/// # Errors
///
/// As [`parse_with_macros`].