Skip to content

Match only ASCII digits in the lexer number patterns - #195

Open
FelippeRoza wants to merge 1 commit into
masterfrom
fix-ascii-digit-regexes
Open

Match only ASCII digits in the lexer number patterns#195
FelippeRoza wants to merge 1 commit into
masterfrom
fix-ascii-digit-regexes

Conversation

@FelippeRoza

Copy link
Copy Markdown
Collaborator

In Python 3 \d matches every Unicode decimal digit, so the lexers read full-width digits as numbers. \tempo 4 = 60 lexes 60 as an IntegerValue and #(display 42) lexes 42 as a Number, though neither is legal LilyPond. Fixes #166.

Replaced with [0-9] in the 12 patterns that match a digit: 3 in scheme.py, 8 in lilypond.py, 1 in html.py.

Six other \d uses are left alone on purpose. They sit inside negated classes or negative lookaheads, where \d correctly excludes every digit. Rewriting [^\W\d_] as [^\W0-9_] would start accepting 4 as an identifier character, which is this bug rather than a fix for it.

tests/test_lex.py is new, so this is the first test for the lexers. Mutation testing covers 10 of the 12 patterns. Scaling and TempoSeparator resist it because both need a valid ASCII number earlier in the expression, so full-width input never reaches them at all.

The html.py line is the loosest fit, HTML numeric character references being a different language. Happy to drop it if you would rather keep this to the LilyPond and Scheme lexers.

In Python 3 \d matches every Unicode decimal digit, so the lexers read
full-width digits as numbers. \tempo 4 = 60 lexed 60 as an IntegerValue and
#(display 42) lexed 42 as a Number, though neither is legal LilyPond.

Replaced \d with [0-9] in the 12 patterns that match a digit, across
ly/lex/scheme.py, ly/lex/lilypond.py and ly/lex/html.py.

Six other \d uses are left as they are. They sit inside negated character
classes or negative lookaheads, where \d correctly excludes every digit.
Rewriting [^\W\d_] as [^\W0-9_] would start accepting 4 as an identifier
character, which is the bug this issue reports rather than a fix for it.

Fixes #166
@bmjcode

bmjcode commented Aug 21, 2026

Copy link
Copy Markdown
Member

In Python 3 \d matches every Unicode decimal digit, so the lexers read full-width digits as numbers. \tempo 4 = 60 lexes 60 as an IntegerValue and #(display 42) lexes 42 as a Number, though neither is legal LilyPond.

This is a good explanation. I'd add a comment in the source files as well so future maintainers will understand why not to change it back. (Something slightly briefer like '\d' matches Unicode digits that are not legal LilyPond is fine.)

Six other \d uses are left alone on purpose. They sit inside negated classes or negative lookaheads, where \d correctly excludes every digit. Rewriting [^\W\d_] as [^\W0-9_] would start accepting 4 as an identifier character, which is this bug rather than a fix for it.

This should also be included as a comment.

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.

scheme.py: wrong match of ASCII digits

2 participants