diff options
author | Jordan Yates <jordan.yates.au@gmail.com> | 2021-07-08 00:11:25 +1000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-07-07 07:11:25 -0700 |
commit | 56b14671b558c06899ab475402e265fe4475bc18 (patch) | |
tree | 5427b4b4c69989f83fde6addce830c5d3a4a2eeb /tests | |
parent | c819d537f32989364791b58493f1fec5ca3de062 (diff) | |
download | pycparser-56b14671b558c06899ab475402e265fe4475bc18.tar.gz |
c_parser: support parenthesized compounds (#423)
* c_parser: support parenthesized compounds
Support parenthesized compound statements as described here:
https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html
Signed-off-by: Jordan Yates <jordan.yates@data61.csiro.au>
* test_c_parser: support additional initializers
Add support to `expand_init` for additional `c_ast` types. If a type
is not explicitly handled, return the type name instead of `None`.
Signed-off-by: Jordan Yates <jordan.yates@data61.csiro.au>
* test_c_parser: test parenthesized compounds
Add parsing tests for various situations of parenthesized compound
statements. The complete tree generated by the test string is:
```
FileAST:
FuncDef:
Decl: foo, [], [], []
FuncDecl:
TypeDecl: foo, []
IdentifierType: ['void']
Compound:
Decl: a, [], [], []
TypeDecl: a, []
IdentifierType: ['int']
Compound:
Compound:
Constant: int, 1
Compound:
Constant: int, 1
Constant: int, 2
Decl: b, [], [], []
TypeDecl: b, []
IdentifierType: ['int']
Compound:
Constant: int, 1
Decl: c, [], [], []
TypeDecl: c, []
IdentifierType: ['int']
Decl: d, [], [], []
TypeDecl: d, []
IdentifierType: ['int']
Compound:
Decl: x, [], [], []
TypeDecl: x, []
IdentifierType: ['int']
Constant: int, 1
BinaryOp: +
ID: x
Constant: int, 2
Assignment: =
ID: a
Compound:
Decl: x, [], [], []
TypeDecl: x, []
IdentifierType: ['int']
Constant: int, 1
BinaryOp: *
Constant: int, 2
ID: x
```
Signed-off-by: Jordan Yates <jordan.yates@data61.csiro.au>
Diffstat (limited to 'tests')
-rwxr-xr-x | tests/test_c_parser.py | 53 |
1 files changed, 53 insertions, 0 deletions
diff --git a/tests/test_c_parser.py b/tests/test_c_parser.py index f9f5281..a46fb1a 100755 --- a/tests/test_c_parser.py +++ b/tests/test_c_parser.py @@ -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): @@ -612,6 +624,47 @@ class TestCParser_fundamentals(TestCParser_base): ([['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 |