pub struct ParseCtx { /* private fields */ }Expand description
Per-parse context carrying the facts the parser can only learn by first
scanning the file’s own definitions (crate::semantic::define) — the
sanctioned second pass described in parser::core. Empty for the first pass;
populated for the second when the document defines any. Both the lexer and the
grammar read it, so the two can never disagree about what a name is.
It carries two families of fact, each read from static definition surface only
(no macro meaning, per AGENTS.md Core decision #1):
- User-defined verbatim constructs — those a document declares with catcode
manipulation (
\@makeother\$, …). The lexer consults these (alongside the built-in DB) to capture a verbatim command’s final argument as oneVERBtoken, and a verbatim environment’s body as oneVERBATIM_BODYtoken. - Environment aliases — a command whose definition body is exactly
\begin{X}/\end{X}, so\bea … \eeapairs as anENVIRONMENTofX(issue #109). The grammar consults these; the lexer does not.
A command entry maps a name (no leading \) to its leading, non-verbatim
argument shape, the verbatim argument itself being implicit — matching the built-in
convention. An environment entry maps a name to its full argument shape (an
environment’s args are all leading; its body follows the \begin{…} arguments), so
presence in environments means the environment is verbatim.
suppressed names the inverse case: commands the current file redefines to an
ordinary (non-verbatim) macro whose name collides with a built-in raw-argument
command (\code, \url, \href, …). A local definition shadows the built-in, so
[lex_verbatim_command] must lex \code{…} as an ordinary group rather than capture
the built-in VERB (follow-up to issue #53). We read only static definition facts (a
visible \newcommand/\def with no catcode signal), never macro meaning.
PartialEq is load-bearing rather than incidental: parser::core decides
whether the second pass has anything to do by comparing the scanned context
against the declaration seed it started from, which stays correct as fields
are added in a way a hand-maintained “did anything change” flag would not.
Implementations§
Source§impl ParseCtx
impl ParseCtx
Sourcepub fn is_empty(&self) -> bool
pub fn is_empty(&self) -> bool
Whether the context names nothing at all — no user verbatim constructs, no suppressions, and no environment aliases — so the second parse pass can be skipped entirely (the common case).
Every map must be accounted for here: a file that defines an alias but no verbatim construct would otherwise never reach pass 2, and its aliases would silently do nothing.
Sourcepub fn overlay_declarations(&mut self, declared: &ResolvedDeclarations)
pub fn overlay_declarations(&mut self, declared: &ResolvedDeclarations)
Overlay a project’s declarations onto this context, taking precedence over anything already recorded.
Declared beats scanned because a declaration is the user explicitly
correcting an inference (AGENTS.md decision #12), which is why this is
an overlay applied after the scan rather than a seed the scan writes
over.
Two families cross over: the declared environment signatures, which
every body-routing predicate here then answers from, and the delimiter
spellings. The alias entries skip the “is it called anywhere” filter
parser::core::parse_ctx applies to scanned ones: that filter exists to
avoid buying a second pass for an alias no call site uses, and a
declaration is already in hand before the first.