diff options
-rw-r--r-- | CHANGES | 4 | ||||
-rw-r--r-- | pycparser/_c_ast.cfg | 6 | ||||
-rw-r--r-- | pycparser/c_ast.py | 5 | ||||
-rw-r--r-- | pycparser/c_parser.py | 23 | ||||
-rw-r--r-- | tests/test_c_parser.py | 42 |
5 files changed, 51 insertions, 29 deletions
@@ -1,6 +1,8 @@ + Version 2.11 (??) - - + - Add support for C99 6.5.3.7 p7 - qualifiers within array dimensions in + function declarations. Started with issue #21 (reported with initial patch + by Robin Martinjak). + Version 2.10 (03.08.2013) diff --git a/pycparser/_c_ast.cfg b/pycparser/_c_ast.cfg index 2596de6..b9fce05 100644 --- a/pycparser/_c_ast.cfg +++ b/pycparser/_c_ast.cfg @@ -13,7 +13,11 @@ # License: BSD #----------------------------------------------------------------- -ArrayDecl: [type*, dim*] +# ArrayDecl is a nested declaration of an array with the given type. +# dim: the dimension (for example, constant 42) +# dim_quals: list of dimension qualifiers, to support C99's allowing 'const' +# and 'static' within the array dimension in function declarations. +ArrayDecl: [type*, dim*, dim_quals] ArrayRef: [name*, subscript*] diff --git a/pycparser/c_ast.py b/pycparser/c_ast.py index e6c6574..212019a 100644 --- a/pycparser/c_ast.py +++ b/pycparser/c_ast.py @@ -127,9 +127,10 @@ class NodeVisitor(object): class ArrayDecl(Node): - def __init__(self, type, dim, coord=None): + def __init__(self, type, dim, dim_quals, coord=None): self.type = type self.dim = dim + self.dim_quals = dim_quals self.coord = coord def children(self): @@ -138,7 +139,7 @@ class ArrayDecl(Node): if self.dim is not None: nodelist.append(("dim", self.dim)) return tuple(nodelist) - attr_names = () + attr_names = ('dim_quals',) class ArrayRef(Node): def __init__(self, name, subscript, coord=None): diff --git a/pycparser/c_parser.py b/pycparser/c_parser.py index bd8e3e6..8ec3416 100644 --- a/pycparser/c_parser.py +++ b/pycparser/c_parser.py @@ -987,10 +987,20 @@ class CParser(PLYParser): | direct_declarator LBRACKET STATIC assignment_expression_opt RBRACKET | direct_declarator LBRACKET CONST assignment_expression_opt RBRACKET """ - arr = c_ast.ArrayDecl( - type=None, - dim=p[3] if len(p) == 5 else p[4], - coord=p[1].coord) + if len(p) > 5: + # Have dimension qualifiers + # Per C99 6.7.5.3 p7 + arr = c_ast.ArrayDecl( + type=None, + dim=p[4], + dim_quals=[p[3]], + coord=p[1].coord) + else: + arr = c_ast.ArrayDecl( + type=None, + dim=p[3], + dim_quals=[], + coord=p[1].coord) p[0] = self._type_modify_decl(decl=p[1], modifier=arr) @@ -1002,6 +1012,7 @@ class CParser(PLYParser): arr = c_ast.ArrayDecl( type=None, dim=c_ast.ID(p[3], self._coord(p.lineno(3))), + dim_quals=[], coord=p[1].coord) p[0] = self._type_modify_decl(decl=p[1], modifier=arr) @@ -1213,6 +1224,7 @@ class CParser(PLYParser): arr = c_ast.ArrayDecl( type=None, dim=p[3], + dim_quals=[], coord=p[1].coord) p[0] = self._type_modify_decl(decl=p[1], modifier=arr) @@ -1223,6 +1235,7 @@ class CParser(PLYParser): p[0] = c_ast.ArrayDecl( type=c_ast.TypeDecl(None, None, None), dim=p[2], + dim_quals=[], coord=self._coord(p.lineno(1))) def p_direct_abstract_declarator_4(self, p): @@ -1231,6 +1244,7 @@ class CParser(PLYParser): arr = c_ast.ArrayDecl( type=None, dim=c_ast.ID(p[3], self._coord(p.lineno(3))), + dim_quals=[], coord=p[1].coord) p[0] = self._type_modify_decl(decl=p[1], modifier=arr) @@ -1241,6 +1255,7 @@ class CParser(PLYParser): p[0] = c_ast.ArrayDecl( type=c_ast.TypeDecl(None, None, None), dim=c_ast.ID(p[3], self._coord(p.lineno(3))), + dim_quals=[], coord=self._coord(p.lineno(1))) def p_direct_abstract_declarator_6(self, p): diff --git a/tests/test_c_parser.py b/tests/test_c_parser.py index 67048a1..f6bf0bd 100644 --- a/tests/test_c_parser.py +++ b/tests/test_c_parser.py @@ -47,7 +47,7 @@ def expand_decl(decl): return ['Typename', nested] elif typ == ArrayDecl: dimval = decl.dim.value if decl.dim else '' - return ['ArrayDecl', dimval, nested] + return ['ArrayDecl', dimval, decl.dim_quals, nested] elif typ == PtrDecl: return ['PtrDecl', nested] elif typ == Typedef: @@ -229,17 +229,17 @@ class TestCParser_fundamentals(TestCParser_base): self.assertEqual(self.get_decl('long ar[15];'), ['Decl', 'ar', - ['ArrayDecl', '15', + ['ArrayDecl', '15', [], ['TypeDecl', ['IdentifierType', ['long']]]]]) self.assertEqual(self.get_decl('long long ar[15];'), ['Decl', 'ar', - ['ArrayDecl', '15', + ['ArrayDecl', '15', [], ['TypeDecl', ['IdentifierType', ['long', 'long']]]]]) self.assertEqual(self.get_decl('unsigned ar[];'), ['Decl', 'ar', - ['ArrayDecl', '', + ['ArrayDecl', '', [], ['TypeDecl', ['IdentifierType', ['unsigned']]]]]) self.assertEqual(self.get_decl('int strlen(char* s);'), @@ -278,30 +278,30 @@ class TestCParser_fundamentals(TestCParser_base): self.assertEqual(self.get_decl('int (*a)[1][2];'), ['Decl', 'a', ['PtrDecl', - ['ArrayDecl', '1', - ['ArrayDecl', '2', + ['ArrayDecl', '1', [], + ['ArrayDecl', '2', [], ['TypeDecl', ['IdentifierType', ['int']]]]]]]) self.assertEqual(self.get_decl('int *a[1][2];'), ['Decl', 'a', - ['ArrayDecl', '1', - ['ArrayDecl', '2', + ['ArrayDecl', '1', [], + ['ArrayDecl', '2', [], ['PtrDecl', ['TypeDecl', ['IdentifierType', ['int']]]]]]]) self.assertEqual(self.get_decl('char ***ar3D[40];'), ['Decl', 'ar3D', - ['ArrayDecl', '40', + ['ArrayDecl', '40', [], ['PtrDecl', ['PtrDecl', ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]]]]) self.assertEqual(self.get_decl('char (***ar3D)[40];'), ['Decl', 'ar3D', ['PtrDecl', ['PtrDecl', ['PtrDecl', - ['ArrayDecl', '40', ['TypeDecl', ['IdentifierType', ['char']]]]]]]]) + ['ArrayDecl', '40', [], ['TypeDecl', ['IdentifierType', ['char']]]]]]]]) self.assertEqual(self.get_decl('int (*x[4])(char, int);'), ['Decl', 'x', - ['ArrayDecl', '4', + ['ArrayDecl', '4', [], ['PtrDecl', ['FuncDecl', [ ['Typename', ['TypeDecl', ['IdentifierType', ['char']]]], @@ -310,13 +310,13 @@ class TestCParser_fundamentals(TestCParser_base): self.assertEqual(self.get_decl('char *(*(**foo [][8])())[];'), ['Decl', 'foo', - ['ArrayDecl', '', - ['ArrayDecl', '8', + ['ArrayDecl', '', [], + ['ArrayDecl', '8', [], ['PtrDecl', ['PtrDecl', ['FuncDecl', [], ['PtrDecl', - ['ArrayDecl', '', + ['ArrayDecl', '', [], ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]]]]]]]]) @@ -372,14 +372,14 @@ class TestCParser_fundamentals(TestCParser_base): self.assertEqual(self.get_decl('int zz(int p[static 10]);'), ['Decl', 'zz', ['FuncDecl', - [['Decl', 'p', ['ArrayDecl', '10', + [['Decl', 'p', ['ArrayDecl', '10', ['static'], ['TypeDecl', ['IdentifierType', ['int']]]]]], ['TypeDecl', ['IdentifierType', ['int']]]]]) self.assertEqual(self.get_decl('int zz(int p[const 10]);'), ['Decl', 'zz', ['FuncDecl', - [['Decl', 'p', ['ArrayDecl', '10', + [['Decl', 'p', ['ArrayDecl', '10', ['const'], ['TypeDecl', ['IdentifierType', ['int']]]]]], ['TypeDecl', ['IdentifierType', ['int']]]]]) @@ -853,7 +853,7 @@ class TestCParser_fundamentals(TestCParser_base): ['TypeDecl', ['IdentifierType', ['Name']]]], ['Decl', 'NameArray', - ['ArrayDecl', '3', + ['ArrayDecl', '3', [], ['TypeDecl', ['IdentifierType', ['Name']]]]]]]]]) self.assertEqual(s1_ast.ext[3].body.block_items[0].lvalue.field.name, 'Name') @@ -959,7 +959,7 @@ class TestCParser_fundamentals(TestCParser_base): ['Decl', 'notp', ['TypeDecl', ['IdentifierType', ['char']]]]) self.assertEqual(self.get_decl(d2, 2), ['Decl', 'ar', - ['ArrayDecl', '4', + ['ArrayDecl', '4', [], ['TypeDecl', ['IdentifierType', ['char']]]]]) def test_invalid_multiple_types_error(self): @@ -1007,11 +1007,11 @@ class TestCParser_fundamentals(TestCParser_base): ''' self.assertEqual(self.get_decl(d3, 0), ['Typedef', 'numberarray', - ['ArrayDecl', '5', + ['ArrayDecl', '5', [], ['TypeDecl', ['IdentifierType', ['int']]]]]) self.assertEqual(self.get_decl(d3, 1), ['Typedef', 'numberarray', - ['ArrayDecl', '5', + ['ArrayDecl', '5', [], ['TypeDecl', ['IdentifierType', ['int']]]]]) def test_decl_inits(self): @@ -1030,7 +1030,7 @@ class TestCParser_fundamentals(TestCParser_base): #~ self.parse(d2).show() self.assertEqual(self.get_decl(d2), ['Decl', 'ar', - ['ArrayDecl', '', + ['ArrayDecl', '', [], ['TypeDecl', ['IdentifierType', ['long']]]]]) self.assertEqual(self.get_decl_init(d2), [ ['Constant', 'int', '7'], |