1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/libxml2macro.py Fri Jan 14 15:39:03 2005 +0000
1.3 @@ -0,0 +1,78 @@
1.4 +#!/usr/bin/env python
1.5 +
1.6 +import compiler
1.7 +
1.8 +def process_nodes(root_node, prefix):
1.9 +
1.10 + """
1.11 + Under the 'root_node', process all suitable expression nodes which employ
1.12 + Name nodes using the given 'prefix'.
1.13 + """
1.14 +
1.15 + for node in root_node.getChildNodes():
1.16 + # Identify suitable names and add such nodes
1.17 + if isinstance(node, compiler.ast.CallFunc):
1.18 + process_callfunc(node, prefix)
1.19 + elif isinstance(node, compiler.ast.Getattr):
1.20 + process_getattr(node, prefix, root_node)
1.21 + else:
1.22 + process_nodes(node, prefix)
1.23 +
1.24 +def process_callfunc(node, prefix):
1.25 + # Check the target.
1.26 + target = node.node
1.27 + if isinstance(target, compiler.ast.Getattr):
1.28 + process_getattr(target, prefix, node)
1.29 + else:
1.30 + process_nodes(node, prefix)
1.31 +
1.32 +def process_getattr(node, prefix, parent):
1.33 + # Check the target.
1.34 + target = node.expr
1.35 + if isinstance(target, compiler.ast.Name) and target.name.startswith(prefix):
1.36 +
1.37 + # Replace CallFunc plus Getattr occurrences:
1.38 + # node.attr(args) -> Node_attr(node, args)
1.39 +
1.40 + if isinstance(parent, compiler.ast.CallFunc):
1.41 + parent.node = compiler.ast.Name("Node_%s" % node.attrname)
1.42 + parent.args.insert(0, compiler.ast.Name(target.name))
1.43 +
1.44 + # Replace plain Getattr nodes:
1.45 + # node.attr -> Node_attr(node)
1.46 + # NOTE: Nasty but necessary rewiring of the parent node required.
1.47 +
1.48 + else:
1.49 + replacement = compiler.ast.CallFunc(
1.50 + compiler.ast.Name("Node_%s" % node.attrname),
1.51 + [node.expr]
1.52 + )
1.53 + for key, value in parent.__dict__.items():
1.54 + # Detect lists.
1.55 + try:
1.56 + if node in value:
1.57 + index = value.index(node)
1.58 + value[index] = replacement
1.59 + except TypeError:
1.60 + if value is node:
1.61 + parent.__dict__[key] = replacement
1.62 + else:
1.63 + process_nodes(node, prefix)
1.64 +
1.65 +def process_file(filename, prefix="x2_"):
1.66 +
1.67 + """
1.68 + Process the module given by the specified 'filename'. The optional special
1.69 + 'prefix' marks those variables to be processed.
1.70 + """
1.71 +
1.72 + # Open the module as an AST.
1.73 +
1.74 + module = compiler.parseFile(filename)
1.75 +
1.76 + # Find references to special variables.
1.77 +
1.78 + process_nodes(module, prefix)
1.79 + return module
1.80 +
1.81 +# vim: tabstop=4 expandtab shiftwidth=4