Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

c_parser: support parenthesized compounds #423

Merged
merged 3 commits into from Jul 7, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions pycparser/c_parser.py
Expand Up @@ -1564,6 +1564,10 @@ def p_expression(self, p):
p[1].exprs.append(p[3])
p[0] = p[1]

def p_parenthesized_compound_expression(self, p):
""" assignment_expression : LPAREN compound_statement RPAREN """
p[0] = p[2]

def p_typedef_name(self, p):
""" typedef_name : TYPEID """
p[0] = c_ast.IdentifierType([p[1]], coord=self._token_coord(p, 1))
Expand Down
53 changes: 53 additions & 0 deletions tests/test_c_parser.py
Expand Up @@ -85,8 +85,20 @@ def expand_init(init):
return ['Constant', init.type, init.value]
elif typ == ID:
return ['ID', init.name]
elif typ == Decl:
return ['Decl', init.name]
elif typ == UnaryOp:
return ['UnaryOp', init.op, expand_decl(init.expr)]
elif typ == BinaryOp:
return ['BinaryOp', expand_init(init.left), init.op, expand_init(init.right)]
elif typ == Compound:
blocks = []
if init.block_items:
blocks = [expand_init(i) for i in init.block_items]
return ['Compound', blocks]
else:
# Fallback to type name
return [typ.__name__]


class TestCParser_base(unittest.TestCase):
Expand Down Expand Up @@ -612,6 +624,47 @@ def test_compound_literals(self):
([['ID', 'a']], [['Constant', 'int', '1'], ['Constant', 'int', '2']]),
([['ID', 'b'], ['Constant', 'int', '0']], ['ID', 't'])])

def test_parenthesized_compounds(self):
e = self.parse(r'''
void foo() {
int a;
({});
({ 1; });
({ 1; 2; });
int b = ({ 1; });
int c, d = ({ int x = 1; x + 2; });
a = ({ int x = 1; 2 * x; });
}''')
body = e.ext[0].body.block_items

self.assertIsInstance(body[1], Compound)
self.assertEqual(body[1].block_items, None)

self.assertIsInstance(body[2], Compound)
self.assertEqual(len(body[2].block_items), 1)
self.assertIsInstance(body[2].block_items[0], Constant)

self.assertIsInstance(body[3], Compound)
self.assertEqual(len(body[3].block_items), 2)
self.assertIsInstance(body[3].block_items[0], Constant)
self.assertIsInstance(body[3].block_items[1], Constant)

self.assertIsInstance(body[4], Decl)
self.assertEqual(expand_init(body[4].init),
['Compound', [['Constant', 'int', '1']]])

self.assertIsInstance(body[5], Decl)
self.assertEqual(body[5].init, None)

self.assertIsInstance(body[6], Decl)
self.assertEqual(expand_init(body[6].init),
['Compound', [['Decl', 'x'], ['BinaryOp', ['ID', 'x'], '+', ['Constant', 'int', '2']]]])

self.assertIsInstance(body[7], Assignment)
self.assertIsInstance(body[7].rvalue, Compound)
self.assertEqual(expand_init(body[7].rvalue),
['Compound', [['Decl', 'x'], ['BinaryOp', ['Constant', 'int', '2'], '*', ['ID', 'x']]]])

def test_enums(self):
e1 = "enum mycolor op;"
e1_type = self.parse(e1).ext[0].type.type
Expand Down