summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorldore <laurent.dore@gmail.com>2018-01-17 14:31:30 +0100
committerEli Bendersky <eliben@users.noreply.github.com>2018-01-17 05:31:30 -0800
commit216823845b2d123f7d443cf27ee057cd1943f0c1 (patch)
tree0b195f522ea964d900442c5b8013893468c49f97
parent97e74649a2aadbf317a74d421121af8060e841f3 (diff)
downloadpycparser-216823845b2d123f7d443cf27ee057cd1943f0c1.tar.gz
Implement __repr__ on Nodes (Issue #226) (#227)
* Implement __repr__ on Nodes.
-rw-r--r--pycparser/_ast_gen.py29
-rw-r--r--pycparser/c_ast.py27
-rw-r--r--tests/test_c_ast.py53
3 files changed, 107 insertions, 2 deletions
diff --git a/pycparser/_ast_gen.py b/pycparser/_ast_gen.py
index 526d1ec..4dab963 100644
--- a/pycparser/_ast_gen.py
+++ b/pycparser/_ast_gen.py
@@ -63,6 +63,7 @@ class NodeCfg(object):
contents: a list of contents - attributes and child nodes
See comment at the top of the configuration file for details.
"""
+
def __init__(self, name, contents):
self.name = name
self.all_entries = []
@@ -85,6 +86,7 @@ class NodeCfg(object):
src = self._gen_init()
src += '\n' + self._gen_children()
src += '\n' + self._gen_iter()
+
src += '\n' + self._gen_attr_names()
return src
@@ -187,11 +189,38 @@ r'''#-----------------------------------------------------------------
_PROLOGUE_CODE = r'''
import sys
+def _repr(obj):
+ """
+ Get the representation of an object, with dedicated pprint-like format for lists.
+ """
+ if isinstance(obj, list):
+ return '[' + (',\n '.join((_repr(e).replace('\n', '\n ') for e in obj))) + '\n]'
+ else:
+ return repr(obj)
class Node(object):
__slots__ = ()
""" Abstract base class for AST nodes.
"""
+ def __repr__(self):
+ """ Generates a python representation of the current node
+ """
+ result = self.__class__.__name__ + '('
+
+ indent = ''
+ separator = ''
+ for name in self.__slots__[:-2]:
+ result += separator
+ result += indent
+ result += name + '=' + (_repr(getattr(self, name)).replace('\n', '\n ' + (' ' * (len(name) + len(self.__class__.__name__)))))
+
+ separator = ','
+ indent = '\n ' + (' ' * len(self.__class__.__name__))
+
+ result += indent + ')'
+
+ return result
+
def children(self):
""" A sequence of all children that are Nodes
"""
diff --git a/pycparser/c_ast.py b/pycparser/c_ast.py
index 99cd6a4..219f07b 100644
--- a/pycparser/c_ast.py
+++ b/pycparser/c_ast.py
@@ -18,11 +18,38 @@
import sys
+def _repr(obj):
+ """
+ Get the representation of an object, with dedicated pprint-like format for lists and tuples.
+ """
+ if isinstance(obj, list):
+ return '[' + (',\n '.join((_repr(e).replace('\n', '\n ') for e in obj))) + '\n]'
+ else:
+ return repr(obj)
class Node(object):
__slots__ = ()
""" Abstract base class for AST nodes.
"""
+ def __repr__(self):
+ """ Generates a python representation of the current node
+ """
+ result = self.__class__.__name__ + '('
+
+ indent = ''
+ separator = ''
+ for name in self.__slots__[:-2]:
+ result += separator
+ result += indent
+ result += name + '=' + (_repr(getattr(self, name)).replace('\n', '\n ' + (' ' * (len(name) + len(self.__class__.__name__)))))
+
+ separator = ','
+ indent = '\n ' + (' ' * len(self.__class__.__name__))
+
+ result += indent + ')'
+
+ return result
+
def children(self):
""" A sequence of all children that are Nodes
"""
diff --git a/tests/test_c_ast.py b/tests/test_c_ast.py
index bfe301a..8e95d55 100644
--- a/tests/test_c_ast.py
+++ b/tests/test_c_ast.py
@@ -38,7 +38,6 @@ class Test_c_ast(unittest.TestCase):
self.assertEqual(weakref.getweakrefcount(coord), 1)
-
class TestNodeVisitor(unittest.TestCase):
class ConstantVisitor(c_ast.NodeVisitor):
def __init__(self):
@@ -94,7 +93,57 @@ class TestNodeVisitor(unittest.TestCase):
cv.visit(comp)
self.assertEqual(cv.values,
- ['5.6', 't', '5.6', 't', 't', '5.6', 't'])
+ ['5.6', 't', '5.6', 't', 't', '5.6', 't'])
+
+ def test_repr(self):
+ c1 = c_ast.Constant(type='float', value='5.6')
+ c2 = c_ast.Constant(type='char', value='t')
+
+ b1 = c_ast.BinaryOp(
+ op='+',
+ left=c1,
+ right=c2)
+
+ b2 = c_ast.BinaryOp(
+ op='-',
+ left=b1,
+ right=c2)
+
+ comp = c_ast.Compound(
+ block_items=[b1, b2, c1, c2])
+
+ expected = ("Compound(block_items=[BinaryOp(op='+',\n"
+ " left=Constant(type='float',\n"
+ " value='5.6'\n"
+ " ),\n"
+ " right=Constant(type='char',\n"
+ " value='t'\n"
+ " )\n"
+ " ),\n"
+ " BinaryOp(op='-',\n"
+ " left=BinaryOp(op='+',\n"
+ " left=Constant(type='float',\n"
+ " value='5.6'\n"
+ " ),\n"
+ " right=Constant(type='char',\n"
+ " value='t'\n"
+ " )\n"
+ " ),\n"
+ " right=Constant(type='char',\n"
+ " value='t'\n"
+ " )\n"
+ " ),\n"
+ " Constant(type='float',\n"
+ " value='5.6'\n"
+ " ),\n"
+ " Constant(type='char',\n"
+ " value='t'\n"
+ " )\n"
+ " ]\n"
+ " )")
+
+ self.assertEqual(repr(comp),
+ expected)
if __name__ == '__main__':