diff options
author | Ori Bernstein <ori@eigenstate.org> | 2021-06-14 00:00:37 +0000 |
---|---|---|
committer | Ori Bernstein <ori@eigenstate.org> | 2021-06-14 00:00:37 +0000 |
commit | a73a964e51247ed169d322c725a3a18859f109a3 (patch) | |
tree | 3f752d117274d444bda44e85609aeac1acf313f3 /sys/src/cmd/python/Tools/compiler/astgen.py | |
parent | e64efe273fcb921a61bf27d33b230c4e64fcd425 (diff) |
python, hg: tow outside the environment.
they've served us well, and can ride off into the sunset.
Diffstat (limited to 'sys/src/cmd/python/Tools/compiler/astgen.py')
-rw-r--r-- | sys/src/cmd/python/Tools/compiler/astgen.py | 289 |
1 files changed, 0 insertions, 289 deletions
diff --git a/sys/src/cmd/python/Tools/compiler/astgen.py b/sys/src/cmd/python/Tools/compiler/astgen.py deleted file mode 100644 index 59b98f2b0..000000000 --- a/sys/src/cmd/python/Tools/compiler/astgen.py +++ /dev/null @@ -1,289 +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 >> 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: - print >> buf, " def __init__(self, %s, lineno=None):" % self.args - else: - print >> buf, " def __init__(self, lineno=None):" - if self.argnames: - 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 |