Skip to content

Fix Roman-numeral rules: ^{N} is not "repeat N times", use ^N - #25

Open
snomos wants to merge 1 commit into
coltekin:masterfrom
snomos:fix-caret-brace-repeat-not-repetition
Open

Fix Roman-numeral rules: ^{N} is not "repeat N times", use ^N#25
snomos wants to merge 1 commit into
coltekin:masterfrom
snomos:fix-caret-brace-repeat-not-repetition

Conversation

@snomos

@snomos snomos commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

xfst/foma's repeat operator only has two brace-taking forms: ^{n,m} (a range, comma required) and ^n (no braces, exactly n times). ^{n} with a single number and no comma isn't valid repeat syntax at all — foma silently parses the braces as a quoted string literal instead, so [X]^{2} means "X" followed by the literal two-character string "2", not "X repeated twice".

This means seven of the Roman-numeral matching rules in morph-phon.xfst (the block around VowelHarmony, tagged ! 2, ! 3, ! 7, ! 8, ! 20, ! 30, ! 70, ! 80) were never matching what their own trailing comments say they match:

$ foma -e 'regex [Ⅰ|I|ⅰ|i]^{2};' -e 'print words' -s
Ⅰ2
I2
ⅰ2
i2

vs. the intended:

$ foma -e 'regex [Ⅰ|I|ⅰ|i]^2;' -e 'print words' -s
ⅠⅠ
ⅠI
Ⅰⅰ
Ⅰi
IⅠ
II
...

The rule commented ! 2 (Roman "II") was actually matching things like "I2", never "II".

Two lines a little further up in the same define already use the correct ^n form for this exact purpose (%0^2, in NumericInsSilentP), so this looks like a straightforward slip rather than an intentional choice elsewhere.

Fix

Drop the braces on the 7 affected rules (^{2}^2, ^{3}^3), matching the already-correct ^n usage used elsewhere in the same file. ^{3,4} (a genuine range, two lines below) is untouched.

How I found this

While getting this repo building under a newer Rust reimplementation of foma (divvun/foma-rs), that tool rejected ^{2} as a syntax error outright. Classic foma doesn't error, but as shown above it silently does something different from what was intended, so this is a genuine pre-existing bug rather than a compatibility gap between the two implementations.

xfst/foma's repeat operator only has two brace-taking forms: ^{n,m} (a
range, comma required) and ^n (no braces, exactly n). ^{n} with a single
number and no comma isn't valid repeat syntax at all -- foma silently
parses the braces as a quoted string literal instead, so [X]^{2} means
"X" followed by the literal two-character string "2", not "X repeated
twice".

This means seven of the Roman-numeral matching rules in
VowelHarmony/FSDevoicing's neighbourhood (the "^Ⅰ|I|ⅰ|i]^{2}" etc. block,
tagged "! 2", "! 3", "! 7", "! 8", "! 20", "! 30", "! 70", "! 80") were
never matching what their own comments say they match:

    $ foma -e 'regex [Ⅰ|I|ⅰ|i]^{2};' -e 'print words' -s
    Ⅰ2
    I2
    ⅰ2
    i2

    $ foma -e 'regex [Ⅰ|I|ⅰ|i]^2;' -e 'print words' -s
    ⅠⅠ
    ⅠI
    Ⅰⅰ
    Ⅰi
    IⅠ
    II
    ...

The rule commented "! 2" (i.e. Roman "II") was actually matching things
like "I2", never "II". Two lines already use the correct ^n form for
this exact purpose a few lines up (%0^2, in NumericInsSilentP), so this
looks like a straightforward slip rather than an intentional choice.

Fixes the 7 affected rules by dropping the braces, matching the
already-correct ^n usage used elsewhere in the same file.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
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.

1 participant