Skip to content

parse: expand \def macros in the mouth, instead of dropping the formula - #10

Merged
tannevaled merged 1 commit into
mainfrom
math-def
Sep 1, 2026
Merged

parse: expand \def macros in the mouth, instead of dropping the formula#10
tannevaled merged 1 commit into
mainfrom
math-def

Conversation

@tannevaled

Copy link
Copy Markdown
Contributor

What

A \def written inside a formula — a paper's own inline shorthand reaching the math layer (\def\R{\mathbb{R}}\R, \def\abs#1{\lvert#1\rvert}\abs{x}) — was an unknown command that dropped the whole equation. Macros defined in the preamble are already substituted upstream by go-tex/engine's math retry; the ones defined in the formula were not, and \def is a top math-drop cause across the arXiv corpus.

How

A TeX "mouth" pass (macro.go) runs before the parser (expandMacros, after resolveConditionals): it records each \def and expands every use — arguments spliced into #1…#n of the body, the result re-processed so nested and chained macros resolve — with a budget so a self- or mutually-recursive macro (\def\x{\x}) can't spin. It supports undelimited parameters (the inline form that occurs); a \def it cannot read (delimited parameters, missing/unbalanced body) or a use with too few arguments is left verbatim for the parser to report, never guessed at. Transparent to a def-free stream.

Verification

New macro_test.go: parameterless/parameterised macros, chained (\a→\b→x+y) and nested macros, expansion inside \frac arguments, single-token vs {group} args, an undeclared-#n body, and every rejecting path (bad name, delimited params, missing/unbalanced body, too few args, unbalanced arg, self-recursion halts). Full suite + -race + go vet + gofmt clean at 100% coverage.

Continues the worst-first math-drop robustness pass (after \char, #9). A follow-up bumps the engine's go-tex/math dependency so the corpus recovers end-to-end.

🤖 Generated with Claude Code

A \def written inside a formula — a paper's own inline shorthand reaching the
math layer, \def\R{\mathbb{R}}\R or \def\abs#1{\lvert#1\rvert}\abs{x} — was an
unknown command that dropped the whole equation. Macros defined in the preamble
are already substituted upstream by go-tex/engine; the ones that live inside the
formula were not handled, and \def is a top math-drop cause across the arXiv
corpus.

Add a TeX "mouth" pass (macro.go) that runs before the parser: it records each
\def and expands every use — arguments spliced into #1…#n of the body, the
result re-processed so nested and chained macros resolve — with a budget that
stops a self- or mutually-recursive macro from spinning. It handles undelimited
parameters (the inline form that occurs); a \def it cannot read (delimited
parameters, no body) or a use with too few arguments is left verbatim for the
parser to report, never guessed at. The pass is transparent to a def-free
stream.

Verified: parameterless and parameterised macros, chained and nested macros,
expansion inside \frac arguments, single-token vs {group} arguments, and every
rejecting path (bad name, delimited params, missing/unbalanced body, too few
args, self-recursion) all covered; full suite, race, go vet, gofmt clean at 100%.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@tannevaled
tannevaled merged commit b0a8068 into main Sep 1, 2026
11 checks passed
@tannevaled
tannevaled deleted the math-def branch September 1, 2026 19:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant