summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES4
-rw-r--r--pycparser/_c_ast.cfg6
-rw-r--r--pycparser/c_ast.py5
-rw-r--r--pycparser/c_parser.py23
-rw-r--r--tests/test_c_parser.py42
5 files changed, 51 insertions, 29 deletions
diff --git a/CHANGES b/CHANGES
index 6faa93a..24e6689 100644
--- a/CHANGES
+++ b/CHANGES
@@ -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'],