From 2e9331244f1e2236eb70ae6c83e4d969bf0eb54a Mon Sep 17 00:00:00 2001 From: Jordy Ruiz Date: Sat, 7 Jan 2023 15:37:53 +0100 Subject: [PATCH 1/3] Support _Pragma, a C99 alternative to #pragma See https://gcc.gnu.org/onlinedocs/cpp/Pragmas.html --- pycparser/c_lexer.py | 1 + pycparser/c_parser.py | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/pycparser/c_lexer.py b/pycparser/c_lexer.py index d68d8ebf..22c64bc7 100644 --- a/pycparser/c_lexer.py +++ b/pycparser/c_lexer.py @@ -112,6 +112,7 @@ def _make_tok_location(self, token): '_BOOL', '_COMPLEX', '_NORETURN', '_THREAD_LOCAL', '_STATIC_ASSERT', '_ATOMIC', '_ALIGNOF', '_ALIGNAS', + '_PRAGMA', ) keyword_map = {} diff --git a/pycparser/c_parser.py b/pycparser/c_parser.py index c9782e09..edc01dff 100644 --- a/pycparser/c_parser.py +++ b/pycparser/c_parser.py @@ -574,8 +574,11 @@ def p_pp_directive(self, p): def p_pppragma_directive(self, p): """ pppragma_directive : PPPRAGMA | PPPRAGMA PPPRAGMASTR + | _PRAGMA LPAREN unified_string_literal RPAREN """ - if len(p) == 3: + if len(p) == 5: + p[0] = c_ast.Pragma(p[3], self._token_coord(p, 2)) + elif len(p) == 3: p[0] = c_ast.Pragma(p[2], self._token_coord(p, 2)) else: p[0] = c_ast.Pragma("", self._token_coord(p, 1)) From 07c54549854cf03b461a4bc399069f797c7a5d08 Mon Sep 17 00:00:00 2001 From: Jordy Ruiz Date: Sat, 7 Jan 2023 16:12:27 +0100 Subject: [PATCH 2/3] Test cases for _Pragma --- tests/test_c_lexer.py | 17 ++++++++++++++--- tests/test_c_parser.py | 5 +++++ 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/tests/test_c_lexer.py b/tests/test_c_lexer.py index 03fd838e..2975b800 100644 --- a/tests/test_c_lexer.py +++ b/tests/test_c_lexer.py @@ -357,6 +357,7 @@ def test_preprocessor_pragma(self): #pragma "string" #pragma somestring="some_other_string" #pragma id 124124 and numbers 0235495 + _Pragma("something else") 59 ''' # Check that pragmas are tokenized, including trailing string @@ -389,9 +390,19 @@ def test_preprocessor_pragma(self): tb = self.clex.token() self.assertEqual(tb.type, 'PPPRAGMASTR') - t6 = self.clex.token() - self.assertEqual(t6.type, 'INT_CONST_DEC') - self.assertEqual(t6.lineno, 12) + t6a = self.clex.token() + t6l = self.clex.token() + t6b = self.clex.token() + t6r = self.clex.token() + self.assertEqual(t6a.type, '_PRAGMA') + self.assertEqual(t6l.type, 'LPAREN') + self.assertEqual(t6b.type, 'STRING_LITERAL') + self.assertEqual(t6b.value, '"something else"') + self.assertEqual(t6r.type, 'RPAREN') + + t7 = self.clex.token() + self.assertEqual(t7.type, 'INT_CONST_DEC') + self.assertEqual(t7.lineno, 13) diff --git a/tests/test_c_parser.py b/tests/test_c_parser.py index 9b536226..25682ad6 100755 --- a/tests/test_c_parser.py +++ b/tests/test_c_parser.py @@ -1736,6 +1736,7 @@ def test_pragma(self): struct s { #pragma baz } s; + _Pragma("other \"string\"") ''' s1_ast = self.parse(s1) self.assertIsInstance(s1_ast.ext[0], Pragma) @@ -1758,6 +1759,10 @@ def test_pragma(self): self.assertEqual(s1_ast.ext[2].type.type.decls[0].string, 'baz') self.assertEqual(s1_ast.ext[2].type.type.decls[0].coord.line, 13) + self.assertIsInstance(s1_ast.ext[3], Pragma) + self.assertEqual(s1_ast.ext[3].string.value, r'"other \"string\""') + self.assertEqual(s1_ast.ext[3].coord.line, 15) + def test_pragmacomp_or_statement(self): s1 = r''' void main() { From 0fcd5017fa8fd932869aaf6bea2fcc48d3917fed Mon Sep 17 00:00:00 2001 From: Jordy Ruiz Date: Sun, 8 Jan 2023 03:00:36 +0100 Subject: [PATCH 3/3] Add explanatory comment for _PRAGMA and PPPRAGMA --- pycparser/c_parser.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pycparser/c_parser.py b/pycparser/c_parser.py index edc01dff..d31574a5 100644 --- a/pycparser/c_parser.py +++ b/pycparser/c_parser.py @@ -571,6 +571,11 @@ def p_pp_directive(self, p): self._parse_error('Directives not supported yet', self._token_coord(p, 1)) + # This encompasses two types of C99-compatible pragmas: + # - The #pragma directive: + # # pragma character_sequence + # - The _Pragma unary operator: + # _Pragma ( " string_literal " ) def p_pppragma_directive(self, p): """ pppragma_directive : PPPRAGMA | PPPRAGMA PPPRAGMASTR