Skip to content

fix: tokenize currency/symbol chars as punct, not control chars (#500) - #685

Merged
ddehilster merged 1 commit into
masterfrom
fix/tokenize-currency-symbols
Jul 6, 2026
Merged

ddehilster merged 1 commit into
masterfrom
fix/tokenize-currency-symbols

Conversation

@ddehilster

Copy link
Copy Markdown
Member

Summary

Fixes #500: currency symbols like £ ¥ € were tokenized as control characters instead of symbols.

Root cause

£ (U+00A3, Unicode category Sc = currency symbol) isn't matched by unicu::isPunct (ICU's u_ispunct excludes Sc), nor by the alpha/num/white checks — so Tok::nextTok fell through to the PNCTRL (control-char) bucket (tok.cpp). dicttok then stamped a bogus ("CTRL" <lead-byte>) attribute — e.g. £ (UTF-8 C2 A3) showed as ("CTRL" 194).

Fix

  • New unicu::isSymbol() — true for currency / math / modifier / other symbol categories (u_charType).
  • Tok::nextTok classifies symbols as PNPUNCT before the PNCTRL fallback. This covers both the tokenize and dicttok passes (dicttok calls nextTok).

Result

Char Before After
$ punct punct
£ ¥ € ctrl + ("CTRL" 194) punct ✅

Blast radius is minimal: ASCII symbols (+ < = > | ~) were already caught by isPunct128, so only previously-misclassified non-ASCII symbols move from PNCTRL to PNPUNCT.

Testing

  • £ ¥ € now tokenize as punct (no spurious CTRL).
  • Regression: emailaddress still extracts email; plain ASCII (alpha/punct/num) unchanged.

Not addressed

The legacy byte-based cmltok tokenizer (rarely used) is still non-Unicode-aware; fixing it means a UTF-8 rewrite — out of scope.


⚠️ Merge order: bumps NLP_ENGINE_VERSION → 3.7.2, which assumes #684 (3.7.1) merges first. If this merges before #684, resolve the trivial main.cpp version-line conflict (keep 3.7.2) so master doesn't skip 3.7.1.

Fixes #500.

🤖 Generated with Claude Code

…500)

Currency symbols like £ ¥ € (Unicode category Sc) are not matched by
unicu::isPunct (ICU's u_ispunct excludes Sc), nor by the alpha/num/white
checks, so Tok::nextTok dropped them into the PNCTRL (control-char) bucket.
dicttok then stamped a bogus ("CTRL" <lead-byte>) attribute -- e.g. £ (UTF-8
C2 A3) showed as ("CTRL" 194).

- Add unicu::isSymbol(): true for currency/math/modifier/other symbol
  categories (u_charType).
- Tok::nextTok: classify symbols as PNPUNCT before the PNCTRL fallback. This
  covers both the `tokenize` and `dicttok` passes (dicttok calls nextTok).

Now $ £ ¥ € all tokenize as punct (like $ already did), with no spurious CTRL
attribute. Blast radius is minimal: ASCII symbols (+ < = > | ~) were already
caught by isPunct128, so only previously-misclassified non-ASCII symbols move
from PNCTRL to PNPUNCT.

Verified: £ ¥ € -> punct; emailaddress analyzer still extracts email; plain
ASCII (alpha/punct/num) unchanged. Not addressed: the legacy byte-based cmltok
tokenizer (rarely used) remains non-Unicode-aware.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@ddehilster
ddehilster force-pushed the fix/tokenize-currency-symbols branch from f44c954 to 55fe7c8 Compare July 6, 2026 21:17
@ddehilster
ddehilster merged commit 75d6c4e into master Jul 6, 2026
7 checks passed
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.

Reading currency like control characters in dictionary

1 participant