From: Petr Viktorin Date: Tue, 28 Jul 2026 07:19:46 +0000 (+0200) Subject: gh-154775: Don't accept duplicate plus sign when matching complex number (GH-154776) X-Git-Url: http://git.ipfire.org/gitweb/?a=commitdiff_plain;h=a85830c7f8456c047b02d4f3549113542cc01b72;p=thirdparty%2FPython%2Fcpython.git gh-154775: Don't accept duplicate plus sign when matching complex number (GH-154776) Co-authored-by: Bartosz Sławecki --- diff --git a/Grammar/python.gram b/Grammar/python.gram index ac1b4a64f38c..2713ba9466a0 100644 --- a/Grammar/python.gram +++ b/Grammar/python.gram @@ -568,7 +568,6 @@ real_number[expr_ty]: imaginary_number[expr_ty]: | imag=NUMBER { _PyPegen_ensure_imaginary(p, imag) } - | '+' imag=NUMBER { _PyPegen_ensure_imaginary(p, imag) } capture_pattern[pattern_ty]: | target=pattern_capture_target { _PyAST_MatchAs(NULL, target->v.Name.id, EXTRA) } diff --git a/Lib/test/test_patma.py b/Lib/test/test_patma.py index e3aaea84ea7c..0825d9d980c5 100644 --- a/Lib/test/test_patma.py +++ b/Lib/test/test_patma.py @@ -2835,14 +2835,6 @@ class TestPatma(unittest.TestCase): self.assertEqual(y, 0) def test_patma_265(self): - x = 0.25 - 1.75j - match x: - case 0.25 - +1.75j: - y = 0 - self.assertEqual(x, 0.25 - 1.75j) - self.assertEqual(y, 0) - - def test_patma_266(self): x = 0 match x: case +1e1000: @@ -3329,6 +3321,34 @@ class TestSyntaxErrors(unittest.TestCase): pass """) + def test_duplicate_sign_in_complex_1(self): + self.assert_syntax_error(""" + match ...: + case 0 ++ 0j: + pass + """) + + def test_duplicate_sign_in_complex_2(self): + self.assert_syntax_error(""" + match ...: + case 0 -+ 0j: + pass + """) + + def test_duplicate_sign_in_complex_3(self): + self.assert_syntax_error(""" + match ...: + case 0 +- 0j: + pass + """) + + def test_duplicate_sign_in_complex_4(self): + self.assert_syntax_error(""" + match ...: + case 0 -- 0j: + pass + """) + class TestTypeErrors(unittest.TestCase): def test_accepts_positional_subpatterns_0(self): diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-07-27-16-29-10.gh-issue-154775._ISRIk.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-07-27-16-29-10.gh-issue-154775._ISRIk.rst new file mode 100644 index 000000000000..b0035c7e1bc0 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-07-27-16-29-10.gh-issue-154775._ISRIk.rst @@ -0,0 +1,2 @@ +When matching a complex literal in :keyword:`case` statements, an extraneous +``+`` sign (for example, ``1++1j`` or ``1-+1j``) is no longer allowed. diff --git a/Parser/parser.c b/Parser/parser.c index 4f4fd3ed46d1..800db5b490fe 100644 --- a/Parser/parser.c +++ b/Parser/parser.c @@ -9355,7 +9355,7 @@ real_number_rule(Parser *p) return _res; } -// imaginary_number: NUMBER | '+' NUMBER +// imaginary_number: NUMBER static expr_ty imaginary_number_rule(Parser *p) { @@ -9392,33 +9392,6 @@ imaginary_number_rule(Parser *p) D(fprintf(stderr, "%*c%s imaginary_number[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "NUMBER")); } - { // '+' NUMBER - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> imaginary_number[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'+' NUMBER")); - Token * _literal; - expr_ty imag; - if ( - (_literal = _PyPegen_expect_token(p, 14)) // token='+' - && - (imag = _PyPegen_number_token(p)) // NUMBER - ) - { - D(fprintf(stderr, "%*c+ imaginary_number[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'+' NUMBER")); - _res = _PyPegen_ensure_imaginary ( p , imag ); - if ((_res == NULL || p->error_indicator) && PyErr_Occurred()) { - p->error_indicator = 1; - p->level--; - return NULL; - } - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s imaginary_number[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'+' NUMBER")); - } _res = NULL; done: p->level--;