Commits

Anonymous committed 7931c3d

Backed out changeset: 8ee804744907

Comments (0)

Files changed (5)

pycparser/_ast_gen.py

+#-----------------------------------------------------------------
+# _ast_gen.py
+#
+# Generates the AST Node classes from a specification given in 
+# a .yaml file
+#
+# The design of this module was inspired by astgen.py from the
+# Python 2.5 code-base.
+#
+# Copyright (C) 2008-2009, Eli Bendersky
+# License: LGPL
+#-----------------------------------------------------------------
+
+import pprint
+from string import Template
+
+import yaml
+
+
+class ASTCodeGenerator(object):
+    def __init__(self, cfg_filename='_c_ast.yaml'):
+        """ Initialize the code generator from a configuration
+            file.
+        """
+        self.cfg_filename = cfg_filename
+        cfg = yaml.load(open(cfg_filename).read())
+        self.node_cfg = [NodeCfg(name, cfg[name]) for name in cfg]
+
+        #~ pprint.pprint(self.node_cfg)
+        #~ print ''
+
+    def generate(self, file=None):
+        """ Generates the code into file, an open file buffer.
+        """
+        src = Template(_PROLOGUE_COMMENT).substitute(
+            cfg_filename=self.cfg_filename)
+        
+        src += _PROLOGUE_CODE
+        for node_cfg in self.node_cfg:
+            src += node_cfg.generate_source() + '\n\n'
+        
+        file.write(src)
+
+
+class NodeCfg(object):
+    def __init__(self, name, contents):
+        self.name = name
+        self.all_entries = []
+        self.attr = []
+        self.child = []
+        self.seq_child = []
+        
+        for entry in contents:
+            clean_entry = entry.rstrip('*')
+            self.all_entries.append(clean_entry)
+            
+            if entry.endswith('**'):
+                self.seq_child.append(clean_entry)
+            elif entry.endswith('*'):
+                self.child.append(clean_entry)
+            else:
+                self.attr.append(entry)
+
+    def generate_source(self):
+        src = self._gen_init()
+        src += '\n' + self._gen_children()
+        src += '\n' + self._gen_show()
+        return src
+    
+    def _gen_init(self):
+        src = "class %s(Node):\n" % self.name
+
+        if self.all_entries:
+            args = ', '.join(self.all_entries)
+            arglist = '(self, %s, coord=None)' % args
+        else:
+            arglist = '(self, coord=None)'
+        
+        src += "    def __init__%s:\n" % arglist
+        
+        for name in self.all_entries + ['coord']:
+            src += "        self.%s = %s\n" % (name, name)
+        
+        return src
+    
+    def _gen_children(self):
+        src = '    def children(self):\n'
+        
+        if self.all_entries:
+            src += '        nodelist = []\n'
+            
+            template = ('' +
+                '        if self.%s is not None:' +
+                ' nodelist.%s(self.%s)\n')
+            
+            for child in self.child:
+                src += template % (
+                    child, 'append', child)
+            
+            for seq_child in self.seq_child:
+                src += template % (
+                    seq_child, 'extend', seq_child)
+                    
+            src += '        return tuple(nodelist)\n'
+        else:
+            src += '        return ()\n'
+            
+        return src
+
+    def _gen_show(self):
+        src = '    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):\n'
+        src += "        lead = ' ' * offset\n"
+        
+        src += "        buf.write(lead + '%s: ')\n\n" % self.name
+        
+        if self.attr:
+            src += "        if attrnames:\n"
+            src += "            attrstr = ', '.join('%s=%s' % nv for nv in ["
+            src += ', '.join('("%s", repr(%s))' % (nv, 'self.%s' % nv) for nv in self.attr)
+            src += '])\n'
+            src += "        else:\n"
+            src += "            attrstr = ', '.join('%s' % v for v in ["
+            src += ', '.join('self.%s' % v for v in self.attr)
+            src += '])\n'
+            src += "        buf.write(attrstr)\n\n"
+        
+        src += "        if showcoord:\n"
+        src += "            buf.write(' (at %s)' % self.coord)\n"
+        src += "        buf.write('\\n')\n\n"
+        
+        src += "        for c in self.children():\n"
+        src += "            c.show(buf, offset + 2, attrnames, showcoord)\n"
+        
+        return src
+
+
+_PROLOGUE_COMMENT = \
+r'''#-----------------------------------------------------------------
+# ** ATTENTION **
+# This code was automatically generated from the file:
+# $cfg_filename 
+#
+# Do not modify it directly. Modify the configuration file and
+# run the generator again.
+# ** ** *** ** **
+#
+# pycparser: c_ast.py
+#
+# AST Node classes.
+#
+# Copyright (C) 2008, Eli Bendersky
+# License: LGPL
+#-----------------------------------------------------------------
+
+'''
+
+_PROLOGUE_CODE = r'''
+import sys
+
+
+class Node(object):
+    """ Abstract base class for AST nodes.
+    """
+    def children(self):
+        """ A sequence of all children that are Nodes
+        """
+        pass
+
+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+        """ Pretty print the Node and all its attributes and
+            children (recursively) to a buffer.
+            
+            file:   
+                Open IO buffer into which the Node is printed.
+            
+            offset: 
+                Initial offset (amount of leading spaces) 
+            
+            attrnames:
+                True if you want to see the attribute names in
+                name=value pairs. False to only see the values.
+            
+            showcoord:
+                Do you want the coordinates of each Node to be
+                displayed.
+        """
+        pass
+
+
+class NodeVisitor(object):
+    """ A base NodeVisitor class for visiting c_ast nodes. 
+        Subclass it and define your own visit_XXX methods, where
+        XXX is the class name you want to visit with these 
+        methods.
+        
+        For example:
+        
+        class ConstantVisitor(NodeVisitor):
+            def __init__(self):
+                self.values = []
+            
+            def visit_Constant(self, node):
+                self.values.append(node.value)
+
+        Creates a list of values of all the constant nodes 
+        encountered below the given node. To use it:
+        
+        cv = ConstantVisitor()
+        cv.visit(node)
+        
+        Notes:
+        
+        *   generic_visit() will be called for AST nodes for which 
+            no visit_XXX method was defined. 
+        *   The children of nodes for which a visit_XXX was 
+            defined will not be visited - if you need this, call
+            generic_visit() on the node. 
+            You can use:
+                NodeVisitor.generic_visit(self, node)
+        *   Modeled after Python's own AST visiting facilities
+            (the ast module of Python 3.0)
+    """
+    def visit(self, node):
+        """ Visit a node. 
+        """
+        method = 'visit_' + node.__class__.__name__
+        visitor = getattr(self, method, self.generic_visit)
+        return visitor(node)
+        
+    def generic_visit(self, node):
+        """ Called if no explicit visitor function exists for a 
+            node. Implements preorder visiting of the node.
+        """
+        for c in node.children():
+            self.visit(c)
+
+
+'''
+
+
+
+if __name__ == "__main__":
+    import sys
+    
+    ast_gen = ASTCodeGenerator('_c_ast.yaml')
+    ast_gen.generate(open('c_ast.py', 'w'))
+    
+    
+    

pycparser/_c_ast.yaml

+#-----------------------------------------------------------------
+# pycparser: _c_ast_gen.yaml
+#
+# Defines the AST Node classes used in pycparser.
+# 
+# Each entry is a Node sub-class name, listing the attributes
+# and child nodes of the class:
+#   <name>*     - a child node
+#   <name>**    - a sequence of child nodes
+#   <name>      - an attribute
+#
+# Copyright (C) 2008-2009, Eli Bendersky
+# License: LGPL
+#-----------------------------------------------------------------
+
+
+ArrayDecl: [type*, dim*]
+
+ArrayRef: [name*, subscript*]
+
+# op: =, +=, /= etc.
+#
+Assignment: [op, lvalue*, rvalue*]
+
+BinaryOp: [op, left*, right*]
+
+Break: []
+
+Case: [expr*, stmt*]
+
+Cast: [to_type*, expr*]
+
+# Compound statement: { declarations... statements...}
+#
+Compound: [decls**, stmts**]
+
+# type: int, char, float, etc. see CLexer for constant token types
+#
+Constant: [type, value]
+
+Continue: []
+
+# name: the variable being declared
+# quals: list of qualifiers (const, volatile)
+# storage: list of storage specifiers (extern, register, etc.)
+# type: declaration type (probably nested with all the modifiers)
+# init: initialization value, or None
+# bitsize: bit field size, or None
+#
+Decl: [name, quals, storage, type*, init*, bitsize*]
+
+Default: [stmt*]
+
+DoWhile: [cond*, stmt*]
+
+# Represents the ellipsis (...) parameter in a function 
+# declaration
+#
+EllipsisParam: []
+
+# Enumeration type specifier
+# name: an optional ID
+# values: an EnumeratorList
+#
+Enum: [name, values*]
+
+# A name/value pair for enumeration values
+#
+Enumerator: [name, value*]
+
+# A list of enumerators
+#
+EnumeratorList: [enumerators**]
+
+# a list of comma separated expressions
+#
+ExprList: [exprs**]
+
+# This is the top of the AST, representing a single C file (a 
+# translation unit in K&R jargon). It contains a list of 
+# "external-declaration"s, which is either declarations (Decl),
+# Typedef or function definitions (FuncDef).
+# 
+FileAST: [ext**]
+
+# for (init; cond; next) stmt
+#
+For: [init*, cond*, next*, stmt*]
+
+# name: Id
+# args: ExprList
+#
+FuncCall: [name*, args*]
+
+# type <decl>(args)
+#
+FuncDecl: [args*, type*]
+
+# Function definition: a declarator for the function name and
+# a body, which is a compound statement. 
+# There's an optional list of parameter declarations for old
+# K&R-style definitions
+#
+FuncDef: [decl*, param_decls**, body*]
+
+Goto: [name]
+
+ID: [name]
+
+# Holder for types that are a simple identifier (e.g. the built
+# ins void, char etc. and typedef-defined types)
+#
+IdentifierType: [names]
+
+If: [cond*, iftrue*, iffalse*]
+
+Label: [name, stmt*]
+
+# a list of comma separated function parameter declarations
+#
+ParamList: [params**]
+
+PtrDecl: [quals, type*]
+
+Return: [expr*]
+
+# name: struct tag name
+# decls: declaration of members
+#
+Struct: [name, decls**]
+
+# type: . or ->
+# name.field or name->field
+#
+StructRef: [name*, type, field*]
+
+Switch: [cond*, stmt*]
+
+# cond ? iftrue : iffalse
+#
+TernaryOp: [cond*, iftrue*, iffalse*]
+
+# A base type declaration
+#
+TypeDecl: [declname, quals, type*]
+
+# A typedef declaration.
+# Very similar to Decl, but without some attributes
+#
+Typedef: [name, quals, storage, type*]
+
+Typename: [quals, type*]
+
+UnaryOp: [op, expr*]
+
+# name: union tag name
+# decls: declaration of members
+#
+Union: [name, decls**]
+
+While: [cond*, stmt*]
+
+
+

pycparser/ast.py

-import sys
-import re
-
-def SubNodeClass(name, attributes=[], children=[]):
-    def init(self, *args, **kargs):
-        coord = None
-        if 'coord' in kargs.keys() :
-            coord = kargs['coord']
-        elif len(args) == (len(attributes) + 
-                           len(children) + 
-                           1):
-            coord = args[-1]
-        _attributes = {}
-        for attribute in attributes :
-            try :
-                _attributes[attribute] = kargs[attribute]
-            except KeyError:
-                _attributes[attribute] = args[attributes.index(attribute)]
-        _children = {}
-        for child in children :
-            try :
-                _children[child] = kargs[child]
-            except KeyError:
-                _children[child] = args[len(attributes)+children.index(child)]
-        Node.__init__(self,
-                      coord,
-                      attributes=_attributes,
-                      children=_children)
-    
-    init.func_doc = ('The arguements of the function can be path through the keywords ' +
-                     'name or the order of appearance of them :\n' + ' ' * 4 +
-                     ('\n' + ' ' * 4).join(attributes+children+['coord']))
-    
-    return type(name,
-                (Node,),
-                {'__init__':init})
-
-class Node(object):
-    """ Abstract base class for AST nodes.
-    """
-    __offset = 4
-    __show_coord = True
-    
-    def __init__(self, coord, attributes={}, children={}, with_value=True):
-        self.coord = coord
-        self.with_value = with_value
-
-        if (not isinstance(attributes, dict) or
-            not isinstance(children, dict)):
-            raise TypeError('attributes and children have to be '+repr(type(dict)))
-        self.attributes = attributes
-        self.children = children
-
-    def __getattr__(self, name):
-        if name in self.attributes.keys():
-            return self.attributes[name]
-        elif name in self.children.keys():
-            return self.children[name]
-        else:
-            return object.__getattribute__(self, name)
-
-    def __setattr__(self, name, value):
-        if not (name in ['attributes',
-                         'children',
-                         'coord',
-                         'with_value']) :
-            try  :
-                self.attributes[name] = value
-            except KeyError, e:
-                try :
-                    self.children[name] = value
-                except KeyError, e:
-                    pass
-        object.__setattr__(self, name, value)
-
-    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
-        buf.write(repr(self))
-    
-    def __repr_header(self):
-        s = type(self).__name__ 
-        if type(self).__show_coord:
-            s += ' (' + self.__repr_coord() + ')'
-        return s
-    
-    def __repr_attributes(self):
-        s = ''
-        entries = []
-        reporter = lambda k,v : '%s' % (k)
-        line_prefix = '\n' + len(self.__repr_header() + ' : (') * ' '
-        if self.with_value :
-            reporter = lambda k,v : '%s = %s' % (k,repr(v))
-        for k, v in self.attributes.items():
-            entries += [reporter(k,v)]
-        return line_prefix.join(entries)
-    
-    def __repr_coord(self):
-        return 'at %s' % self.coord
-    
-    def __repr_children(self):
-        children_keys = self.children.keys()
-        children_keys.sort()
-        reprs = []
-        for name in children_keys:
-            s = ''
-            value = self.children[name]
-            child_head = type(self).__offset * ' ' + '* '+ name + ' : '
-            s += child_head
-            line_prefix = '\n' + ' ' * len(child_head)
-            repr_value = repr(value)
-            if isinstance(value, list) :
-                repr_value = '['+'\n'.join('- %s' % repr(v) for v in value)+']'
-            s += re.sub('\n', line_prefix, repr_value)
-            reprs += [s]
-        return '\n'.join(['']+reprs+[''])
-    
-    def __repr__(self):
-        s = self.__repr_header()
-        if len(self.attributes):
-            s += ' : (' + self.__repr_attributes() + ')' 
-        if len(self.children):
-            s += self.__repr_children()
-        return s
-
-class NodeVisitor(object):
-    """ A base NodeVisitor class for visiting c_ast nodes. 
-    Subclass it and define your own visit_XXX methods, where
-    XXX is the class name you want to visit with these 
-    methods.
-    
-    For example:
-    
-    class ConstantVisitor(NodeVisitor):
-    def __init__(self):
-    self.values = []
-    
-    def visit_Constant(self, node):
-    self.values.append(node.value)
-
-    Creates a list of values of all the constant nodes 
-    encountered below the given node. To use it:
-    
-    cv = ConstantVisitor()
-    cv.visit(node)
-    
-    Notes:
-    
-    *   generic_visit() will be called for AST nodes for which 
-    no visit_XXX method was defined. 
-    *   The children of nodes for which a visit_XXX was 
-    defined will not be visited - if you need this, call
-    generic_visit() on the node. 
-    You can use:
-    NodeVisitor.generic_visit(self, node)
-    *   Modeled after Python's own AST visiting facilities
-    (the ast module of Python 3.0)
-    """
-    def visit(self, node):
-        """ Visit a node. 
-        """
-        method = 'visit_' + node.__class__.__name__
-        visitor = getattr(self, method, self.generic_visit)
-        return visitor(node)
-    
-    def generic_visit(self, node):
-        """ Called if no explicit visitor function exists for a 
-        node. Implements preorder visiting of the node.
-        """
-        for k in node.children:
-            self.visit(node.children[k])
-
-

pycparser/c_ast.py

-import c_ast as current
-from ast import *
-
-classes = [SubNodeClass('ArrayDecl',
-                        children=['type','dim']),
-
-
-           SubNodeClass('ArrayRef',
-                        children=['name',
-                                  'subscript']),
-
-           SubNodeClass('Assignment',
-                        ['op'],
-                        ['lvalue',
-                         'rvalue']),
-
-           SubNodeClass('BinaryOp',
-                        ['op'],
-                        ['left', 'right']),
-
-           SubNodeClass('Break'),
-
-           SubNodeClass('Case',
-                        children=['expr','stmt']),
-
-           SubNodeClass('Cast',
-                        children=['to_type',
-                                  'expr']),
-
-           SubNodeClass('Compound',
-                        children=['decls',
-                                  'stmts']),
-
-           SubNodeClass('Constant',
-                        ['type',
-                         'value']),
-
-           SubNodeClass('Conitnue'),
-
-           SubNodeClass('Decl',
-                        ['name',
-                         'quals',
-                         'storage'],
-                        ['type',
-                         'init',
-                         'bitsize']),
-
-           SubNodeClass('Default',
-                        children = ['stmt']),
-
-
-           SubNodeClass('DoWhile',
-                        children = ['cond',
-                                    'stmt']),
-
-           SubNodeClass('EllipsisParam'),
-
-           SubNodeClass('Enum',
-                        ['name'],
-                        ['values']),
-
-           SubNodeClass('Enumerator',
-                        ['name'],
-                        ['value']),
-
-
-           SubNodeClass('EnumeratorList',
-                        children=['enumerators']),
-
-           SubNodeClass('ExprList',
-                        children=['exprs']),
-
-
-           SubNodeClass('AST',
-                        children=['ext']),
-
-           SubNodeClass('For',
-                        children=['init',
-                                  'cond',
-                                  'next',
-                                  'stmt']),
-
-           SubNodeClass('FuncCall',
-                        children=['name',
-                                  'args']),
-
-           SubNodeClass('FuncDecl',
-                        children=['args',
-                                  'type']),
-
-           SubNodeClass('FuncDef',
-                        children=['decl',
-                                  'body',
-                                  'param_decls']),
-
-           SubNodeClass('Goto', ['name']),
-
-           SubNodeClass('ID', ['name']),
-
-           SubNodeClass('IdentifierType', ['names']),
-
-           SubNodeClass('If',
-                        children = ['cond',
-                                    'iftrue',
-                                    'iffalse']),
-
-           SubNodeClass('Label',
-                        ['name'],
-                        ['stmt']),
-
-           SubNodeClass('ParamList',
-                        children=['params']),
-
-           SubNodeClass('PtrDecl', ['quals'], ['type']),
-
-           SubNodeClass('Return',
-                        children=['expr']),
-
-
-           SubNodeClass('Struct', ['name'], ['decls']),
-
-           SubNodeClass('StructRef',
-                        ['type'],
-                        ['name',
-                         'field']),
-
-           SubNodeClass('Switch',
-                        children=['cond',
-                                  'stmt']),
-
-
-           SubNodeClass('TernaryOp',
-                        children=['cond',
-                                  'iftrue',
-                                  'iffalse']),
-
-           SubNodeClass('TypeDecl',
-                        ['declname',
-                         'quals'],
-                        ['type']),
-
-           SubNodeClass('Typedef',
-                        ['name',
-                         'quals',
-                         'storage'],
-                        ['type']),
-
-           SubNodeClass('Typename',
-                        ['quals'],
-                        ['type']),
-
-           SubNodeClass('UnaryOp', ['op'], ['expr']),
-
-           SubNodeClass('Union', ['name'], ['decls']),
-
-           SubNodeClass('While',
-                        children = ['cond',
-                                    'stmt'])]
-
-for subclass in classes:
-    setattr(current, subclass.__name__, subclass)
+#-----------------------------------------------------------------
+# ** ATTENTION **
+# This code was automatically generated from the file:
+# _c_ast.yaml 
+#
+# Do not modify it directly. Modify the configuration file and
+# run the generator again.
+# ** ** *** ** **
+#
+# pycparser: c_ast.py
+#
+# AST Node classes.
+#
+# Copyright (C) 2008, Eli Bendersky
+# License: LGPL
+#-----------------------------------------------------------------
+
+
+import sys
+
+
+class Node(object):
+    """ Abstract base class for AST nodes.
+    """
+    def children(self):
+        """ A sequence of all children that are Nodes
+        """
+        pass
+
+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+        """ Pretty print the Node and all its attributes and
+            children (recursively) to a buffer.
+            
+            file:   
+                Open IO buffer into which the Node is printed.
+            
+            offset: 
+                Initial offset (amount of leading spaces) 
+            
+            attrnames:
+                True if you want to see the attribute names in
+                name=value pairs. False to only see the values.
+            
+            showcoord:
+                Do you want the coordinates of each Node to be
+                displayed.
+        """
+        pass
+
+
+class NodeVisitor(object):
+    """ A base NodeVisitor class for visiting c_ast nodes. 
+        Subclass it and define your own visit_XXX methods, where
+        XXX is the class name you want to visit with these 
+        methods.
+        
+        For example:
+        
+        class ConstantVisitor(NodeVisitor):
+            def __init__(self):
+                self.values = []
+            
+            def visit_Constant(self, node):
+                self.values.append(node.value)
+
+        Creates a list of values of all the constant nodes 
+        encountered below the given node. To use it:
+        
+        cv = ConstantVisitor()
+        cv.visit(node)
+        
+        Notes:
+        
+        *   generic_visit() will be called for AST nodes for which 
+            no visit_XXX method was defined. 
+        *   The children of nodes for which a visit_XXX was 
+            defined will not be visited - if you need this, call
+            generic_visit() on the node. 
+            You can use:
+                NodeVisitor.generic_visit(self, node)
+        *   Modeled after Python's own AST visiting facilities
+            (the ast module of Python 3.0)
+    """
+    def visit(self, node):
+        """ Visit a node. 
+        """
+        method = 'visit_' + node.__class__.__name__
+        visitor = getattr(self, method, self.generic_visit)
+        return visitor(node)
+        
+    def generic_visit(self, node):
+        """ Called if no explicit visitor function exists for a 
+            node. Implements preorder visiting of the node.
+        """
+        for c in node.children():
+            self.visit(c)
+
+
+class Typedef(Node):
+    def __init__(self, name, quals, storage, type, coord=None):
+        self.name = name
+        self.quals = quals
+        self.storage = storage
+        self.type = type
+        self.coord = coord
+
+    def children(self):
+        nodelist = []
+        if self.type is not None: nodelist.append(self.type)
+        return tuple(nodelist)
+
+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+        lead = ' ' * offset
+        buf.write(lead + 'Typedef: ')
+
+        if attrnames:
+            attrstr = ', '.join('%s=%s' % nv for nv in [("name", repr(self.name)), ("quals", repr(self.quals)), ("storage", repr(self.storage))])
+        else:
+            attrstr = ', '.join('%s' % v for v in [self.name, self.quals, self.storage])
+        buf.write(attrstr)
+
+        if showcoord:
+            buf.write(' (at %s)' % self.coord)
+        buf.write('\n')
+
+        for c in self.children():
+            c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class Struct(Node):
+    def __init__(self, name, decls, coord=None):
+        self.name = name
+        self.decls = decls
+        self.coord = coord
+
+    def children(self):
+        nodelist = []
+        if self.decls is not None: nodelist.extend(self.decls)
+        return tuple(nodelist)
+
+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+        lead = ' ' * offset
+        buf.write(lead + 'Struct: ')
+
+        if attrnames:
+            attrstr = ', '.join('%s=%s' % nv for nv in [("name", repr(self.name))])
+        else:
+            attrstr = ', '.join('%s' % v for v in [self.name])
+        buf.write(attrstr)
+
+        if showcoord:
+            buf.write(' (at %s)' % self.coord)
+        buf.write('\n')
+
+        for c in self.children():
+            c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class FuncCall(Node):
+    def __init__(self, name, args, coord=None):
+        self.name = name
+        self.args = args
+        self.coord = coord
+
+    def children(self):
+        nodelist = []
+        if self.name is not None: nodelist.append(self.name)
+        if self.args is not None: nodelist.append(self.args)
+        return tuple(nodelist)
+
+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+        lead = ' ' * offset
+        buf.write(lead + 'FuncCall: ')
+
+        if showcoord:
+            buf.write(' (at %s)' % self.coord)
+        buf.write('\n')
+
+        for c in self.children():
+            c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class UnaryOp(Node):
+    def __init__(self, op, expr, coord=None):
+        self.op = op
+        self.expr = expr
+        self.coord = coord
+
+    def children(self):
+        nodelist = []
+        if self.expr is not None: nodelist.append(self.expr)
+        return tuple(nodelist)
+
+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+        lead = ' ' * offset
+        buf.write(lead + 'UnaryOp: ')
+
+        if attrnames:
+            attrstr = ', '.join('%s=%s' % nv for nv in [("op", repr(self.op))])
+        else:
+            attrstr = ', '.join('%s' % v for v in [self.op])
+        buf.write(attrstr)
+
+        if showcoord:
+            buf.write(' (at %s)' % self.coord)
+        buf.write('\n')
+
+        for c in self.children():
+            c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class Union(Node):
+    def __init__(self, name, decls, coord=None):
+        self.name = name
+        self.decls = decls
+        self.coord = coord
+
+    def children(self):
+        nodelist = []
+        if self.decls is not None: nodelist.extend(self.decls)
+        return tuple(nodelist)
+
+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+        lead = ' ' * offset
+        buf.write(lead + 'Union: ')
+
+        if attrnames:
+            attrstr = ', '.join('%s=%s' % nv for nv in [("name", repr(self.name))])
+        else:
+            attrstr = ', '.join('%s' % v for v in [self.name])
+        buf.write(attrstr)
+
+        if showcoord:
+            buf.write(' (at %s)' % self.coord)
+        buf.write('\n')
+
+        for c in self.children():
+            c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class TernaryOp(Node):
+    def __init__(self, cond, iftrue, iffalse, coord=None):
+        self.cond = cond
+        self.iftrue = iftrue
+        self.iffalse = iffalse
+        self.coord = coord
+
+    def children(self):
+        nodelist = []
+        if self.cond is not None: nodelist.append(self.cond)
+        if self.iftrue is not None: nodelist.append(self.iftrue)
+        if self.iffalse is not None: nodelist.append(self.iffalse)
+        return tuple(nodelist)
+
+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+        lead = ' ' * offset
+        buf.write(lead + 'TernaryOp: ')
+
+        if showcoord:
+            buf.write(' (at %s)' % self.coord)
+        buf.write('\n')
+
+        for c in self.children():
+            c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class Label(Node):
+    def __init__(self, name, stmt, coord=None):
+        self.name = name
+        self.stmt = stmt
+        self.coord = coord
+
+    def children(self):
+        nodelist = []
+        if self.stmt is not None: nodelist.append(self.stmt)
+        return tuple(nodelist)
+
+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+        lead = ' ' * offset
+        buf.write(lead + 'Label: ')
+
+        if attrnames:
+            attrstr = ', '.join('%s=%s' % nv for nv in [("name", repr(self.name))])
+        else:
+            attrstr = ', '.join('%s' % v for v in [self.name])
+        buf.write(attrstr)
+
+        if showcoord:
+            buf.write(' (at %s)' % self.coord)
+        buf.write('\n')
+
+        for c in self.children():
+            c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class IdentifierType(Node):
+    def __init__(self, names, coord=None):
+        self.names = names
+        self.coord = coord
+
+    def children(self):
+        nodelist = []
+        return tuple(nodelist)
+
+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+        lead = ' ' * offset
+        buf.write(lead + 'IdentifierType: ')
+
+        if attrnames:
+            attrstr = ', '.join('%s=%s' % nv for nv in [("names", repr(self.names))])
+        else:
+            attrstr = ', '.join('%s' % v for v in [self.names])
+        buf.write(attrstr)
+
+        if showcoord:
+            buf.write(' (at %s)' % self.coord)
+        buf.write('\n')
+
+        for c in self.children():
+            c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class FuncDef(Node):
+    def __init__(self, decl, param_decls, body, coord=None):
+        self.decl = decl
+        self.param_decls = param_decls
+        self.body = body
+        self.coord = coord
+
+    def children(self):
+        nodelist = []
+        if self.decl is not None: nodelist.append(self.decl)
+        if self.body is not None: nodelist.append(self.body)
+        if self.param_decls is not None: nodelist.extend(self.param_decls)
+        return tuple(nodelist)
+
+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+        lead = ' ' * offset
+        buf.write(lead + 'FuncDef: ')
+
+        if showcoord:
+            buf.write(' (at %s)' % self.coord)
+        buf.write('\n')
+
+        for c in self.children():
+            c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class Enumerator(Node):
+    def __init__(self, name, value, coord=None):
+        self.name = name
+        self.value = value
+        self.coord = coord
+
+    def children(self):
+        nodelist = []
+        if self.value is not None: nodelist.append(self.value)
+        return tuple(nodelist)
+
+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+        lead = ' ' * offset
+        buf.write(lead + 'Enumerator: ')
+
+        if attrnames:
+            attrstr = ', '.join('%s=%s' % nv for nv in [("name", repr(self.name))])
+        else:
+            attrstr = ', '.join('%s' % v for v in [self.name])
+        buf.write(attrstr)
+
+        if showcoord:
+            buf.write(' (at %s)' % self.coord)
+        buf.write('\n')
+
+        for c in self.children():
+            c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class For(Node):
+    def __init__(self, init, cond, next, stmt, coord=None):
+        self.init = init
+        self.cond = cond
+        self.next = next
+        self.stmt = stmt
+        self.coord = coord
+
+    def children(self):
+        nodelist = []
+        if self.init is not None: nodelist.append(self.init)
+        if self.cond is not None: nodelist.append(self.cond)
+        if self.next is not None: nodelist.append(self.next)
+        if self.stmt is not None: nodelist.append(self.stmt)
+        return tuple(nodelist)
+
+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+        lead = ' ' * offset
+        buf.write(lead + 'For: ')
+
+        if showcoord:
+            buf.write(' (at %s)' % self.coord)
+        buf.write('\n')
+
+        for c in self.children():
+            c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class Assignment(Node):
+    def __init__(self, op, lvalue, rvalue, coord=None):
+        self.op = op
+        self.lvalue = lvalue
+        self.rvalue = rvalue
+        self.coord = coord
+
+    def children(self):
+        nodelist = []
+        if self.lvalue is not None: nodelist.append(self.lvalue)
+        if self.rvalue is not None: nodelist.append(self.rvalue)
+        return tuple(nodelist)
+
+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+        lead = ' ' * offset
+        buf.write(lead + 'Assignment: ')
+
+        if attrnames:
+            attrstr = ', '.join('%s=%s' % nv for nv in [("op", repr(self.op))])
+        else:
+            attrstr = ', '.join('%s' % v for v in [self.op])
+        buf.write(attrstr)
+
+        if showcoord:
+            buf.write(' (at %s)' % self.coord)
+        buf.write('\n')
+
+        for c in self.children():
+            c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class FuncDecl(Node):
+    def __init__(self, args, type, coord=None):
+        self.args = args
+        self.type = type
+        self.coord = coord
+
+    def children(self):
+        nodelist = []
+        if self.args is not None: nodelist.append(self.args)
+        if self.type is not None: nodelist.append(self.type)
+        return tuple(nodelist)
+
+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+        lead = ' ' * offset
+        buf.write(lead + 'FuncDecl: ')
+
+        if showcoord:
+            buf.write(' (at %s)' % self.coord)
+        buf.write('\n')
+
+        for c in self.children():
+            c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class Enum(Node):
+    def __init__(self, name, values, coord=None):
+        self.name = name
+        self.values = values
+        self.coord = coord
+
+    def children(self):
+        nodelist = []
+        if self.values is not None: nodelist.append(self.values)
+        return tuple(nodelist)
+
+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+        lead = ' ' * offset
+        buf.write(lead + 'Enum: ')
+
+        if attrnames:
+            attrstr = ', '.join('%s=%s' % nv for nv in [("name", repr(self.name))])
+        else:
+            attrstr = ', '.join('%s' % v for v in [self.name])
+        buf.write(attrstr)
+
+        if showcoord:
+            buf.write(' (at %s)' % self.coord)
+        buf.write('\n')
+
+        for c in self.children():
+            c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class ExprList(Node):
+    def __init__(self, exprs, coord=None):
+        self.exprs = exprs
+        self.coord = coord
+
+    def children(self):
+        nodelist = []
+        if self.exprs is not None: nodelist.extend(self.exprs)
+        return tuple(nodelist)
+
+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+        lead = ' ' * offset
+        buf.write(lead + 'ExprList: ')
+
+        if showcoord:
+            buf.write(' (at %s)' % self.coord)
+        buf.write('\n')
+
+        for c in self.children():
+            c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class Break(Node):
+    def __init__(self, coord=None):
+        self.coord = coord
+
+    def children(self):
+        return ()
+
+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+        lead = ' ' * offset
+        buf.write(lead + 'Break: ')
+
+        if showcoord:
+            buf.write(' (at %s)' % self.coord)
+        buf.write('\n')
+
+        for c in self.children():
+            c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class DoWhile(Node):
+    def __init__(self, cond, stmt, coord=None):
+        self.cond = cond
+        self.stmt = stmt
+        self.coord = coord
+
+    def children(self):
+        nodelist = []
+        if self.cond is not None: nodelist.append(self.cond)
+        if self.stmt is not None: nodelist.append(self.stmt)
+        return tuple(nodelist)
+
+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+        lead = ' ' * offset
+        buf.write(lead + 'DoWhile: ')
+
+        if showcoord:
+            buf.write(' (at %s)' % self.coord)
+        buf.write('\n')
+
+        for c in self.children():
+            c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class StructRef(Node):
+    def __init__(self, name, type, field, coord=None):
+        self.name = name
+        self.type = type
+        self.field = field
+        self.coord = coord
+
+    def children(self):
+        nodelist = []
+        if self.name is not None: nodelist.append(self.name)
+        if self.field is not None: nodelist.append(self.field)
+        return tuple(nodelist)
+
+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+        lead = ' ' * offset
+        buf.write(lead + 'StructRef: ')
+
+        if attrnames:
+            attrstr = ', '.join('%s=%s' % nv for nv in [("type", repr(self.type))])
+        else:
+            attrstr = ', '.join('%s' % v for v in [self.type])
+        buf.write(attrstr)
+
+        if showcoord:
+            buf.write(' (at %s)' % self.coord)
+        buf.write('\n')
+
+        for c in self.children():
+            c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class BinaryOp(Node):
+    def __init__(self, op, left, right, coord=None):
+        self.op = op
+        self.left = left
+        self.right = right
+        self.coord = coord
+
+    def children(self):
+        nodelist = []
+        if self.left is not None: nodelist.append(self.left)
+        if self.right is not None: nodelist.append(self.right)
+        return tuple(nodelist)
+
+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+        lead = ' ' * offset
+        buf.write(lead + 'BinaryOp: ')
+
+        if attrnames:
+            attrstr = ', '.join('%s=%s' % nv for nv in [("op", repr(self.op))])
+        else:
+            attrstr = ', '.join('%s' % v for v in [self.op])
+        buf.write(attrstr)
+
+        if showcoord:
+            buf.write(' (at %s)' % self.coord)
+        buf.write('\n')
+
+        for c in self.children():
+            c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class Compound(Node):
+    def __init__(self, decls, stmts, coord=None):
+        self.decls = decls
+        self.stmts = stmts
+        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)
+        return tuple(nodelist)
+
+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+        lead = ' ' * offset
+        buf.write(lead + 'Compound: ')
+
+        if showcoord:
+            buf.write(' (at %s)' % self.coord)
+        buf.write('\n')
+
+        for c in self.children():
+            c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class ArrayDecl(Node):
+    def __init__(self, type, dim, coord=None):
+        self.type = type
+        self.dim = dim
+        self.coord = coord
+
+    def children(self):
+        nodelist = []
+        if self.type is not None: nodelist.append(self.type)
+        if self.dim is not None: nodelist.append(self.dim)
+        return tuple(nodelist)
+
+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+        lead = ' ' * offset
+        buf.write(lead + 'ArrayDecl: ')
+
+        if showcoord:
+            buf.write(' (at %s)' % self.coord)
+        buf.write('\n')
+
+        for c in self.children():
+            c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class Case(Node):
+    def __init__(self, expr, stmt, coord=None):
+        self.expr = expr
+        self.stmt = stmt
+        self.coord = coord
+
+    def children(self):
+        nodelist = []
+        if self.expr is not None: nodelist.append(self.expr)
+        if self.stmt is not None: nodelist.append(self.stmt)
+        return tuple(nodelist)
+
+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+        lead = ' ' * offset
+        buf.write(lead + 'Case: ')
+
+        if showcoord:
+            buf.write(' (at %s)' % self.coord)
+        buf.write('\n')
+
+        for c in self.children():
+            c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class Cast(Node):
+    def __init__(self, to_type, expr, coord=None):
+        self.to_type = to_type
+        self.expr = expr
+        self.coord = coord
+
+    def children(self):
+        nodelist = []
+        if self.to_type is not None: nodelist.append(self.to_type)
+        if self.expr is not None: nodelist.append(self.expr)
+        return tuple(nodelist)
+
+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+        lead = ' ' * offset
+        buf.write(lead + 'Cast: ')
+
+        if showcoord:
+            buf.write(' (at %s)' % self.coord)
+        buf.write('\n')
+
+        for c in self.children():
+            c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class TypeDecl(Node):
+    def __init__(self, declname, quals, type, coord=None):
+        self.declname = declname
+        self.quals = quals
+        self.type = type
+        self.coord = coord
+
+    def children(self):
+        nodelist = []
+        if self.type is not None: nodelist.append(self.type)
+        return tuple(nodelist)
+
+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+        lead = ' ' * offset
+        buf.write(lead + 'TypeDecl: ')
+
+        if attrnames:
+            attrstr = ', '.join('%s=%s' % nv for nv in [("declname", repr(self.declname)), ("quals", repr(self.quals))])
+        else:
+            attrstr = ', '.join('%s' % v for v in [self.declname, self.quals])
+        buf.write(attrstr)
+
+        if showcoord:
+            buf.write(' (at %s)' % self.coord)
+        buf.write('\n')
+
+        for c in self.children():
+            c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class Default(Node):
+    def __init__(self, stmt, coord=None):
+        self.stmt = stmt
+        self.coord = coord
+
+    def children(self):
+        nodelist = []
+        if self.stmt is not None: nodelist.append(self.stmt)
+        return tuple(nodelist)
+
+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+        lead = ' ' * offset
+        buf.write(lead + 'Default: ')
+
+        if showcoord:
+            buf.write(' (at %s)' % self.coord)
+        buf.write('\n')
+
+        for c in self.children():
+            c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class PtrDecl(Node):
+    def __init__(self, quals, type, coord=None):
+        self.quals = quals
+        self.type = type
+        self.coord = coord
+
+    def children(self):
+        nodelist = []
+        if self.type is not None: nodelist.append(self.type)
+        return tuple(nodelist)
+
+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+        lead = ' ' * offset
+        buf.write(lead + 'PtrDecl: ')
+
+        if attrnames:
+            attrstr = ', '.join('%s=%s' % nv for nv in [("quals", repr(self.quals))])
+        else:
+            attrstr = ', '.join('%s' % v for v in [self.quals])
+        buf.write(attrstr)
+
+        if showcoord:
+            buf.write(' (at %s)' % self.coord)
+        buf.write('\n')
+
+        for c in self.children():
+            c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class Switch(Node):
+    def __init__(self, cond, stmt, coord=None):
+        self.cond = cond
+        self.stmt = stmt
+        self.coord = coord
+
+    def children(self):
+        nodelist = []
+        if self.cond is not None: nodelist.append(self.cond)
+        if self.stmt is not None: nodelist.append(self.stmt)
+        return tuple(nodelist)
+
+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+        lead = ' ' * offset
+        buf.write(lead + 'Switch: ')
+
+        if showcoord:
+            buf.write(' (at %s)' % self.coord)
+        buf.write('\n')
+
+        for c in self.children():
+            c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class Continue(Node):
+    def __init__(self, coord=None):
+        self.coord = coord
+
+    def children(self):
+        return ()
+
+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+        lead = ' ' * offset
+        buf.write(lead + 'Continue: ')
+
+        if showcoord:
+            buf.write(' (at %s)' % self.coord)
+        buf.write('\n')
+
+        for c in self.children():
+            c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class ParamList(Node):
+    def __init__(self, params, coord=None):
+        self.params = params
+        self.coord = coord
+
+    def children(self):
+        nodelist = []
+        if self.params is not None: nodelist.extend(self.params)
+        return tuple(nodelist)
+
+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+        lead = ' ' * offset
+        buf.write(lead + 'ParamList: ')
+
+        if showcoord:
+            buf.write(' (at %s)' % self.coord)
+        buf.write('\n')
+
+        for c in self.children():
+            c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class Return(Node):
+    def __init__(self, expr, coord=None):
+        self.expr = expr
+        self.coord = coord
+
+    def children(self):
+        nodelist = []
+        if self.expr is not None: nodelist.append(self.expr)
+        return tuple(nodelist)
+
+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+        lead = ' ' * offset
+        buf.write(lead + 'Return: ')
+
+        if showcoord:
+            buf.write(' (at %s)' % self.coord)
+        buf.write('\n')
+
+        for c in self.children():
+            c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class Typename(Node):
+    def __init__(self, quals, type, coord=None):
+        self.quals = quals
+        self.type = type
+        self.coord = coord
+
+    def children(self):
+        nodelist = []
+        if self.type is not None: nodelist.append(self.type)
+        return tuple(nodelist)
+
+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+        lead = ' ' * offset
+        buf.write(lead + 'Typename: ')
+
+        if attrnames:
+            attrstr = ', '.join('%s=%s' % nv for nv in [("quals", repr(self.quals))])
+        else:
+            attrstr = ', '.join('%s' % v for v in [self.quals])
+        buf.write(attrstr)
+
+        if showcoord:
+            buf.write(' (at %s)' % self.coord)
+        buf.write('\n')
+
+        for c in self.children():
+            c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class ID(Node):
+    def __init__(self, name, coord=None):
+        self.name = name
+        self.coord = coord
+
+    def children(self):
+        nodelist = []
+        return tuple(nodelist)
+
+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+        lead = ' ' * offset
+        buf.write(lead + 'ID: ')
+
+        if attrnames:
+            attrstr = ', '.join('%s=%s' % nv for nv in [("name", repr(self.name))])
+        else:
+            attrstr = ', '.join('%s' % v for v in [self.name])
+        buf.write(attrstr)
+
+        if showcoord:
+            buf.write(' (at %s)' % self.coord)
+        buf.write('\n')
+
+        for c in self.children():
+            c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class Goto(Node):
+    def __init__(self, name, coord=None):
+        self.name = name
+        self.coord = coord
+
+    def children(self):
+        nodelist = []
+        return tuple(nodelist)
+
+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+        lead = ' ' * offset
+        buf.write(lead + 'Goto: ')
+
+        if attrnames:
+            attrstr = ', '.join('%s=%s' % nv for nv in [("name", repr(self.name))])
+        else:
+            attrstr = ', '.join('%s' % v for v in [self.name])
+        buf.write(attrstr)
+
+        if showcoord:
+            buf.write(' (at %s)' % self.coord)
+        buf.write('\n')
+
+        for c in self.children():
+            c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class Decl(Node):
+    def __init__(self, name, quals, storage, type, init, bitsize, coord=None):
+        self.name = name
+        self.quals = quals
+        self.storage = storage
+        self.type = type
+        self.init = init
+        self.bitsize = bitsize
+        self.coord = coord
+
+    def children(self):
+        nodelist = []
+        if self.type is not None: nodelist.append(self.type)
+        if self.init is not None: nodelist.append(self.init)
+        if self.bitsize is not None: nodelist.append(self.bitsize)
+        return tuple(nodelist)
+
+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+        lead = ' ' * offset
+        buf.write(lead + 'Decl: ')
+
+        if attrnames:
+            attrstr = ', '.join('%s=%s' % nv for nv in [("name", repr(self.name)), ("quals", repr(self.quals)), ("storage", repr(self.storage))])
+        else:
+            attrstr = ', '.join('%s' % v for v in [self.name, self.quals, self.storage])
+        buf.write(attrstr)
+
+        if showcoord:
+            buf.write(' (at %s)' % self.coord)
+        buf.write('\n')
+
+        for c in self.children():
+            c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class Constant(Node):
+    def __init__(self, type, value, coord=None):
+        self.type = type
+        self.value = value
+        self.coord = coord
+
+    def children(self):
+        nodelist = []
+        return tuple(nodelist)
+
+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+        lead = ' ' * offset
+        buf.write(lead + 'Constant: ')
+
+        if attrnames:
+            attrstr = ', '.join('%s=%s' % nv for nv in [("type", repr(self.type)), ("value", repr(self.value))])
+        else:
+            attrstr = ', '.join('%s' % v for v in [self.type, self.value])
+        buf.write(attrstr)
+
+        if showcoord:
+            buf.write(' (at %s)' % self.coord)
+        buf.write('\n')
+
+        for c in self.children():
+            c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class FileAST(Node):
+    def __init__(self, ext, coord=None):
+        self.ext = ext
+        self.coord = coord
+
+    def children(self):
+        nodelist = []
+        if self.ext is not None: nodelist.extend(self.ext)
+        return tuple(nodelist)
+
+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+        lead = ' ' * offset
+        buf.write(lead + 'FileAST: ')
+
+        if showcoord:
+            buf.write(' (at %s)' % self.coord)
+        buf.write('\n')
+
+        for c in self.children():
+            c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class ArrayRef(Node):
+    def __init__(self, name, subscript, coord=None):
+        self.name = name
+        self.subscript = subscript
+        self.coord = coord
+
+    def children(self):
+        nodelist = []
+        if self.name is not None: nodelist.append(self.name)
+        if self.subscript is not None: nodelist.append(self.subscript)
+        return tuple(nodelist)
+
+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+        lead = ' ' * offset
+        buf.write(lead + 'ArrayRef: ')
+
+        if showcoord:
+            buf.write(' (at %s)' % self.coord)
+        buf.write('\n')
+
+        for c in self.children():
+            c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class While(Node):
+    def __init__(self, cond, stmt, coord=None):
+        self.cond = cond
+        self.stmt = stmt
+        self.coord = coord
+
+    def children(self):
+        nodelist = []
+        if self.cond is not None: nodelist.append(self.cond)
+        if self.stmt is not None: nodelist.append(self.stmt)
+        return tuple(nodelist)
+
+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+        lead = ' ' * offset
+        buf.write(lead + 'While: ')
+
+        if showcoord:
+            buf.write(' (at %s)' % self.coord)
+        buf.write('\n')
+
+        for c in self.children():
+            c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class EnumeratorList(Node):
+    def __init__(self, enumerators, coord=None):
+        self.enumerators = enumerators
+        self.coord = coord
+
+    def children(self):
+        nodelist = []
+        if self.enumerators is not None: nodelist.extend(self.enumerators)
+        return tuple(nodelist)
+
+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+        lead = ' ' * offset
+        buf.write(lead + 'EnumeratorList: ')
+
+        if showcoord:
+            buf.write(' (at %s)' % self.coord)
+        buf.write('\n')
+
+        for c in self.children():
+            c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class EllipsisParam(Node):
+    def __init__(self, coord=None):
+        self.coord = coord
+
+    def children(self):
+        return ()
+
+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+        lead = ' ' * offset
+        buf.write(lead + 'EllipsisParam: ')
+
+        if showcoord:
+            buf.write(' (at %s)' % self.coord)
+        buf.write('\n')
+
+        for c in self.children():
+            c.show(buf, offset + 2, attrnames, showcoord)
+
+
+class If(Node):
+    def __init__(self, cond, iftrue, iffalse, coord=None):
+        self.cond = cond
+        self.iftrue = iftrue
+        self.iffalse = iffalse
+        self.coord = coord
+
+    def children(self):
+        nodelist = []
+        if self.cond is not None: nodelist.append(self.cond)
+        if self.iftrue is not None: nodelist.append(self.iftrue)
+        if self.iffalse is not None: nodelist.append(self.iffalse)
+        return tuple(nodelist)
+
+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):
+        lead = ' ' * offset
+        buf.write(lead + 'If: ')
+
+        if showcoord:
+            buf.write(' (at %s)' % self.coord)
+        buf.write('\n')
+
+        for c in self.children():
+            c.show(buf, offset + 2, attrnames, showcoord)
+
+

pycparser/c_parser.py

         """
         # Note: external_declaration is already a list
         #
-        p[0] = c_ast.AST(p[1])
+        p[0] = c_ast.FileAST(p[1])
     
     def p_translation_unit_2(self, p):
         """ translation_unit    : translation_unit external_declaration
     # I.e. "hello " "world" is seen by the C compiler as a single string literal
     # with the value "hello world"
     #
-    def p_unified_string_literal(self, p):
+    def p_unified_string_literal(self, p):
         """ unified_string_literal  : STRING_LITERAL
-                                    | unified_string_literal STRING_LITERAL  
+                                    | unified_string_literal STRING_LITERAL  
         """
         if len(p) == 2: # single literal
             p[0] = c_ast.Constant(