Skip to content

Glued honorific: "田中さん, V." does not peel where "田中さん, PhD" does #319

Description

@derek73

Same credential, three spellings, two answers:

parse("田中さん, PhD")     # title PhD, family 田中, suffix さん      ← peels
parse("田中さん, V.")      # family '田中さん', given 'V.'            ← does not
parse("田中さん, Ph. D.")  # family '田中さん', suffix 'Ph. D.'       ← does not

Not a regression — all three are byte-identical to 1.4.0 and to pre-#312 — but #312 fixed the first and left its siblings, so which behavior you get depends on whether the post-comma token passes an initial veto.

Why

#312 scoped the peel's site to the name-bearing runs: segments[:2] under FAMILY_COMMA, segments[0] otherwise. That rests on segments[1] being name text under a family comma. It usually is — but not always.

_segment.py picks SUFFIX_COMMA only when suffixy(groups[1]) and len(groups[0]) > 1. When the post-comma part is entirely suffix-shaped and the pre-comma part is a single word, the structure falls through to FAMILY_COMMA with segments[1] holding post-nominals rather than given-name text. _assign agrees with that reading — it runs _peel_leading_titles over that run and routes it to title/suffix.

So the peel walks into the one kind of run it was scoped away from, and the gap it was scoped against bites:

  • segment() admits a post-comma run on is_suffix_lenient
  • _is_post_nominal asks is_suffix_strict
  • the initial-shaped suffix words fall between them — measured, V., V, I are lenient-True and strict-False

An initial-shaped token therefore becomes the peel site, ends in no listed tail, and the peel is silently abandoned. Adding a word before the comma (Dr 田中さん, V.) flips the structure to SUFFIX_COMMA and it peels correctly.

Why it was not fixed in #318

The clean condition is "include segments[1] only when it is actually name text", which is what segment()'s own suffixy already decides. But suffixy is a closure inside segment(), and its comment warns it must stay in sync with group's _PH/_D merge — so a copy in _script_segment would be a third definition of one rule.

The cheap substitute was measured and rejected: all(is_suffix_lenient) fixes V. and Jr. but not Ph. D. (because Ph. alone is not lenient-suffix), leaving PhD and Ph. D. inconsistent — trading one arbitrary split for another.

田中さん, V. is pinned as-is by a parity case row in #318 so the limit is recorded rather than latent.

What the fix probably looks like

Extract suffixy from segment() into _pipeline/_vocab.py alongside is_suffix_lenient/is_suffix_strict, so segment, group and script_segment share one definition of "this run is post-nominals, not name". Then the peel's scope becomes: include the second run under a family comma unless suffixy says it is a suffix run.

Care needed on the Ph./D. merge — suffixy treats an adjacent pair as one unit, and group has a matching merge that the comment says must not drift.

Worth doing alongside anything else that wants the same predicate; it is the third caller that makes the extraction pay.

Found by whole-branch review on #318 (#312).

Metadata

Metadata

Assignees

Labels

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions