From 0af7d8b5e61692fca899c7909b530b7e0909c15e Mon Sep 17 00:00:00 2001 From: Manuel Jacob Date: Thu, 29 Jan 2026 11:34:44 +0100 Subject: [PATCH] Add lexer support for complex literals. They are part of the current C2y ISO draft (included by N3298 [1]). [1] https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3298.htm --- pycparser/c_lexer.py | 8 ++++++-- tests/test_c_lexer.py | 15 +++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/pycparser/c_lexer.py b/pycparser/c_lexer.py index 4f66b244..b6c14d33 100644 --- a/pycparser/c_lexer.py +++ b/pycparser/c_lexer.py @@ -537,6 +537,7 @@ def _handle_pppragma(self) -> List[Token]: _bad_string_literal = '"' + _string_char + "*" + _bad_escape + _string_char + '*"' # floating constants (K&R2: A.2.5.3) +_floating_suffix_opt = r"([FfLl][iIjJ]?|[iIjJ][FfLl]?)?" _exponent_part = r"""([eE][-+]?[0-9]+)""" _fractional_constant = r"""([0-9]*\.[0-9]+)|([0-9]+\.)""" _floating_constant = ( @@ -546,7 +547,9 @@ def _handle_pppragma(self) -> List[Token]: + _exponent_part + "?)|([0-9]+" + _exponent_part - + "))[FfLl]?)" + + "))" + + _floating_suffix_opt + + ")" ) _binary_exponent_part = r"""([pP][+-]?[0-9]+)""" _hex_fractional_constant = ( @@ -561,7 +564,8 @@ def _handle_pppragma(self) -> List[Token]: + _hex_fractional_constant + ")" + _binary_exponent_part - + "[FfLl]?)" + + _floating_suffix_opt + + ")" ) diff --git a/tests/test_c_lexer.py b/tests/test_c_lexer.py index 00acddcd..ac203301 100644 --- a/tests/test_c_lexer.py +++ b/tests/test_c_lexer.py @@ -128,6 +128,21 @@ def test_hexadecimal_floating_constants(self): self.assertTokensTypes("0x.488641p0", ["HEX_FLOAT_CONST"]) self.assertTokensTypes("0X12.P0", ["HEX_FLOAT_CONST"]) + def test_complex_constants(self): + self.assertTokensTypes("1.2i", ["FLOAT_CONST"]) + self.assertTokensTypes("1.2I", ["FLOAT_CONST"]) + self.assertTokensTypes("1.2j", ["FLOAT_CONST"]) + self.assertTokensTypes("1.2J", ["FLOAT_CONST"]) + self.assertTokensTypes("1.2fi", ["FLOAT_CONST"]) + self.assertTokensTypes("1.2if", ["FLOAT_CONST"]) + + self.assertTokensTypes("0x1.2p3i", ["HEX_FLOAT_CONST"]) + self.assertTokensTypes("0x1.2p3I", ["HEX_FLOAT_CONST"]) + self.assertTokensTypes("0x1.2p3j", ["HEX_FLOAT_CONST"]) + self.assertTokensTypes("0x1.2p3J", ["HEX_FLOAT_CONST"]) + self.assertTokensTypes("0x1.2p3fi", ["HEX_FLOAT_CONST"]) + self.assertTokensTypes("0x1.2p3if", ["HEX_FLOAT_CONST"]) + def test_char_constants(self): self.assertTokensTypes(r"""'x'""", ["CHAR_CONST"]) self.assertTokensTypes(r"""L'x'""", ["WCHAR_CONST"])