Skip to content

Split vowel groups on hiatus when a high vowel carries the stress - #3

Open
tyza66 wants to merge 1 commit into
lari-pellini:mainfrom
tyza66:fix/syllables-hiatus
Open

tyza66 wants to merge 1 commit into
lari-pellini:mainfrom
tyza66:fix/syllables-hiatus

Conversation

@tyza66

@tyza66 tyza66 commented Oct 22, 2026

Copy link
Copy Markdown

What

Fixes #1: vowel groups are now split on hiatus when a high vowel (i, u)
carries the stress, so rainha counts 3 (ra-i-nha) and fotografia
counts 5 (fo-to-gra-fi-a) instead of 2 and 4.

Why

HIATUS_MARKERS = "íú" only matched an accented high vowel in second
position, and neither i nor u is in STRONG. So the pair ai/ia never
split, and every unaccented word with a high-vowel hiatus was undercounted.

The fix

Portuguese decides hiatus versus diphthong by whether the high vowel carries
the stress, so the counter now locates the stressed vowel first
(stressed_vowel) and then breaks a vowel group when a high vowel is a
nucleus rather than a glide:

rule example
a high vowel that carries the stress is a nucleus ra-i-nha, fo-to-gra-fi-a, sa-í-de, ru-ím
a stressed high vowel before a strong vowel also splits Ma-ri-a, po-e-si-a, a-tu-a
an unstressed high vowel after another vowel in the same group glides onto it, so the next vowel starts a new syllable prai-a, chei-o, sa-iu
two strong vowels in a row are two nuclei (unchanged) co-e-lho, le-ão

Three supporting changes came with it:

  • vowel groups are now index ranges instead of strings, so the stress can be
    compared against a position inside the group;
  • the silent u of que/gue/gui is dropped before counting;
  • HIATUS_MARKERS is replaced by HIGH, STRESS_MARK and HIATUS_WORDS
    (the old constant is gone, since it no longer describes the rule).

Rising diphthongs are deliberately left alone: dia, rua, pai, caixa,
história, família, diabo, médio all keep their current counts, and
the existing 11 words in test_portuguese_syllables still pass unchanged.

Tests

test_portuguese_syllables gains the words from the issue plus guards on both
sides of the new rule, and a new test pins the silent-u behaviour. The suite
is 9 runs / 60 assertions, still dependency-free and green on Ruby 3.1 and 3.3.

I also diffed the new counter against the old one over a 318-word Portuguese
word list: 32 words move to the correct count, 0 regress.

Known limits

This stays a heuristic, and two classes of word are still wrong:

  • Portuguese does not mark the stress of unaccented words, so the few common
    words where a high vowel is stressed instead of glided are listed in
    HIATUS_WORDS. That list is admittedly a stopgap; a real syllable
    dictionary or a stress model would replace it.
  • Some pairs are lexical and cannot be told apart from the spelling:
    criança (cri-an-ça) versus caixa (cai-xa), diálogo (di-á-lo-go)
    versus diabo (dia-bo). Those are unchanged from before.

Happy to rework any of this if you'd rather scope it differently.

Disclosure

This PR was written with AI assistance. I used
Alpha to locate the root
cause, prototype the rule set against a 318-word Portuguese word list, and
draft the patch and this description. Every change was reviewed by me before
committing, and I verified the diff is a strict improvement over the previous
counter with no regressions.

The old rule only broke a vowel group apart when the second vowel was an
accented high vowel or when both vowels were strong, so "ai" and "ia" were
always counted as one syllable: "rainha" gave 2 instead of 3 and
"fotografia" gave 4 instead of 5.

Track the stressed vowel and use it to decide whether a high vowel is a
nucleus or a glide:

- a high vowel that carries the stress is a nucleus ("ra-i-nha",
  "fo-to-gra-fi-a", "sa-í-de");
- a stressed high vowel before a strong vowel also splits ("Ma-ri-a",
  "a-tu-a");
- an unstressed high vowel after another vowel in the same group glides
  onto it, so the following vowel starts a new syllable ("prai-a",
  "chei-o", "sa-iu").

Rising diphthongs such as "dia", "rua", "cai" and "ria" still stay
together. The vowel groups are now index ranges so the stress can be
compared against the group, and the silent "u" of "que"/"gue"/"gui" is
dropped before counting.

Because Portuguese does not mark the stress of unaccented words, the
handful of common words where a high vowel is stressed instead of glided
("rainha", "sair", "raiz", ...) are listed in HIATUS_WORDS. Stress in
words like "criança" or "diálogo" is still lexical and stays wrong.
Copilot AI balanced review requested due to automatic review settings October 22, 2026 21:19

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

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.

Improve Portuguese syllable counting for hiatus like ra-i-nha and fi-a

2 participants