diff options
author | Guido van Rossum <guido@python.org> | 2007-05-14 22:03:55 (GMT) |
---|---|---|
committer | Guido van Rossum <guido@python.org> | 2007-05-14 22:03:55 (GMT) |
commit | a8add0ec5ef05c26e1641b8310b65ddd75c0fec3 (patch) | |
tree | 1626110463ca617ab105990ee1923f6ee65c7476 /Tools/compiler/astgen.py | |
parent | 827b055ffe8060ac229cda8d75eb24176cc697c0 (diff) | |
download | cpython-a8add0ec5ef05c26e1641b8310b65ddd75c0fec3.zip cpython-a8add0ec5ef05c26e1641b8310b65ddd75c0fec3.tar.gz cpython-a8add0ec5ef05c26e1641b8310b65ddd75c0fec3.tar.bz2 |
Merged revisions 55270-55324 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/branches/p3yk
........
r55271 | fred.drake | 2007-05-11 10:14:47 -0700 (Fri, 11 May 2007) | 3 lines
remove jpeg, panel libraries for SGI; there is more IRIX stuff left over,
I guess that should be removed too, but will leave for someone who is sure
........
r55280 | fred.drake | 2007-05-11 19:11:37 -0700 (Fri, 11 May 2007) | 1 line
remove mention of file that has been removed
........
r55301 | brett.cannon | 2007-05-13 17:38:05 -0700 (Sun, 13 May 2007) | 4 lines
Remove rexec and Bastion from the stdlib. This also eliminates the need for
f_restricted on frames. This in turn negates the need for
PyEval_GetRestricted() and PyFrame_IsRestricted().
........
r55303 | brett.cannon | 2007-05-13 19:22:22 -0700 (Sun, 13 May 2007) | 2 lines
Remove the md5 and sha modules.
........
r55305 | george.yoshida | 2007-05-13 19:45:55 -0700 (Sun, 13 May 2007) | 2 lines
fix markup
........
r55306 | neal.norwitz | 2007-05-13 19:47:57 -0700 (Sun, 13 May 2007) | 1 line
Get the doc building again after some removals.
........
r55307 | neal.norwitz | 2007-05-13 19:50:45 -0700 (Sun, 13 May 2007) | 1 line
Get test_pyclbr passing again after getstatus was removed from commands. This "test case" was weird since it was just importing a seemingly random module. Remove the import
........
r55322 | brett.cannon | 2007-05-14 14:09:20 -0700 (Mon, 14 May 2007) | 3 lines
Remove the compiler package. Will eventually need a mechanism to byte compile
an AST.
........
Diffstat (limited to 'Tools/compiler/astgen.py')
-rw-r--r-- | Tools/compiler/astgen.py | 292 |
1 files changed, 0 insertions, 292 deletions
diff --git a/Tools/compiler/astgen.py b/Tools/compiler/astgen.py deleted file mode 100644 index 601d2bd..0000000 --- a/Tools/compiler/astgen.py +++ /dev/null @@ -1,292 +0,0 @@ -"""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 getopt -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("class %s(Node):" % self.name, file=buf) - self._gen_init(buf) - print(file=buf) - self._gen_getChildren(buf) - print(file=buf) - self._gen_getChildNodes(buf) - print(file=buf) - self._gen_repr(buf) - buf.seek(0, 0) - return buf.read() - - def _gen_init(self, buf): - if self.args: - print(" def __init__(self, %s, lineno=None):" % self.args, file=buf) - else: - print(" def __init__(self, lineno=None):", file=buf) - if self.argnames: - for name in self.argnames: - print(" self.%s = %s" % (name, name), file=buf) - print(" self.lineno = lineno", file=buf) - # 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((" " + line).rstrip(), file=buf) - - def _gen_getChildren(self, buf): - print(" def getChildren(self):", file=buf) - if len(self.argnames) == 0: - print(" return ()", file=buf) - else: - if self.hardest_arg < P_NESTED: - clist = COMMA.join(["self.%s" % c - for c in self.argnames]) - if self.nargs == 1: - print(" return %s," % clist, file=buf) - else: - print(" return %s" % clist, file=buf) - else: - if len(self.argnames) == 1: - print(" return tuple(flatten(self.%s))" % self.argnames[0], file=buf) - else: - print(" children = []", file=buf) - template = " children.%s(%sself.%s%s)" - for name in self.argnames: - if self.argprops[name] == P_NESTED: - print(template % ("extend", "flatten(", - name, ")"), file=buf) - else: - print(template % ("append", "", name, ""), file=buf) - print(" return tuple(children)", file=buf) - - def _gen_getChildNodes(self, buf): - print(" def getChildNodes(self):", file=buf) - if len(self.argnames) == 0: - print(" return ()", file=buf) - 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(" return ()", file=buf) - elif len(clist) == 1: - print(" return %s," % clist[0], file=buf) - else: - print(" return %s" % COMMA.join(clist), file=buf) - else: - print(" nodelist = []", file=buf) - 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(tmp % (name, name), file=buf) - elif self.argprops[name] == P_NESTED: - print(template % ("extend", "flatten_nodes(", - name, ")"), file=buf) - elif self.argprops[name] == P_NODE: - print(template % ("append", "", name, ""), file=buf) - print(" return tuple(nodelist)", file=buf) - - def _gen_repr(self, buf): - print(" def __repr__(self):", file=buf) - 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(' return "%s(%s)" %% (%s)' % \ - (self.name, fmt, vals), file=buf) - else: - print(' return "%s()"' % self.name, file=buf) - -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 compiler.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): - def getChildNodes(self): - return () - def getChildren(self): - return () - -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 |