metrale_grammar/matcher/mod.rs
1// SPDX-License-Identifier: MIT OR Apache-2.0
2//
3// Grammar matcher — port wave W6, the final algorithmic subsystem.
4//
5// Pure-Rust port of `cpp/grammar_matcher.cc` + `include/xgrammar/
6// matcher.h`. The matcher is the per-request, per-decode-step state
7// Metrale Engine drives: it accepts sampled tokens, fills the next-token accept
8// bitmask, supports rollback (for speculative decoding) and detects
9// termination.
10//
11// Module map:
12// bitmask — `TokenBitmask` / `BitmaskSlice`: the packed i32
13// bit-per-token mask, byte-compatible with the upstream
14// CUDA `apply_token_bitmask` kernel.
15// matcher — `GrammarMatcher`: construction, accept token/string,
16// rollback, termination, reset.
17// fill — `FillNextTokenBitmask` + `FindJumpForwardString`.
18// coalesce — Coalescence forced-token fast-path (Tier 3b):
19// `forced_token` / `next_forced_tokens`.
20// completion — `find_completion_to_accept`: shortest grammar-legal
21// close to a stop-legal state (Metrale Engine budget-aware close).
22// batch — `BatchGrammarMatcher`: parallel batched bitmask fill.
23//
24// PORT NOTES / SIMPLIFICATIONS vs C++
25// -----------------------------------
26// * The C++ `Impl` inherits `EarleyParser`; the Rust port composes
27// one. The parser already exposes `advance` / `pop_last_states` /
28// `push_one_state_to_check` / `is_completed`.
29// * The C++ matcher reads `stop_token_is_accepted_` off the parser
30// base. That field is cleared on every `pop_last_states`, which is
31// wrong for a matcher rollback that does not reach the stop step.
32// The Rust matcher owns its own `stop_token_accepted` flag, undone
33// precisely by `rollback` via the zero-length history entry.
34// * The bitmask is a packed `i32` slice / owned `TokenBitmask` rather
35// than a `DLTensor` — the W7 API shim adapts it to Metrale Engine's tensor.
36// * `BatchGrammarMatcher`'s parallel path requires the natural
37// matcher-to-slice mapping (see `batch.rs`); an arbitrary `indices`
38// permutation falls back to the (always-correct) sequential path.
39// * `max_rollback_tokens` is accepted but ignored — the C++ also
40// deprecated and ignores it; rollback is unbounded.
41// * `_DebugPrintInternalState` is not ported (debug-only, the C++
42// notes its representation is unstable).
43
44mod batch;
45mod bitmask;
46mod coalesce;
47mod completion;
48mod fill;
49// The `GrammarMatcher` struct lives in `matcher.rs`; the file split
50// (struct vs. `fill.rs`) is required by the 250-line-per-file cap.
51#[allow(clippy::module_inception)]
52mod matcher;
53
54pub use batch::BatchGrammarMatcher;
55pub use bitmask::{BITS_PER_WORD, BitmaskSlice, TokenBitmask, bitmask_size};
56pub use fill::FillError;
57pub use matcher::GrammarMatcher;
58
59#[cfg(test)]
60mod tests;