Посещение узлов в синтаксическом дереве с помощью модуля Python ast - PullRequest
9 голосов
/ 09 февраля 2011

Я играю с python ast (абстрактное синтаксическое дерево).

Я написал следующее, и оно посетило все узлы 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)

Затем добавил несколько методов в класс Py2Neko

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

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

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

Но тогда, когда он сталкивается с оператором "print", присваиванием или выражением, кажется, что он останавливается и не идет дальше.

Выводит:

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

Может кто-нибудь сказать мне, что я сделал не так.

Я использую Python 2.6.6

Ответы [ 2 ]

11 голосов
/ 09 февраля 2011

Поскольку ваш метод visit_Assign явно не обрабатывает дочерние узлы узла Assign, обход синтаксического дерева на этом останавливается.

Если вы посмотрите на метод NodeVisitor.generic_visit в реализации ast.py, вы увидите, что он проходит через дочерние элементы текущего узла. Таким образом, вы можете явно вызывать метод базового класса generic_visit для каждого из ваших методов, которые должны обрабатывать дочерние элементы:

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)
4 голосов
/ 09 февраля 2011

Для нетерминальных узлов ваша функция посещения должна посещать детей. См. Простой пример использования ast.NodeVisitor? для получения дополнительной информации.

...