Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Beautify Node.show() for parse tree printing #518

Closed
wants to merge 9 commits into from
110 changes: 62 additions & 48 deletions pycparser/_ast_gen.py
Expand Up @@ -224,55 +224,69 @@ def children(self):
"""
pass

def show(self, buf=sys.stdout, offset=0, attrnames=False, nodenames=False, showcoord=False, _my_node_name=None):
""" Pretty print the Node and all its attributes and
children (recursively) to a buffer.

buf:
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.

nodenames:
True if you want to see the actual node names
within their parents.

showcoord:
Do you want the coordinates of each Node to be
displayed.
"""
lead = ' ' * offset
if nodenames and _my_node_name is not None:
buf.write(lead + self.__class__.__name__+ ' <' + _my_node_name + '>: ')
else:
buf.write(lead + self.__class__.__name__+ ': ')

if self.attr_names:
if attrnames:
nvlist = [(n, getattr(self,n)) for n in self.attr_names]
attrstr = ', '.join('%s=%s' % nv for nv in nvlist)
def show(self, buf=sys.stdout, attrnames=False, nodenames=False, showcoord=False, _my_node_name=None, indent='', islast = True):
""" Pretty print the Node and all its attributes and
children (recursively) to a buffer.

buf:
Open IO buffer into which the Node is printed.

attrnames:
True if you want to see the attribute names in
name=value pairs. False to only see the values.

nodenames:
True if you want to see the actual node names
within their parents.

showcoord:
Do you want the coordinates of each Node to be
displayed.

indent:
Spaces and lines to be displayed behind node.

islast:
Denotes if node is final element in its tree.
"""
marker = "└─" if islast else "├─"
lead = indent + marker

if nodenames and _my_node_name is not None:
buf.write(lead + self.__class__.__name__+ ' <' + _my_node_name + '>: ')
else:
vlist = [getattr(self, n) for n in self.attr_names]
attrstr = ', '.join('%s' % v for v in vlist)
buf.write(attrstr)

if showcoord:
buf.write(' (at %s)' % self.coord)
buf.write('\n')

for (child_name, child) in self.children():
child.show(
buf,
offset=offset + 2,
attrnames=attrnames,
nodenames=nodenames,
showcoord=showcoord,
_my_node_name=child_name)
buf.write(lead + self.__class__.__name__+ ': ')

if self.attr_names:
if attrnames:
nvlist = [(n, getattr(self,n)) for n in self.attr_names]
attrstr = ', '.join('%s=%s' % nv for nv in nvlist)
else:
vlist = [getattr(self, n) for n in self.attr_names]
attrstr = ', '.join('%s' % v for v in vlist)
buf.write(attrstr)

if showcoord:
buf.write(' (at %s)' % self.coord)
buf.write('\n')

indent += " " if islast else "│ "

lastChild = None

children = self.children()
if len(children) > 0:
_, lastChild = children[-1]

for (child_name, child) in self.children():
child.show(
buf,
attrnames=attrnames,
nodenames=nodenames,
showcoord=showcoord,
_my_node_name=child_name,
indent=indent,
islast=(lastChild == child))


class NodeVisitor(object):
Expand Down
28 changes: 21 additions & 7 deletions pycparser/c_ast.py
Expand Up @@ -55,16 +55,13 @@ def children(self):
"""
pass

def show(self, buf=sys.stdout, offset=0, attrnames=False, nodenames=False, showcoord=False, _my_node_name=None):
def show(self, buf=sys.stdout, attrnames=False, nodenames=False, showcoord=False, _my_node_name=None, indent='', islast = True):
""" Pretty print the Node and all its attributes and
children (recursively) to a buffer.

buf:
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.
Expand All @@ -76,8 +73,16 @@ def show(self, buf=sys.stdout, offset=0, attrnames=False, nodenames=False, showc
showcoord:
Do you want the coordinates of each Node to be
displayed.

indent:
Spaces and lines to be displayed behind node.
Dob-The-Duilder marked this conversation as resolved.
Show resolved Hide resolved

islast:
Denotes if node is final element in its tree.
"""
lead = ' ' * offset
marker = "└─" if islast else "├─"
lead = indent + marker

if nodenames and _my_node_name is not None:
buf.write(lead + self.__class__.__name__+ ' <' + _my_node_name + '>: ')
else:
Expand All @@ -96,14 +101,23 @@ def show(self, buf=sys.stdout, offset=0, attrnames=False, nodenames=False, showc
buf.write(' (at %s)' % self.coord)
buf.write('\n')

indent += " " if islast else "│ "

lastChild = None

children = self.children()
if len(children) > 0:
_, lastChild = children[-1]
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you should be able to accomplish this in a cleaner way using enumerate in the for loop below. Then you can trivially find if the index is the one before last and you won't need this condition and lastChild

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I understood what you meant but if not let me know. Its been changed now.


for (child_name, child) in self.children():
child.show(
buf,
offset=offset + 2,
attrnames=attrnames,
nodenames=nodenames,
showcoord=showcoord,
_my_node_name=child_name)
_my_node_name=child_name,
indent=indent,
islast=(lastChild == child))


class NodeVisitor(object):
Expand Down