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
		
			
				
	
	
		
			114 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			114 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| from compiler import ast
 | |
| 
 | |
| # XXX should probably rename ASTVisitor to ASTWalker
 | |
| # XXX can it be made even more generic?
 | |
| 
 | |
| class ASTVisitor:
 | |
|     """Performs a depth-first walk of the AST
 | |
| 
 | |
|     The ASTVisitor will walk the AST, performing either a preorder or
 | |
|     postorder traversal depending on which method is called.
 | |
| 
 | |
|     methods:
 | |
|     preorder(tree, visitor)
 | |
|     postorder(tree, visitor)
 | |
|         tree: an instance of ast.Node
 | |
|         visitor: an instance with visitXXX methods
 | |
| 
 | |
|     The ASTVisitor is responsible for walking over the tree in the
 | |
|     correct order.  For each node, it checks the visitor argument for
 | |
|     a method named 'visitNodeType' where NodeType is the name of the
 | |
|     node's class, e.g. Class.  If the method exists, it is called
 | |
|     with the node as its sole argument.
 | |
| 
 | |
|     The visitor method for a particular node type can control how
 | |
|     child nodes are visited during a preorder walk.  (It can't control
 | |
|     the order during a postorder walk, because it is called _after_
 | |
|     the walk has occurred.)  The ASTVisitor modifies the visitor
 | |
|     argument by adding a visit method to the visitor; this method can
 | |
|     be used to visit a child node of arbitrary type.
 | |
|     """
 | |
| 
 | |
|     VERBOSE = 0
 | |
| 
 | |
|     def __init__(self):
 | |
|         self.node = None
 | |
|         self._cache = {}
 | |
| 
 | |
|     def default(self, node, *args):
 | |
|         for child in node.getChildNodes():
 | |
|             self.dispatch(child, *args)
 | |
| 
 | |
|     def dispatch(self, node, *args):
 | |
|         self.node = node
 | |
|         klass = node.__class__
 | |
|         meth = self._cache.get(klass, None)
 | |
|         if meth is None:
 | |
|             className = klass.__name__
 | |
|             meth = getattr(self.visitor, 'visit' + className, self.default)
 | |
|             self._cache[klass] = meth
 | |
| ##        if self.VERBOSE > 0:
 | |
| ##            className = klass.__name__
 | |
| ##            if self.VERBOSE == 1:
 | |
| ##                if meth == 0:
 | |
| ##                    print "dispatch", className
 | |
| ##            else:
 | |
| ##                print "dispatch", className, (meth and meth.__name__ or '')
 | |
|         return meth(node, *args)
 | |
| 
 | |
|     def preorder(self, tree, visitor, *args):
 | |
|         """Do preorder walk of tree using visitor"""
 | |
|         self.visitor = visitor
 | |
|         visitor.visit = self.dispatch
 | |
|         self.dispatch(tree, *args) # XXX *args make sense?
 | |
| 
 | |
| class ExampleASTVisitor(ASTVisitor):
 | |
|     """Prints examples of the nodes that aren't visited
 | |
| 
 | |
|     This visitor-driver is only useful for development, when it's
 | |
|     helpful to develop a visitor incrementally, and get feedback on what
 | |
|     you still have to do.
 | |
|     """
 | |
|     examples = {}
 | |
| 
 | |
|     def dispatch(self, node, *args):
 | |
|         self.node = node
 | |
|         meth = self._cache.get(node.__class__, None)
 | |
|         className = node.__class__.__name__
 | |
|         if meth is None:
 | |
|             meth = getattr(self.visitor, 'visit' + className, 0)
 | |
|             self._cache[node.__class__] = meth
 | |
|         if self.VERBOSE > 1:
 | |
|             print "dispatch", className, (meth and meth.__name__ or '')
 | |
|         if meth:
 | |
|             meth(node, *args)
 | |
|         elif self.VERBOSE > 0:
 | |
|             klass = node.__class__
 | |
|             if klass not in self.examples:
 | |
|                 self.examples[klass] = klass
 | |
|                 print
 | |
|                 print self.visitor
 | |
|                 print klass
 | |
|                 for attr in dir(node):
 | |
|                     if attr[0] != '_':
 | |
|                         print "\t", "%-12.12s" % attr, getattr(node, attr)
 | |
|                 print
 | |
|             return self.default(node, *args)
 | |
| 
 | |
| # XXX this is an API change
 | |
| 
 | |
| _walker = ASTVisitor
 | |
| def walk(tree, visitor, walker=None, verbose=None):
 | |
|     if walker is None:
 | |
|         walker = _walker()
 | |
|     if verbose is not None:
 | |
|         walker.VERBOSE = verbose
 | |
|     walker.preorder(tree, visitor)
 | |
|     return walker.visitor
 | |
| 
 | |
| def dumpNode(node):
 | |
|     print node.__class__
 | |
|     for attr in dir(node):
 | |
|         if attr[0] != '_':
 | |
|             print "\t", "%-10.10s" % attr, getattr(node, attr)
 |