runtime(python): Update syntax, improve pythonNumber pattern performance

Commit: 
https://github.com/vim/vim/commit/2cf18fcc240030880bbd138e5174e436a3f20823
Author: Doug Kearns <[email protected]>
Date:   Wed Mar 11 19:47:55 2026 +0000

    runtime(python): Update syntax, improve pythonNumber pattern performance
    
    - Improve the performance of all pythonNumber patterns by unrolling
      digit/underscore sequence loops.
    - Split the float literal pattern into two simpler patterns.
    
    fixes:  #19625 (Reported by James McCoy)
    closes: #19630
    
    Signed-off-by: Doug Kearns <[email protected]>
    Signed-off-by: Christian Brabandt <[email protected]>

diff --git a/runtime/syntax/python.vim b/runtime/syntax/python.vim
index 456a9825a..e48346899 100644
--- a/runtime/syntax/python.vim
+++ b/runtime/syntax/python.vim
@@ -5,6 +5,7 @@
 " 2025 Sep 25 by Vim Project: fix wrong type highlighting #18394
 " 2025 Dec 03 by Vim Project: highlight t-strings #18679
 " 2026 Jan 26 by Vim Project: highlight constants #18922
+" 2026 Mar 11 by Vim Project: fix number performance #19630
 " Credits:     Neil Schemenauer <[email protected]>
 "              Dmitry Vasiliev
 "              Rob B
@@ -270,16 +271,21 @@ syn match   pythonEscape  "\$"
 " https://docs.python.org/reference/lexical_analysis.html#numeric-literals
 if !exists("python_no_number_highlight")
   " numbers (including complex)
-  syn match   pythonNumber     "\<0[oO]\%(_\=\o\)\+\>"
-  syn match   pythonNumber     "\<0[xX]\%(_\=\x\)\+\>"
-  syn match   pythonNumber     "\<0[bB]\%(_\=[01]\)\+\>"
-  syn match   pythonNumber     "\<\%([1-9]\%(_\=\d\)*\|0\+\%(_\=0\)*\)\>"
-  syn match   pythonNumber     "\<\d\%(_\=\d\)*[jJ]\>"
-  syn match   pythonNumber     "\<\d\%(_\=\d\)*[eE][+-]\=\d\%(_\=\d\)*[jJ]\=\>"
+  syn match   pythonNumber     "\<0[oO]_\=\o\+\%(_\o\+\)*\>"
+  syn match   pythonNumber     "\<0[xX]_\=\x\+\%(_\x\+\)*\>"
+  syn match   pythonNumber     "\<0[bB]_\=[01]\+\%(_[01]\+\)*\>"
+  syn match   pythonNumber     "\<\%([1-9]\d*\%(_\d\+\)*\|0\+\%(_0\+\)*\)\>"
+  syn match   pythonNumber     "\<\d\+\%(_\d\+\)*[jJ]\>"
+  syn match   pythonNumber     
"\<\d\+\%(_\d\+\)*[eE][+-]\=\d\+\%(_\d\+\)*[jJ]\=\>"
+  " \d\.
   syn match   pythonNumber
-        \ "\<\d\%(_\=\d\)*\.\%([eE][+-]\=\d\%(_\=\d\)*\)\=[jJ]\=\%(\W\|$\)\@="
+        \ 
"\<\d\+\%(_\d\+\)*\.\%([eE][+-]\=\d\+\%(_\d\+\)*\)\=[jJ]\=\%(\W\|$\)\@="
+  " \d\.\d
   syn match   pythonNumber
-        \ 
"\%(^\|\W\)\@1<=\%(\d\%(_\=\d\)*\)\=\.\d\%(_\=\d\)*\%([eE][+-]\=\d\%(_\=\d\)*\)\=[jJ]\=\>"
+        \ 
"\<\d\+\%(_\d\+\)*\.\d\+\%(_\d\+\)*\%([eE][+-]\=\d\+\%(_\d\+\)*\)\=[jJ]\=\>"
+  " \.\d
+  syn match   pythonNumber
+        \ 
"\%(^\|\W\)\@1<=\.\d\+\%(_\d\+\)*\%([eE][+-]\=\d\+\%(_\d\+\)*\)\=[jJ]\=\>"
 endif
 
 " Group the built-ins in the order in the 'Python Library Reference' for
diff --git a/runtime/syntax/testdir/dumps/python_numbers_00.dump 
b/runtime/syntax/testdir/dumps/python_numbers_00.dump
new file mode 100644
index 000000000..6f6506400
--- /dev/null
+++ b/runtime/syntax/testdir/dumps/python_numbers_00.dump
@@ -0,0 +1,20 @@
+>#+0#0000e05#ffffff0| |N|u|m|e|r|i|c| |l|i|t|e|r|a|l|s| +0#0000000&@56
+|#+0#0000e05&| 
|h|t@1|p|s|:|/@1|d|o|c|s|.|p|y|t|h|o|n|.|o|r|g|/|3|/|r|e|f|e|r|e|n|c|e|/|l|e|x|i|c|a|l|_|a|n|a|l|y|s|i|s|.|h|t|m|l|#|n|u|m|e|r|i|c|-|l|i|t|e|r|a|l
+|s| +0#0000000&@73
+@75
+|#+0#0000e05&| |I|n|t|e|g|e|r| |l|i|t|e|r|a|l|s| +0#0000000&@56
+@75
+|7+0#e000002&| +0#0000000&@73
+|3+0#e000002&| +0#0000000&@73
+|2+0#e000002&|1|4|7|4|8|3|6|4|7| +0#0000000&@64
+@75
+|7+0#e000002&|9|2@1|8|1|6|2|5|1|4|2|6|4|3@1|7|5|9|3|5|4|3|9|5|0|3@1|6|7|9|2@1|8|1|6|2|5|1|4|2|6|4|3@1|7|5|9|3|5|4|3|9|5|0|3@1|6|
 +0#0000000&@16
+@75
+|1+0#e000002&|0@1|_|0@2|_|0@2|_|0@2| +0#0000000&@59
+|1+0#e000002&|0@10| +0#0000000&@62
+|1+0#e000002&|_|0@1|_|0@1|_|0@1|_|0@1|_|0@2| +0#0000000&@57
+@75
+|0+0#e000002&|b|1|0@1|1@1|0|1@2| +0#0000000&@63
+|0+0#e000002&|b|_|1@2|0|_|0|1|0|1| +0#0000000&@62
+|0+0#e000002&|o|1|7@1| +0#0000000&@69
+@57|1|,|1| @10|T|o|p| 
diff --git a/runtime/syntax/testdir/dumps/python_numbers_01.dump 
b/runtime/syntax/testdir/dumps/python_numbers_01.dump
new file mode 100644
index 000000000..eda3caae3
--- /dev/null
+++ b/runtime/syntax/testdir/dumps/python_numbers_01.dump
@@ -0,0 +1,20 @@
+|1+0#e000002#ffffff0|0@10| +0#0000000&@62
+|1+0#e000002&|_|0@1|_|0@1|_|0@1|_|0@1|_|0@2| +0#0000000&@57
+@75
+|0+0#e000002&|b|1|0@1|1@1|0|1@2| +0#0000000&@63
+|0+0#e000002&|b|_|1@2|0|_|0|1|0|1| +0#0000000&@62
+>0+0#e000002&|o|1|7@1| +0#0000000&@69
+|0+0#e000002&|o|3|7@1| +0#0000000&@69
+|0+0#e000002&|x|d|e|a|d|b|e@1|f| +0#0000000&@64
+|0+0#e000002&|x|D|e|a|d|_|B|e@1|f| +0#0000000&@63
+@75
+|#+0#0000e05&| |F|l|o|a|t|i|n|g|-|p|o|i|n|t| |l|i|t|e|r|a|l|s| +0#0000000&@49
+@75
+|2+0#e000002&|.|7|1|8|2|8| +0#0000000&@67
+|4+0#e000002&|.|0| +0#0000000&@71
+@75
+|9+0#e000002&|6|_|4|8|5|.|3@1|2|_|1|2|3| +0#0000000&@60
+|3+0#e000002&|.|1|4|_|1|5|_|9|3| +0#0000000&@64
+@75
+|1+0#e000002&|0|.| +0#0000000&@1|#+0#0000e05&| |(|e|q|u|i|v|a|l|e|n|t| |t|o| 
|1|0|.|0|)| +0#0000000&@47
+@57|1|8|,|1| @9|2|5|%| 
diff --git a/runtime/syntax/testdir/dumps/python_numbers_02.dump 
b/runtime/syntax/testdir/dumps/python_numbers_02.dump
new file mode 100644
index 000000000..5ea9c1e74
--- /dev/null
+++ b/runtime/syntax/testdir/dumps/python_numbers_02.dump
@@ -0,0 +1,20 @@
+|1+0#e000002#ffffff0|0|.| +0#0000000&@1|#+0#0000e05&| |(|e|q|u|i|v|a|l|e|n|t| 
|t|o| |1|0|.|0|)| +0#0000000&@47
+|.+0#e000002&|0@1|1| +0#0000000&@1|#+0#0000e05&| |(|e|q|u|i|v|a|l|e|n|t| |t|o| 
|0|.|0@1|1|)| +0#0000000&@45
+@75
+|1+0#e000002&|.|0|e|3| +0#0000000&@1|#+0#0000e05&| |(|r|e|p|r|e|s|e|n|t|s| 
|1|.|0|×|1|0|³|,| |o|r| |1|0@2|.|0|)| +0#0000000&@34
+|1+0#e000002&|.|1|6@1|e|-|5| +0#0000000&@1|#+0#0000e05&| 
|(|r|e|p|r|e|s|e|n|t|s| |1|.|1|6@1|×|1|0|⁻|⁵|,| |o|r| |0|.|0@3|1@1|6@1|)| 
+0#0000000&@24
+>6+0#e000002&|.|0|2@1|1|4|0|7|6|e|+|2|3| +0#0000000&@1|#+0#0000e05&| 
|(|r|e|p|r|e|s|e|n|t|s| |6|.|0|2@1|1|4|0|7|6|×|1|0|²|³|,| |o|r| 
|6|0|2@1|1|4|0|7|6|0@14|.
+|)| +0#0000000&@73
+@75
+|1+0#e000002&|e|3| +0#0000000&@1|#+0#0000e05&| |(|e|q|u|i|v|a|l|e|n|t| |t|o| 
|1|.|e|3| |a|n|d| |1|.|0|e|3|)| +0#0000000&@37
+|0+0#e000002&|e|0| +0#0000000&@1|#+0#0000e05&| |(|e|q|u|i|v|a|l|e|n|t| |t|o| 
|0|.|)| +0#0000000&@49
+@75
+|#+0#0000e05&| |I|m|a|g|i|n|a|r|y| |l|i|t|e|r|a|l|s| +0#0000000&@54
+@75
+|3+0#e000002&|++0#0000000&|4+0#e000002&|.|2|j| +0#0000000&@68
+@75
+|3+0#e000002&| +0#0000000&|+| |4+0#e000002&|.|2|j| +0#0000000&@66
+@75
+|4+0#e000002&|.|2|j| +0#0000000&@70
+|3+0#e000002&|.|1|4|j| +0#0000000&@69
+@57|3|6|,|1| @9|6|2|%| 
diff --git a/runtime/syntax/testdir/dumps/python_numbers_03.dump 
b/runtime/syntax/testdir/dumps/python_numbers_03.dump
new file mode 100644
index 000000000..8b42f433f
--- /dev/null
+++ b/runtime/syntax/testdir/dumps/python_numbers_03.dump
@@ -0,0 +1,20 @@
+|3+0#e000002#ffffff0|.|1|4|j| +0#0000000&@69
+|1+0#e000002&|0|.|j| +0#0000000&@70
+|.+0#e000002&|0@1|1|j| +0#0000000&@69
+|1+0#e000002&|e|1|0@1|j| +0#0000000&@68
+|3+0#e000002&|.|1|4|e|-|1|0|j| +0#0000000&@65
+>3+0#e000002&|.|1|4|_|1|5|_|9|3|j| +0#0000000&@63
+@75
+|1+0#e000002&|0|j| +0#0000000&@71
+|0+0#e000002&|j| +0#0000000&@72
+|1+0#e000002&|0@23|j| +0#0000000&@2|#+0#0000e05&| |e|q|u|i|v|a|l|e|n|t| |t|o| 
|1|e|+|2|4|j| +0#0000000&@23
+@75
+|3+0#e000002&|.|1|4|J| +0#0000000&@2|#+0#0000e05&| |e|q|u|i|v|a|l|e|n|t| |t|o| 
|3|.|1|4|j| +0#0000000&@45
+@75
+@75
+@75
+|#+0#0000e05&| |I|s@1|u|e| |#|1|9|6|2|5| |(|r|u|n|t|i|m|e|(|p|y|t|h|o|n|)|:| 
|L|a|r|g|e| |n|u|m|b|e|r| |l|i|t|e|r|a|l|s| |c|a|u|s|e| |E|3|6|3|)| 
+0#0000000&@8
+@75
+|N|=|2+0#e000002&|1|4|0|3|2|4|6|5|0|2|4|0|7|4@1|9|6|1|2|6|4@1|2|3|0|7|2|8|3|9|3@2|5|6|3|0@1|8|6|1|4|7|1|5|1|4@1|7|5@1|0|1|7@1|9|7@1|5|4|9|2|0|8@1|1|4|1|8|0|2|3
+|4@1|7|1|4|0|1|3|6@1|4|3@1|4|5@1|1|9|0|9|5|8|0|4|6|7|9|6|1|0|9@1|2|8|5|1|8|7|2|4|7|0|9|1|4|5|8|7|6|8|7|3|9|6|2|6|1|9|2|1|5@1|7|3|6|3|0|4|7|4|5|4|@+0#4040ff13&@2
+| +0#0000000&@56|5|3|,|1| @9|9|5|%| 
diff --git a/runtime/syntax/testdir/dumps/python_numbers_04.dump 
b/runtime/syntax/testdir/dumps/python_numbers_04.dump
new file mode 100644
index 000000000..2a70defa9
--- /dev/null
+++ b/runtime/syntax/testdir/dumps/python_numbers_04.dump
@@ -0,0 +1,20 @@
+|N+0&#ffffff0|=|2+0#e000002&|1|4|0|3|2|4|6|5|0|2|4|0|7|4@1|9|6|1|2|6|4@1|2|3|0|7|2|8|3|9|3@2|5|6|3|0@1|8|6|1|4|7|1|5|1|4@1|7|5@1|0|1|7@1|9|7@1|5|4|9|2|0|8@1|1|4|1|8|0|2|3
+|4@1|7|1|4|0|1|3|6@1|4|3@1|4|5@1|1|9|0|9|5|8|0|4|6|7|9|6|1|0|9@1|2|8|5|1|8|7|2|4|7|0|9|1|4|5|8|7|6|8|7|3|9|6|2|6|1|9|2|1|5@1|7|3|6|3|0|4|7|4|5|4|7@1|0
+|5|2|0|8|0|5|1@1|9|0|5|6|4|9|3|1|0|6@1|8|1| +0#0000000&@53
+> @74
+|~+0#4040ff13&| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+| +0#0000000&@56|6@1|,|0|-|1| @7|B|o|t| 

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion visit 
https://groups.google.com/d/msgid/vim_dev/E1w0Pit-000aKr-UR%40256bit.org.

Raspunde prin e-mail lui