fix(typst): eliminate LALR(1) conflict on heading title items
Build and Deploy Verso / deploy (push) Failing after 3h10m10s

Removing Strong and Emphasis from headingTitleItem eliminates the
conflict: both appear in document-level item, causing the LR automaton
to merge heading-title states with document-item states and make "*"
ambiguous (Strong opener vs. end of heading).

HeadingText is widened to ![\n$#`<@\\]+ so "*" and "_" inside headings
are consumed as plain text rather than producing error nodes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
claude
2026-06-07 20:58:05 +00:00
parent 26da1f6205
commit 94e8ff3503
@@ -31,12 +31,15 @@ item {
// HeadingMark is produced by an external tokenizer that enforces the
// start-of-line constraint and captures the "=+" prefix + trailing space.
Heading { HeadingMark HeadingTitle }
// headingTitleItem+ (not *) so HeadingTitle is never empty: the generator
// would otherwise produce a shift/reduce conflict on "*" after HeadingMark,
// unable to tell if "*" starts a Strong inside the heading or at doc level.
// Strong and Emphasis are intentionally excluded from headingTitleItem.
// Including them causes an LALR(1) conflict: since Strong/Emphasis also appear
// in document-level `item`, the LR automaton merges heading-title states with
// document-item states, making "*" ambiguous (Strong opener vs. end of heading).
// Instead, HeadingText is widened to consume "*" and "_" as plain text inside
// headings — they are not interpreted as markup delimiters there.
HeadingTitle { headingTitleItem+ }
headingTitleItem {
Strong | Emphasis | CodeExpr | InlineMath | RawInline | Label | Ref | HeadingText
CodeExpr | InlineMath | RawInline | Label | Ref | HeadingText
}
// ── Comments ──────────────────────────────────────────────────────────────
@@ -186,7 +189,7 @@ Escape { "\\" EscapeChar }
MathContent { ![$\n]+ }
// Text tokens for different markup contexts; each excludes its own delimiters.
HeadingText { ![\n*_$#`<@\\]+ }
HeadingText { ![\n$#`<@\\]+ }
StrongText { ![\n*$#`@\\]+ }
EmphText { ![\n_$#`@\\]+ }