These files are a subset of the python-2.7.2.tgz distribution from python.org. Changed files from PyMod-2.7.2 have been copied into the corresponding directories of this tree, replacing the original files in the distribution. Signed-off-by: daryl.mcdaniel@intel.com git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@13197 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			295 lines
		
	
	
		
			9.8 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			295 lines
		
	
	
		
			9.8 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| """Generate ast module from specification
 | |
| 
 | |
| This script generates the ast module from a simple specification,
 | |
| which makes it easy to accomodate changes in the grammar.  This
 | |
| approach would be quite reasonable if the grammar changed often.
 | |
| Instead, it is rather complex to generate the appropriate code.  And
 | |
| the Node interface has changed more often than the grammar.
 | |
| """
 | |
| 
 | |
| import fileinput
 | |
| import re
 | |
| import sys
 | |
| from StringIO import StringIO
 | |
| 
 | |
| SPEC = "ast.txt"
 | |
| COMMA = ", "
 | |
| 
 | |
| def load_boilerplate(file):
 | |
|     f = open(file)
 | |
|     buf = f.read()
 | |
|     f.close()
 | |
|     i = buf.find('### ''PROLOGUE')
 | |
|     j = buf.find('### ''EPILOGUE')
 | |
|     pro = buf[i+12:j].strip()
 | |
|     epi = buf[j+12:].strip()
 | |
|     return pro, epi
 | |
| 
 | |
| def strip_default(arg):
 | |
|     """Return the argname from an 'arg = default' string"""
 | |
|     i = arg.find('=')
 | |
|     if i == -1:
 | |
|         return arg
 | |
|     t = arg[:i].strip()
 | |
|     return t
 | |
| 
 | |
| P_NODE = 1
 | |
| P_OTHER = 2
 | |
| P_NESTED = 3
 | |
| P_NONE = 4
 | |
| 
 | |
| class NodeInfo:
 | |
|     """Each instance describes a specific AST node"""
 | |
|     def __init__(self, name, args):
 | |
|         self.name = name
 | |
|         self.args = args.strip()
 | |
|         self.argnames = self.get_argnames()
 | |
|         self.argprops = self.get_argprops()
 | |
|         self.nargs = len(self.argnames)
 | |
|         self.init = []
 | |
| 
 | |
|     def get_argnames(self):
 | |
|         if '(' in self.args:
 | |
|             i = self.args.find('(')
 | |
|             j = self.args.rfind(')')
 | |
|             args = self.args[i+1:j]
 | |
|         else:
 | |
|             args = self.args
 | |
|         return [strip_default(arg.strip())
 | |
|                 for arg in args.split(',') if arg]
 | |
| 
 | |
|     def get_argprops(self):
 | |
|         """Each argument can have a property like '*' or '!'
 | |
| 
 | |
|         XXX This method modifies the argnames in place!
 | |
|         """
 | |
|         d = {}
 | |
|         hardest_arg = P_NODE
 | |
|         for i in range(len(self.argnames)):
 | |
|             arg = self.argnames[i]
 | |
|             if arg.endswith('*'):
 | |
|                 arg = self.argnames[i] = arg[:-1]
 | |
|                 d[arg] = P_OTHER
 | |
|                 hardest_arg = max(hardest_arg, P_OTHER)
 | |
|             elif arg.endswith('!'):
 | |
|                 arg = self.argnames[i] = arg[:-1]
 | |
|                 d[arg] = P_NESTED
 | |
|                 hardest_arg = max(hardest_arg, P_NESTED)
 | |
|             elif arg.endswith('&'):
 | |
|                 arg = self.argnames[i] = arg[:-1]
 | |
|                 d[arg] = P_NONE
 | |
|                 hardest_arg = max(hardest_arg, P_NONE)
 | |
|             else:
 | |
|                 d[arg] = P_NODE
 | |
|         self.hardest_arg = hardest_arg
 | |
| 
 | |
|         if hardest_arg > P_NODE:
 | |
|             self.args = self.args.replace('*', '')
 | |
|             self.args = self.args.replace('!', '')
 | |
|             self.args = self.args.replace('&', '')
 | |
| 
 | |
|         return d
 | |
| 
 | |
|     def gen_source(self):
 | |
|         buf = StringIO()
 | |
|         print >> buf, "class %s(Node):" % self.name
 | |
|         self._gen_init(buf)
 | |
|         print >> buf
 | |
|         self._gen_getChildren(buf)
 | |
|         print >> buf
 | |
|         self._gen_getChildNodes(buf)
 | |
|         print >> buf
 | |
|         self._gen_repr(buf)
 | |
|         buf.seek(0, 0)
 | |
|         return buf.read()
 | |
| 
 | |
|     def _gen_init(self, buf):
 | |
|         if self.args:
 | |
|             argtuple = '(' in self.args
 | |
|             args = self.args if not argtuple else ''.join(self.argnames)
 | |
|             print >> buf, "    def __init__(self, %s, lineno=None):" % args
 | |
|         else:
 | |
|             print >> buf, "    def __init__(self, lineno=None):"
 | |
|         if self.argnames:
 | |
|             if argtuple:
 | |
|                 for idx, name in enumerate(self.argnames):
 | |
|                     print >> buf, "        self.%s = %s[%s]" % (name, args, idx)
 | |
|             else:
 | |
|                 for name in self.argnames:
 | |
|                     print >> buf, "        self.%s = %s" % (name, name)
 | |
|         print >> buf, "        self.lineno = lineno"
 | |
|         # Copy the lines in self.init, indented four spaces.  The rstrip()
 | |
|         # business is to get rid of the four spaces if line happens to be
 | |
|         # empty, so that reindent.py is happy with the output.
 | |
|         for line in self.init:
 | |
|             print >> buf, ("    " + line).rstrip()
 | |
| 
 | |
|     def _gen_getChildren(self, buf):
 | |
|         print >> buf, "    def getChildren(self):"
 | |
|         if len(self.argnames) == 0:
 | |
|             print >> buf, "        return ()"
 | |
|         else:
 | |
|             if self.hardest_arg < P_NESTED:
 | |
|                 clist = COMMA.join(["self.%s" % c
 | |
|                                     for c in self.argnames])
 | |
|                 if self.nargs == 1:
 | |
|                     print >> buf, "        return %s," % clist
 | |
|                 else:
 | |
|                     print >> buf, "        return %s" % clist
 | |
|             else:
 | |
|                 if len(self.argnames) == 1:
 | |
|                     print >> buf, "        return tuple(flatten(self.%s))" % self.argnames[0]
 | |
|                 else:
 | |
|                     print >> buf, "        children = []"
 | |
|                     template = "        children.%s(%sself.%s%s)"
 | |
|                     for name in self.argnames:
 | |
|                         if self.argprops[name] == P_NESTED:
 | |
|                             print >> buf, template % ("extend", "flatten(",
 | |
|                                                       name, ")")
 | |
|                         else:
 | |
|                             print >> buf, template % ("append", "", name, "")
 | |
|                     print >> buf, "        return tuple(children)"
 | |
| 
 | |
|     def _gen_getChildNodes(self, buf):
 | |
|         print >> buf, "    def getChildNodes(self):"
 | |
|         if len(self.argnames) == 0:
 | |
|             print >> buf, "        return ()"
 | |
|         else:
 | |
|             if self.hardest_arg < P_NESTED:
 | |
|                 clist = ["self.%s" % c
 | |
|                          for c in self.argnames
 | |
|                          if self.argprops[c] == P_NODE]
 | |
|                 if len(clist) == 0:
 | |
|                     print >> buf, "        return ()"
 | |
|                 elif len(clist) == 1:
 | |
|                     print >> buf, "        return %s," % clist[0]
 | |
|                 else:
 | |
|                     print >> buf, "        return %s" % COMMA.join(clist)
 | |
|             else:
 | |
|                 print >> buf, "        nodelist = []"
 | |
|                 template = "        nodelist.%s(%sself.%s%s)"
 | |
|                 for name in self.argnames:
 | |
|                     if self.argprops[name] == P_NONE:
 | |
|                         tmp = ("        if self.%s is not None:\n"
 | |
|                                "            nodelist.append(self.%s)")
 | |
|                         print >> buf, tmp % (name, name)
 | |
|                     elif self.argprops[name] == P_NESTED:
 | |
|                         print >> buf, template % ("extend", "flatten_nodes(",
 | |
|                                                   name, ")")
 | |
|                     elif self.argprops[name] == P_NODE:
 | |
|                         print >> buf, template % ("append", "", name, "")
 | |
|                 print >> buf, "        return tuple(nodelist)"
 | |
| 
 | |
|     def _gen_repr(self, buf):
 | |
|         print >> buf, "    def __repr__(self):"
 | |
|         if self.argnames:
 | |
|             fmt = COMMA.join(["%s"] * self.nargs)
 | |
|             if '(' in self.args:
 | |
|                 fmt = '(%s)' % fmt
 | |
|             vals = ["repr(self.%s)" % name for name in self.argnames]
 | |
|             vals = COMMA.join(vals)
 | |
|             if self.nargs == 1:
 | |
|                 vals = vals + ","
 | |
|             print >> buf, '        return "%s(%s)" %% (%s)' % \
 | |
|                   (self.name, fmt, vals)
 | |
|         else:
 | |
|             print >> buf, '        return "%s()"' % self.name
 | |
| 
 | |
| rx_init = re.compile('init\((.*)\):')
 | |
| 
 | |
| def parse_spec(file):
 | |
|     classes = {}
 | |
|     cur = None
 | |
|     for line in fileinput.input(file):
 | |
|         if line.strip().startswith('#'):
 | |
|             continue
 | |
|         mo = rx_init.search(line)
 | |
|         if mo is None:
 | |
|             if cur is None:
 | |
|                 # a normal entry
 | |
|                 try:
 | |
|                     name, args = line.split(':')
 | |
|                 except ValueError:
 | |
|                     continue
 | |
|                 classes[name] = NodeInfo(name, args)
 | |
|                 cur = None
 | |
|             else:
 | |
|                 # some code for the __init__ method
 | |
|                 cur.init.append(line)
 | |
|         else:
 | |
|             # some extra code for a Node's __init__ method
 | |
|             name = mo.group(1)
 | |
|             cur = classes[name]
 | |
|     return sorted(classes.values(), key=lambda n: n.name)
 | |
| 
 | |
| def main():
 | |
|     prologue, epilogue = load_boilerplate(sys.argv[-1])
 | |
|     print prologue
 | |
|     print
 | |
|     classes = parse_spec(SPEC)
 | |
|     for info in classes:
 | |
|         print info.gen_source()
 | |
|     print epilogue
 | |
| 
 | |
| if __name__ == "__main__":
 | |
|     main()
 | |
|     sys.exit(0)
 | |
| 
 | |
| ### PROLOGUE
 | |
| """Python abstract syntax node definitions
 | |
| 
 | |
| This file is automatically generated by Tools/compiler/astgen.py
 | |
| """
 | |
| from consts import CO_VARARGS, CO_VARKEYWORDS
 | |
| 
 | |
| def flatten(seq):
 | |
|     l = []
 | |
|     for elt in seq:
 | |
|         t = type(elt)
 | |
|         if t is tuple or t is list:
 | |
|             for elt2 in flatten(elt):
 | |
|                 l.append(elt2)
 | |
|         else:
 | |
|             l.append(elt)
 | |
|     return l
 | |
| 
 | |
| def flatten_nodes(seq):
 | |
|     return [n for n in flatten(seq) if isinstance(n, Node)]
 | |
| 
 | |
| nodes = {}
 | |
| 
 | |
| class Node:
 | |
|     """Abstract base class for ast nodes."""
 | |
|     def getChildren(self):
 | |
|         pass # implemented by subclasses
 | |
|     def __iter__(self):
 | |
|         for n in self.getChildren():
 | |
|             yield n
 | |
|     def asList(self): # for backwards compatibility
 | |
|         return self.getChildren()
 | |
|     def getChildNodes(self):
 | |
|         pass # implemented by subclasses
 | |
| 
 | |
| class EmptyNode(Node):
 | |
|     pass
 | |
| 
 | |
| class Expression(Node):
 | |
|     # Expression is an artificial node class to support "eval"
 | |
|     nodes["expression"] = "Expression"
 | |
|     def __init__(self, node):
 | |
|         self.node = node
 | |
| 
 | |
|     def getChildren(self):
 | |
|         return self.node,
 | |
| 
 | |
|     def getChildNodes(self):
 | |
|         return self.node,
 | |
| 
 | |
|     def __repr__(self):
 | |
|         return "Expression(%s)" % (repr(self.node))
 | |
| 
 | |
| ### EPILOGUE
 | |
| for name, obj in globals().items():
 | |
|     if isinstance(obj, type) and issubclass(obj, Node):
 | |
|         nodes[name.lower()] = obj
 |