symbian-qemu-0.9.1-12/python-2.6.1/Lib/compiler/visitor.py
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 from compiler import ast
       
     2 
       
     3 # XXX should probably rename ASTVisitor to ASTWalker
       
     4 # XXX can it be made even more generic?
       
     5 
       
     6 class ASTVisitor:
       
     7     """Performs a depth-first walk of the AST
       
     8 
       
     9     The ASTVisitor will walk the AST, performing either a preorder or
       
    10     postorder traversal depending on which method is called.
       
    11 
       
    12     methods:
       
    13     preorder(tree, visitor)
       
    14     postorder(tree, visitor)
       
    15         tree: an instance of ast.Node
       
    16         visitor: an instance with visitXXX methods
       
    17 
       
    18     The ASTVisitor is responsible for walking over the tree in the
       
    19     correct order.  For each node, it checks the visitor argument for
       
    20     a method named 'visitNodeType' where NodeType is the name of the
       
    21     node's class, e.g. Class.  If the method exists, it is called
       
    22     with the node as its sole argument.
       
    23 
       
    24     The visitor method for a particular node type can control how
       
    25     child nodes are visited during a preorder walk.  (It can't control
       
    26     the order during a postorder walk, because it is called _after_
       
    27     the walk has occurred.)  The ASTVisitor modifies the visitor
       
    28     argument by adding a visit method to the visitor; this method can
       
    29     be used to visit a child node of arbitrary type.
       
    30     """
       
    31 
       
    32     VERBOSE = 0
       
    33 
       
    34     def __init__(self):
       
    35         self.node = None
       
    36         self._cache = {}
       
    37 
       
    38     def default(self, node, *args):
       
    39         for child in node.getChildNodes():
       
    40             self.dispatch(child, *args)
       
    41 
       
    42     def dispatch(self, node, *args):
       
    43         self.node = node
       
    44         klass = node.__class__
       
    45         meth = self._cache.get(klass, None)
       
    46         if meth is None:
       
    47             className = klass.__name__
       
    48             meth = getattr(self.visitor, 'visit' + className, self.default)
       
    49             self._cache[klass] = meth
       
    50 ##        if self.VERBOSE > 0:
       
    51 ##            className = klass.__name__
       
    52 ##            if self.VERBOSE == 1:
       
    53 ##                if meth == 0:
       
    54 ##                    print "dispatch", className
       
    55 ##            else:
       
    56 ##                print "dispatch", className, (meth and meth.__name__ or '')
       
    57         return meth(node, *args)
       
    58 
       
    59     def preorder(self, tree, visitor, *args):
       
    60         """Do preorder walk of tree using visitor"""
       
    61         self.visitor = visitor
       
    62         visitor.visit = self.dispatch
       
    63         self.dispatch(tree, *args) # XXX *args make sense?
       
    64 
       
    65 class ExampleASTVisitor(ASTVisitor):
       
    66     """Prints examples of the nodes that aren't visited
       
    67 
       
    68     This visitor-driver is only useful for development, when it's
       
    69     helpful to develop a visitor incrementally, and get feedback on what
       
    70     you still have to do.
       
    71     """
       
    72     examples = {}
       
    73 
       
    74     def dispatch(self, node, *args):
       
    75         self.node = node
       
    76         meth = self._cache.get(node.__class__, None)
       
    77         className = node.__class__.__name__
       
    78         if meth is None:
       
    79             meth = getattr(self.visitor, 'visit' + className, 0)
       
    80             self._cache[node.__class__] = meth
       
    81         if self.VERBOSE > 1:
       
    82             print "dispatch", className, (meth and meth.__name__ or '')
       
    83         if meth:
       
    84             meth(node, *args)
       
    85         elif self.VERBOSE > 0:
       
    86             klass = node.__class__
       
    87             if not self.examples.has_key(klass):
       
    88                 self.examples[klass] = klass
       
    89                 print
       
    90                 print self.visitor
       
    91                 print klass
       
    92                 for attr in dir(node):
       
    93                     if attr[0] != '_':
       
    94                         print "\t", "%-12.12s" % attr, getattr(node, attr)
       
    95                 print
       
    96             return self.default(node, *args)
       
    97 
       
    98 # XXX this is an API change
       
    99 
       
   100 _walker = ASTVisitor
       
   101 def walk(tree, visitor, walker=None, verbose=None):
       
   102     if walker is None:
       
   103         walker = _walker()
       
   104     if verbose is not None:
       
   105         walker.VERBOSE = verbose
       
   106     walker.preorder(tree, visitor)
       
   107     return walker.visitor
       
   108 
       
   109 def dumpNode(node):
       
   110     print node.__class__
       
   111     for attr in dir(node):
       
   112         if attr[0] != '_':
       
   113             print "\t", "%-10.10s" % attr, getattr(node, attr)