Skip to content

Commit

Permalink
Better pretty printing for ASDL's own AST.
Browse files Browse the repository at this point in the history
This will help with generating code to support reflection over ASDL
types.
  • Loading branch information
Andy Chu committed Dec 19, 2017
1 parent 07b0648 commit e30dd7f
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 26 deletions.
84 changes: 59 additions & 25 deletions asdl/asdl_.py
Expand Up @@ -19,6 +19,7 @@
# [1] "The Zephyr Abstract Syntax Description Language" by Wang, et. al. See
# http://asdl.sourceforge.net/
#-------------------------------------------------------------------------------
import cStringIO
import re

__all__ = [
Expand Down Expand Up @@ -94,39 +95,59 @@ def __repr__(self):
# See the EBNF at the top of the file to understand the logical connection
# between the various node types.

# TODO:
# - Add id type -- or should it be py(id) or something?

builtin_types = {'string', 'int', 'bool'}

class AST:
def __repr__(self):
def Print(self, f, indent):
raise NotImplementedError

def __repr__(self):
f = cStringIO.StringIO()
self.Print(f, 0)
return f.getvalue()


class Module(AST):
def __init__(self, name, dfns):
self.name = name
self.dfns = dfns
self.types = {type.name: type.value for type in dfns}

def __repr__(self):
return 'Module({0.name}, {0.dfns})'.format(self)
def Print(self, f, indent):
ind = indent * ' '
f.write('%sModule %s {\n' % (ind, self.name))

for d in self.dfns:
d.Print(f, indent+1)
f.write('\n')
f.write('%s}\n' % ind)


class Type(AST):
def __init__(self, name, value):
self.name = name
self.value = value

def __repr__(self):
return 'Type({0.name}, {0.value})'.format(self)
def Print(self, f, indent):
ind = indent * ' '
f.write('%sType %s {\n' % (ind, self.name))
self.value.Print(f, indent+1)
f.write('%s}\n' % ind)


class Constructor(AST):
def __init__(self, name, fields=None):
self.name = name
self.fields = fields or []

def __repr__(self):
return 'Constructor({0.name}, {0.fields})'.format(self)
def Print(self, f, indent):
ind = indent * ' '
f.write('%sConstructor %s {\n' % (ind, self.name))

for field in self.fields:
field.Print(f, indent+1)
f.write('%s}\n' % ind)


class Field(AST):
def __init__(self, type, name=None, seq=False, opt=False):
Expand All @@ -135,39 +156,52 @@ def __init__(self, type, name=None, seq=False, opt=False):
self.seq = seq
self.opt = opt

def __repr__(self):
def Print(self, f, indent):
extra = []
if self.seq:
extra = ", seq=True"
extra.append('seq=True')
elif self.opt:
extra = ", opt=True"
extra.append('opt=True')
else:
extra = ""
if self.name is None:
return 'Field({0.type}{1})'.format(self, extra)
else:
return 'Field({0.type}, {0.name}{1})'.format(self, extra)

ind = indent * ' '
f.write('%sField %s %s' % (ind, self.name, self.type))
if extra:
f.write('(')
f.write(', '.join(extra))
f.write(')')
f.write('\n')


class Sum(AST):
def __init__(self, types, attributes=None):
self.types = types
self.attributes = attributes or []

def __repr__(self):
def Print(self, f, indent):
ind = indent * ' '
f.write('%sSum {\n' % ind)
for t in self.types:
t.Print(f, indent+1)
if self.attributes:
return 'Sum({0.types}, {0.attributes})'.format(self)
else:
return 'Sum({0.types})'.format(self)
f.write('%s\n' % self.attributes)
f.write('%s}\n' % ind)


class Product(AST):
def __init__(self, fields, attributes=None):
self.fields = fields
self.attributes = attributes or []

def __repr__(self):
def Print(self, f, indent):
ind = indent * ' '
f.write('%sProduct {\n' % ind)
for field in self.fields:
field.Print(f, indent+1)
if self.attributes:
return 'Product({0.fields}, {0.attributes})'.format(self)
else:
return 'Product({0.fields})'.format(self)
f.write('%s\n' % self.attributes)
f.write('%s}\n' % ind)

# A generic visitor for the meta-AST that describes ASDL. This can be used by
# emitters. Note that this visitor does not provide a generic visit method, so a
Expand Down
1 change: 0 additions & 1 deletion asdl/format.py
Expand Up @@ -315,7 +315,6 @@ def MakeTree(obj, abbrev_hook=None, omit_empty=True):
else:
# Id uses this now. TODO: Should we have plugins? Might need it for
# color.
#print('OTHER', obj.__class__, isinstance(obj, py_meta.CompoundObj))
return _ColoredString(repr(obj), _OTHER_TYPE)

return out_node
Expand Down
4 changes: 4 additions & 0 deletions asdl/gen_python.py
@@ -1,6 +1,10 @@
#!/usr/bin/python
"""
gen_python.py
Generate Python code from and ASDL schema.
TODO: What about Id? app_types?
"""

import sys
Expand Down

0 comments on commit e30dd7f

Please sign in to comment.