Skip to content

Commit

Permalink
Fuller support for qualifiers in array dimensions.
Browse files Browse the repository at this point in the history
Added a field to the ArrayDecl node and modified tests
  • Loading branch information
eliben committed Jan 25, 2014
1 parent e7c55cf commit 8aad318
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 29 deletions.
4 changes: 3 additions & 1 deletion CHANGES
Original file line number Diff line number Diff line change
@@ -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)

Expand Down
6 changes: 5 additions & 1 deletion pycparser/_c_ast.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -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*]

Expand Down
5 changes: 3 additions & 2 deletions pycparser/c_ast.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,9 +127,10 @@ def generic_visit(self, node):


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):
Expand All @@ -138,7 +139,7 @@ def children(self):
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):
Expand Down
23 changes: 19 additions & 4 deletions pycparser/c_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -987,10 +987,20 @@ def p_direct_declarator_3(self, p):
| 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)

Expand All @@ -1002,6 +1012,7 @@ def p_direct_declarator_4(self, p):
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)
Expand Down Expand Up @@ -1213,6 +1224,7 @@ def p_direct_abstract_declarator_2(self, p):
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)
Expand All @@ -1223,6 +1235,7 @@ def p_direct_abstract_declarator_3(self, p):
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):
Expand All @@ -1231,6 +1244,7 @@ def p_direct_abstract_declarator_4(self, p):
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)
Expand All @@ -1241,6 +1255,7 @@ def p_direct_abstract_declarator_5(self, p):
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):
Expand Down
42 changes: 21 additions & 21 deletions tests/test_c_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -229,17 +229,17 @@ def test_simple_decls(self):

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);'),
Expand Down Expand Up @@ -278,30 +278,30 @@ def test_nested_decls(self): # the fun begins
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']]]],
Expand All @@ -310,13 +310,13 @@ def test_nested_decls(self): # the fun begins

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']]]]]]]]]]]])
Expand Down Expand Up @@ -372,14 +372,14 @@ def test_func_decls_with_array_dim_qualifiers(self):
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']]]]])

Expand Down Expand Up @@ -853,7 +853,7 @@ def test_struct_members_namespace(self):
['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')

Expand Down Expand Up @@ -959,7 +959,7 @@ def test_multi_decls(self):
['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):
Expand Down Expand Up @@ -1007,11 +1007,11 @@ def test_duplicate_typedef(self):
'''
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):
Expand All @@ -1030,7 +1030,7 @@ def test_decl_inits(self):
#~ 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'],
Expand Down

0 comments on commit 8aad318

Please sign in to comment.