From e30dd7f19f5c51bb35a4889134726b9afb4d19fa Mon Sep 17 00:00:00 2001 From: Andy Chu Date: Tue, 19 Dec 2017 09:34:16 -0800 Subject: [PATCH] Better pretty printing for ASDL's own AST. This will help with generating code to support reflection over ASDL types. --- asdl/asdl_.py | 84 ++++++++++++++++++++++++++++++++-------------- asdl/format.py | 1 - asdl/gen_python.py | 4 +++ 3 files changed, 63 insertions(+), 26 deletions(-) diff --git a/asdl/asdl_.py b/asdl/asdl_.py index ed1ea4c9b3..87182f413b 100644 --- a/asdl/asdl_.py +++ b/asdl/asdl_.py @@ -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__ = [ @@ -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): @@ -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 diff --git a/asdl/format.py b/asdl/format.py index 3d33d1dc59..d97a92c9a8 100644 --- a/asdl/format.py +++ b/asdl/format.py @@ -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 diff --git a/asdl/gen_python.py b/asdl/gen_python.py index cdeaa9055f..3aa501b768 100755 --- a/asdl/gen_python.py +++ b/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