None when the input is not valid for that kind. Rust owns these rules. The
implementation reuses the upstream
text-processing-rs
v0.3.0 parsers. Local Rust code adds grammar, complete-span validation, and
canonicalization only where the upstream parser is not sufficient; it is not a
second Python realizer or a fork of the upstream library. A local parser may
run before the upstream parser for a kind with additional supported forms,
while delegated kinds retain the upstream parser after local guards pass.
Supported kinds
The explicit ELECTRONIC and PHONE entry points add complete-span guards before
delegating. ELECTRONIC also validates protocol/domain structure and the
delegated output. Unknown trailing words are rejected instead of being
silently ignored or appended to the normalized value.
open quote and close quote each realize to a quote-symbol candidate. The
realizer does not define sentence-level opening and closing quote spacing.
Structural whitespace commands such as new line and new paragraph are not
runtime candidates because the scorer and path renderer do not yet represent
whitespace-only replacements.
Representation comparison
representations_equivalent is evaluation-only. It compares semantic values
without adding display aliases to runtime candidates. It currently supports:
CARDINAL: grouping, zero padding, Roman numerals, and signed zero.DATE: unambiguous field order and separators, month or weekday abbreviations, ordinal suffixes, and era punctuation, including eras on full dates.DECIMAL: grouping, decimal padding, decimal comma, named scales, attached scale suffixes, scientific notation, preserved negative zero, and bounded canonical expansion.DIGIT_SEQUENCE: harmless grouping punctuation and separators are ignored while the digit order and value are preserved.TIME: clock padding and separators, compact clocks, AM/PM case and punctuation, 12/24-hour notation, timezone case and offset padding, and duration or fraction padding.MONEY: currency symbols, ISO codes, currency placement, grouping, decimal zero padding, major/minor units, and named or abbreviated thousand/lakh/crore/ million/billion/trillion scales. Currency identity is preserved:$maps to USD, while explicit CAD/AUD and other currency codes remain distinct.MEASUREMENT: numeric grouping, decimal padding, Unicode minus/spacing, unit symbols and names, square/cubic aliases, compound rate units, and metric/data/power unit aliases. Numeric value and canonical unit must both match. Case-sensitive unit identities remain distinct, including metermversus minutemin, mega versus milli prefixes, and byte versus bit units.ORDINAL: numeric suffixes, ordinal words and scales, optional articles, Roman numerals, and harmless terminal punctuation.PHONE: separator/grouping punctuation, country-code spacing, and SSN or IP structure are normalized while the digit sequence and structure remain significant.
dollar/cent is paired with an explicit non-USD target such as A$ or €;
the source does not contain enough information to infer that currency. The 63
None rows are malformed sil/pa annotations. The remaining 212,618
determinate, non-malformed rows have 100% exact-or-equivalent coverage.
The seven-shard audits also cover 4,761,909 CARDINAL rows (99.913% exact or
equivalent), 12,029,272 DATE rows (99.995%), and 350,825 DECIMAL rows
(99.982%). Their remaining rows are malformed, contradictory, or carry target
annotation suffixes that are not part of the semantic value.
These corpus audits are regression evidence, not the source of the grammar.
Rules must be expressed in terms of generic numeric, date, time, unit, and
span structure. A sentence, URL, annotation token, or other dataset-specific
string must not receive a special case.
Synthetic checks cover signed and zero forms, malformed numeric separators,
balanced digit grouping, bounded scientific expansion, overflow and leap-day
rejection, grouping and locale decimal separators, repeated-dot grouping,
Unicode spacing, invalid timezone offsets, repeated scales, and unrelated
suffixes. These checks are kept alongside the focused Rust tests so future
kinds receive the same complete-span and formatting review.
Update this document and the README when a kind gains or loses behavior. Add a
focused Rust test for each new form.