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
24 changes: 16 additions & 8 deletions pycparser/_ast_gen.py
Expand Up @@ -224,16 +224,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 @@ -245,8 +242,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 verticle lines to be displayed infront of 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 @@ -265,14 +270,17 @@ def show(self, buf=sys.stdout, offset=0, attrnames=False, nodenames=False, showc
buf.write(' (at %s)' % self.coord)
buf.write('\n')

for (child_name, child) in self.children():
indent += " " if islast else "│ "

for idx, (child_name, child) in enumerate(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=(idx == len(self.children())-1))


class NodeVisitor(object):
Expand Down
2 changes: 1 addition & 1 deletion pycparser/_build_tables.py
Expand Up @@ -20,7 +20,7 @@
# Generate c_ast.py
from _ast_gen import ASTCodeGenerator
ast_gen = ASTCodeGenerator('_c_ast.cfg')
ast_gen.generate(open('c_ast.py', 'w'))
ast_gen.generate(open('c_ast.py', 'w', encoding='UTF-8')))
Dob-The-Duilder marked this conversation as resolved.
Show resolved Hide resolved

from pycparser import c_parser

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