Expand description
message-bundles slice 3 (#878): the ICU MessageFormat placeholder
mini-parser, plus the plain-{name} template scanner (split_template)
it dispatches from. Self-contained and bynk-syntax-free by design
(Decision B) — the whole ICU sub-grammar ({name, plural, one {…} other {…}}, {name, select, …}, {name, number[, style]}, {name, date[, style]}) lives entirely inside a messages template’s String
content, parsed here as plain &str and consumed by both the checker
(bynk-emit/src/project/validate.rs) and the emitter
(emit_message_entry_renderer). No bynk-syntax grammar/lexer/AST
change backs this — a template stays one opaque String all the way
through parsing.
Lives in bynk-check (moved here in the compiler-pipeline-review’s Wave
5, batch 5.1) rather than bynk-emit, since its only consumer besides
the emitter is checker-side (validate.rs’s malformed-syntax pass) and
it has no emitter-specific dependency of its own.
Quoting: a bare ' toggles a “quoted” region; '' inside either mode
means a literal ' and doesn’t toggle; while quoted, {/}/,/# are
inert literal text. This is a deliberately narrower rule than full ICU
MessageFormat’s own quoting semantics — sufficient for this slice’s fixed
subset, not a general ICU implementation (Decision B/the proposal’s named
scope cuts).
Explicitly unsupported, each with its own diagnosable
IcuParseErrorKind rather than silent misbehaviour: selectordinal,
plural’s offset:/=N exact-value arms, arbitrary CLDR skeletons
beyond the fixed style keywords below, and nesting a second {arg, …}
dispatch inside a sub-message (a sub-message is literal text + # only).
Structs§
Enums§
- Date
Style - Format
Kind - The coarse comparison unit for cross-locale format agreement
(
bynk.messages.format_mismatch,bynk-emit/src/project/validate.rs) — arm/style content doesn’t matter for agreement, only which of the five surface forms a placeholder uses.Plaincovers the bare{name}fast path, which never calls into this parser at all. - IcuParse
Error Kind - Number
Style - Placeholder
Kind - Plural
Category - SubSegment
- One piece of a
plural/selectarm’s sub-message. Owned, not&'a str: ICU''-unescaping can shrink byte length, so a literal sub-segment cannot always borrow from the source template. - Template
Segment - A
{name}placeholder (plain, or — message-bundles slice 3 (#878) — an ICU-dispatch placeholder whoseinnertext contains a,) or a run of literal text inside a message template.offsetis the byte offset in the owning template whereinner/the placeholder’s content begins (right after the opening{) — used by slice 3’sicu_dispatch_placeholdersto rebase parse-error spans (Decision C).
Functions§
- find_
icu_ close - Quote+depth-aware scan from just after a placeholder’s opening
{(rest), used only once emission-side detection (split_template) has already decided this is an ICU-dispatch placeholder (a,precedes the naive first}). Depth starts at 1 for the still-open outer brace; returns the byte offset of the true closing}(depth reaching 0),Noneif it never closes. - icu_
dispatch_ placeholders - Every ICU-dispatch placeholder in
template—(byte offset ofinnerwithintemplate,innertext)— for the checker’s malformed-syntax pass (bynk-emit/src/project/validate.rs). A placeholder only reaches here ifsplit_templatealready decided it was ICU-dispatch (itsinnercontains a top-level comma); a plain{name}never does, by construction (proven insplit_template’s own doc comment). - parse_
icu_ placeholder - Parses one placeholder’s
innertext (everything between the outer{/}, e.g."count, plural, one {# item} other {# items}") — the precondition for calling this at all is thatinnercontains at least one top-level comma (split_template’s own trigger for treating a placeholder as ICU-dispatch rather than a plain{name}). - placeholder_
names - message-bundles slice 2 (#874): a template’s placeholder-name set, for
cross-locale agreement checking (
bynk-emit/src/project/validate.rs). Exposes only the name set, notTemplateSegmentitself, keeping the checker’s dependency on the emitter narrow. message-bundles slice 3 (#878): an ICU-dispatch placeholder’s name is itsinnertext up to the first top-level comma, trimmed — a plain placeholder’sinnernever contains a comma (by construction ofsplit_template’sis_icudecision above), so it’s returned verbatim, preserving the untrimmed-name quirk documented onsplit_templateexactly as before. - split_
template - Compile-time string scan splitting a template into literal/placeholder
segments (Decision D, message-bundles slice 1 — no new lexer/parser
grammar;
{name}is resolved by this Rust-side scan during lowering, not parsed as an expression). A{with no matching}, or an empty{}, is just literal text — malformed-placeholder checking is out of scope here. The name is taken verbatim, with no whitespace trimming:{ name }is a placeholder literally named" name ", which will never match aparamskey and so always renders as literal text (PR #872 review) — a real rough edge, left for a future slice rather than guessed at here. - template_
format_ kinds - Every placeholder’s
(name, FormatKind)intemplate, silently dropping any placeholder whose ICU parse fails — that failure ischeck_entry_icu_syntax‘s job to report (once), not this pure helper’s, so a caller comparing two locales’ templates never double-reports a malformed one.