9

I'm playing with python ast (abstract syntax tree).

I wrote the following and it visited all nodes of the AST.

import ast

class Py2Neko(ast.NodeVisitor):
    def generic_visit(self, node):
              print type(node).__name__
              ast.NodeVisitor.generic_visit(self, node)

       def visit_Name(self, node):
              print 'Name :', node.id

       def visit_Num(self, node):
              print 'Num :', node.__dict__['n']

       def visit_Str(self, node):
              print "Str :", node.s

if __name__ == '__main__':

    node = ast.parse("a = 1 + 2")

    print ast.dump(node)

    v = Py2Neko()
    v.visit(node)

Then added some methods to Py2Neko class

def visit_Print(self, node):
    print "Print :"

def visit_Assign(self, node):
    print "Assign :"

def visit_Expr(self, node):
    print "Expr :"

But then when it encounters a "print" statement or an assignement or an expression it seems that it stops and isn't going further.

It outputs:

Module(body=[Assign(targets=[Name(id='a', ctx=Store())], value=BinOp(left=Num(n=1), op=Add(),       right=Num(n=2)))])
Module
Assign :

Can someone tell me what I did wrong.

I'm using Python 2.6.6

Sanjay Manohar
  • 6,920
  • 3
  • 35
  • 58
narke
  • 103
  • 1
  • 1
  • 4

2 Answers2

11

Since your visit_Assign method does not explicitly process the child nodes of the Assign node, traversal of the syntax tree stops there.

If you have a look at the NodeVisitor.generic_visit method in the implementation of ast.py, you'll see that it loops through the children of the current node. So, you can explicitly call the base class generic_visit method from each of your methods that needs to process children:

import ast

class Py2Neko(ast.NodeVisitor):
    def generic_visit(self, node):
        print type(node).__name__
        ast.NodeVisitor.generic_visit(self, node)

    def visit_Name(self, node):
        print 'Name :', node.id

    def visit_Num(self, node):
        print 'Num :', node.__dict__['n']

    def visit_Str(self, node):
        print "Str :", node.s

    def visit_Print(self, node):
        print "Print :"
        ast.NodeVisitor.generic_visit(self, node)

    def visit_Assign(self, node):
        print "Assign :"
        ast.NodeVisitor.generic_visit(self, node)

    def visit_Expr(self, node):
        print "Expr :"
        ast.NodeVisitor.generic_visit(self, node)

if __name__ == '__main__':
    node = ast.parse("a = 1 + 2")

    print ast.dump(node)

    v = Py2Neko()
    v.visit(node)
Luke Moore
  • 685
  • 5
  • 7
4

For non-terminal nodes, your visit function has to visit the children. See Simple example of how to use ast.NodeVisitor? for some more information.

Community
  • 1
  • 1
Ned Batchelder
  • 364,293
  • 75
  • 561
  • 662
  • D'oh - I was thinking of this but somehow (irrationally) assumed the `NodeVisitor` would handle this on it's own. –  Feb 09 '11 at 17:02
  • I saw the example you provide but how to specify to visit the children? For example here: http://dev.pocoo.org/hg/sandbox/file/98ce1ce17c7c/ast/codegen.py they have visit_Print() and others and it seems to work but not for me. – narke Feb 09 '11 at 17:15