Мой коллега предложил, чтобы я записал шаблон "посетитель" для навигации по AST. Кто-либо может сказать мне больше, как я начал бы писать это?
Насколько я понимаю, каждый Узел в AST имел бы visit()
метод (?), который так или иначе назвать (от где?). Это о завершает мое понимание.
Для упрощения всего предположите, что у меня есть узлы Root
, Expression
, Number
, Op
и дерево похоже на это:
Root
|
Op(+)
/ \
/ \
Number(5) \
Op(*)
/ \
/ \
/ \
Number(2) Number(444)
Может любой думать, как шаблон "посетитель" посетил бы это дерево для создания вывода:
5 + 2 * 444
Спасибо, Boda Cydo.
В Википедии есть отличный обзор того, как работает шаблон Visitor , хотя образец реализации, который они используют, находится на Java. Однако вы можете легко перенести это на Python, не так ли?
По сути, вы хотите реализовать механизм двойной диспетчеризации . Каждый узел в вашем AST должен будет реализовать метод accept ()
(НЕ метод visit ()
).Метод принимает в качестве аргумента объект посетителя. В реализации этого метода accept ()
вы вызываете метод visit ()
объекта посетителя (будет по одному для каждого типа узла AST; в Java вы используйте перегрузку параметров, в Python я полагаю, вы можете использовать разные методы visit _ * ()
). Затем правильный посетитель будет отправлен с правильным типом узла в качестве аргумента.
См. документы для ast.NodeVisitor
, например грубая возможность может быть такой:
import ast
class MyVisitor(ast.NodeVisitor):
def visit_BinaryOp(self, node):
self.visit(node.left)
print node.op,
self.visit(node.right)
def visit_Num(self, node):
print node.n,
конечно, при этом не появляются круглые скобки даже там, где это необходимо, и т.д., так что на самом деле сделано больше работы, но это только начало ;-).