Implemented mixing of declarations and statements in compound statements for C99.
-> In the Compound AST node, decls and stmts were removed and replaced by a single list named block_items (this is an API change!)
diff --git a/TODO.txt b/TODO.txt
index d1dbfb7..5395b5a 100644
--- a/TODO.txt
+++ b/TODO.txt
@@ -7,7 +7,7 @@
 

 V- new keywords restrict, inline

 - mix declarations and statements inside a block

-- VLAs (non-constants in arr[n]), including [*] for parameter lists

+V- VLAs (non-constants in arr[n]), including [*] for parameter lists

 V- declarations in the first expression of "for" loops

 - named initializers for structs and arrays

 

diff --git a/examples/cdecl.py b/examples/cdecl.py
index 1db5149..3df6efc 100644
--- a/examples/cdecl.py
+++ b/examples/cdecl.py
@@ -17,7 +17,7 @@
 # =>

 # ar is a pointer to array[10] of pointer to const Node

 #

-# Copyright (C) 2008, Eli Bendersky

+# Copyright (C) 2008-2010, Eli Bendersky

 # License: LGPL

 #-----------------------------------------------------------------

 import sys

diff --git a/examples/explore_ast.py b/examples/explore_ast.py
index 7daf15b..f845c0f 100644
--- a/examples/explore_ast.py
+++ b/examples/explore_ast.py
@@ -9,7 +9,7 @@
 # information from the AST.

 # It helps to have the _c_ast.yaml file in front of you.

 #

-# Copyright (C) 2008, Eli Bendersky

+# Copyright (C) 2008-2010, Eli Bendersky

 # License: LGPL

 #-----------------------------------------------------------------

 import sys

@@ -92,23 +92,19 @@
 #

 function_body = ast.ext[2].body

 

-# The following displays the variable declarations in the function

+# The following displays the declarations and statements in the function

 # body

 #

-#~ for decl in function_body.decls:

+#~ for decl in function_body.block_items:

     #~ decl.show()

 

-# We can see a single variable, i, declared to be a simple type

-# declaration of type 'unsigned int'.

+# We can see a single variable declaration, i, declared to be a simple type

+# declaration of type 'unsigned int', followed by statements.

 #

-# Let's look at the statemts now:

-#

-#~ for stmt in function_body.stmts:

-    #~ stmt.show()

 

-# stmts is a list, so the second element is the For statement:

+# block_items is a list, so the third element is the For statement:

 #

-for_stmt = function_body.stmts[1]

+for_stmt = function_body.block_items[2]

 #~ for_stmt.show()

 

 # As you can see in _c_ast.yaml, For's children are 'init, cond,

@@ -118,7 +114,7 @@
 #

 # Let's dig deeper, to the while statement inside the for loop:

 #

-while_stmt = for_stmt.stmt.stmts[0]

+while_stmt = for_stmt.stmt.block_items[1]

 #~ while_stmt.show()

 

 # While is simpler, it only has a condition node and a stmt node.

diff --git a/pycparser/_c_ast.yaml b/pycparser/_c_ast.yaml
index 97fbca6..3e386ae 100644
--- a/pycparser/_c_ast.yaml
+++ b/pycparser/_c_ast.yaml
@@ -30,9 +30,10 @@
 

 Cast: [to_type*, expr*]

 

-# Compound statement: { declarations... statements...}

+# Compound statement in C99 is a list of block items (declarations or 

+# statements).

 #

-Compound: [decls**, stmts**]

+Compound: [block_items**]

 

 # type: int, char, float, etc. see CLexer for constant token types

 #

diff --git a/pycparser/c_ast.py b/pycparser/c_ast.py
index 1dfe354..a3f6405 100644
--- a/pycparser/c_ast.py
+++ b/pycparser/c_ast.py
@@ -637,15 +637,13 @@
 

 

 class Compound(Node):

-    def __init__(self, decls, stmts, coord=None):

-        self.decls = decls

-        self.stmts = stmts

+    def __init__(self, block_items, coord=None):

+        self.block_items = block_items

         self.coord = coord

 

     def children(self):

         nodelist = []

-        if self.decls is not None: nodelist.extend(self.decls)

-        if self.stmts is not None: nodelist.extend(self.stmts)

+        if self.block_items is not None: nodelist.extend(self.block_items)

         return tuple(nodelist)

 

     def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):

diff --git a/pycparser/c_parser.py b/pycparser/c_parser.py
index 2d0a8b6..d36f197 100644
--- a/pycparser/c_parser.py
+++ b/pycparser/c_parser.py
@@ -84,7 +84,7 @@
             'init_declarator_list',

             'parameter_type_list',

             'specifier_qualifier_list',

-            'statement_list',

+            'block_item_list',

             'type_qualifier_list',

         ]

         

@@ -981,43 +981,29 @@
             args=p[2],

             type=c_ast.TypeDecl(None, None, None),

             coord=self._coord(p.lineno(1)))

-        

-    def p_compound_statement_1(self, p):

-        """ compound_statement : LBRACE statement_list_opt RBRACE """

-        p[0] = c_ast.Compound(

-            decls=None, 

-            stmts=p[2], 

-            coord=self._coord(p.lineno(1)))

     

-    def p_compound_statement_2(self, p):

-        """ compound_statement : LBRACE declaration_list RBRACE """

-        p[0] = c_ast.Compound(

-            decls=p[2], 

-            stmts=None, 

-            coord=self._coord(p.lineno(1)))

-    

-    def p_compound_statement_3(self, p):

-        """ compound_statement : LBRACE declaration_list statement_list RBRACE """

-        #~ print '(((((('

-        #~ print p[2]

-        #~ print p[3]

-        #~ print '(((((('

-        p[0] = c_ast.Compound(

-            decls=p[2], 

-            stmts=p[3], 

-            coord=self._coord(p.lineno(1)))

-    

-    # Note: this doesn't create an AST node, but a list of AST 

-    # nodes that will be used as the statement list of a compound

+    # declaration is a list, statement isn't. To make it consistent, block_item

+    # will always be a list

     #

-    def p_statement_list(self, p):

-        """ statement_list  : statement 

-                            | statement_list statement

+    def p_block_item(self, p):
+        """ block_item  : declaration

+                        | statement
         """

-        if len(p) == 2: # single expr

-            p[0] = [p[1]] if p[1] else [] 

-        else:

-            p[0] = p[1] + ([p[2]] if p[2] else [])

+        p[0] = p[1] if isinstance(p[1], list) else [p[1]]

+    

+    # Since we made block_item a list, this just combines lists

+    # 

+    def p_block_item_list(self, p):

+        """ block_item_list : block_item 

+                            | block_item_list block_item

+        """

+        p[0] = p[1] if len(p) == 2 else p[1] + p[2]

+    

+    def p_compound_statement_1(self, p):

+        """ compound_statement : LBRACE block_item_list_opt RBRACE """

+        p[0] = c_ast.Compound(

+            block_items=p[2], 

+            coord=self._coord(p.lineno(1)))

     

     def p_labeled_statement_1(self, p):

         """ labeled_statement : ID COLON statement """

diff --git a/tests/test_c_ast.py b/tests/test_c_ast.py
index d5794e1..2f1007f 100644
--- a/tests/test_c_ast.py
+++ b/tests/test_c_ast.py
@@ -71,8 +71,7 @@
             right=c2)

 

         comp = c_ast.Compound(

-            decls=[b1, b2],

-            stmts=[c1, c2])

+            block_items=[b1, b2, c1, c2])

         

         cv = self.ConstantVisitor()

         cv.visit(comp)

diff --git a/tests/test_c_parser.py b/tests/test_c_parser.py
index ef6f85c..532fe26 100644
--- a/tests/test_c_parser.py
+++ b/tests/test_c_parser.py
@@ -136,8 +136,8 @@
             return 0;
         }'''
         f1_1 = self.parse(t1_1, filename='test.c')
-        self.assert_coord(f1_1.ext[0].body.stmts[0], 3, 'test.c')
-        self.assert_coord(f1_1.ext[0].body.stmts[1], 4, 'test.c')
+        self.assert_coord(f1_1.ext[0].body.block_items[0], 3, 'test.c')
+        self.assert_coord(f1_1.ext[0].body.block_items[1], 4, 'test.c')
         
         t2 = """
         #line 99
@@ -350,17 +350,17 @@
         """
         compound = self.parse(e).ext[0].body
         
-        s1 = compound.decls[0].init
+        s1 = compound.block_items[0].init
         self.assertTrue(isinstance(s1, UnaryOp))
         self.assertEqual(s1.op, 'sizeof')
         self.assertTrue(isinstance(s1.expr, ID))
         self.assertEqual(s1.expr.name, 'k')
         
-        s2 = compound.decls[1].init
+        s2 = compound.block_items[1].init
         self.assertEqual(expand_decl(s2.expr),
             ['Typename', ['TypeDecl', ['IdentifierType', ['int']]]])
         
-        s3 = compound.decls[2].init
+        s3 = compound.block_items[2].init
         self.assertEqual(expand_decl(s3.expr),
             ['Typename', 
                 ['PtrDecl', 
@@ -791,8 +791,7 @@
                     [['Decl', 'p', ['TypeDecl', ['IdentifierType', ['int']]]]], 
                     ['TypeDecl', ['IdentifierType', ['int']]]]])
         
-        self.assertEqual(type(f1.body.stmts[0]), Return)
-        self.assertEqual(f1.body.decls, None)
+        self.assertEqual(type(f1.body.block_items[0]), Return)
         
         f2 = parse_fdef('''
         char* zzz(int p, char* c)
@@ -813,9 +812,8 @@
                                         ['TypeDecl', ['IdentifierType', ['char']]]]]], 
                     ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]])
             
-        self.assertEqual(list(map(type, f2.body.stmts)), 
-            [Assignment, Return])
-        self.assertEqual(len(f2.body.decls), 2)
+        self.assertEqual(list(map(type, f2.body.block_items)), 
+            [Decl, Decl, Assignment, Return])
         
         f3 = parse_fdef('''
         char* zzz(p, c)
@@ -836,9 +834,8 @@
                         ['ID', 'c']],
                     ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]])
         
-        self.assertEqual(list(map(type, f3.body.stmts)), 
-            [Assignment, Return])
-        self.assertEqual(len(f3.body.decls), 2)
+        self.assertEqual(list(map(type, f3.body.block_items)), 
+            [Decl, Decl, Assignment, Return])
         
         self.assertEqual(expand_decl(f3.param_decls[0]),
             ['Decl', 'p', ['TypeDecl', ['IdentifierType', ['long']]]])
@@ -866,7 +863,7 @@
         ''')
         
         self.assertEqual(
-            d3.ext[0].body.stmts[0].args.exprs[1].value,
+            d3.ext[0].body.block_items[0].args.exprs[1].value,
             r'"Wrong Params?\nUsage:\n%s <binary_file_path>\n"')
         
         d4 = self.get_decl_init('char* s = "" "foobar";')
@@ -889,8 +886,8 @@
                 int var2[*];
             }
         ''')
-        self.failUnless(isinstance(ps2.ext[0].body.decls[1].type.dim, Assignment))
-        self.failUnless(isinstance(ps2.ext[0].body.decls[2].type.dim, ID))
+        self.failUnless(isinstance(ps2.ext[0].body.block_items[1].type.dim, Assignment))
+        self.failUnless(isinstance(ps2.ext[0].body.block_items[2].type.dim, ID))
 
 
 class TestCParser_whole_code(unittest.TestCase):