Вот одно из возможных решений.Он возвращает дуги в несколько ином порядке к вашему примеру, но это не должно иметь значения.
from xml.dom import minidom
dom = minidom.parse('test1.wl.xml')
def print_arcs(from_list, to_list):
'''
Print arcs from every member of the from list, to every member of
the to list
'''
for source in from_list:
for target in to_list:
print "%s -> %s" % (source, target)
def parse(node, came_from):
'''
Descend an XML structure representing an AST
'''
if not node:
return came_from
if node.nodeName=="#text":
return parse(node.nextSibling, came_from)
if node.nodeName=="program":
return parse(node.firstChild, came_from)
if node.nodeName=="assignment":
this = node.getAttribute('label')
print_arcs(came_from, [this])
return parse(node.nextSibling, [this])
if node.nodeName=="while":
loop_start = node.getAttribute('condition-label')
print_arcs(came_from, [loop_start])
next = [loop_start]
for s in node.childNodes:
if s.nodeName=="body":
loop_end = parse(s, [loop_start])
print_arcs(loop_end, [loop_start])
return parse(node.nextSibling, next)
if node.nodeName=="if":
if_start = node.getAttribute('condition-label')
print_arcs(came_from, [if_start])
next = []
for s in node.childNodes:
if s.nodeName=="#text":
continue
item = parse(s, [if_start])
if item:
next.extend(item)
return parse(node.nextSibling, next)
if node.nodeName=="condition":
return None
if node.nodeName=="true-branch":
return parse(node.firstChild, came_from)
if node.nodeName=="false-branch":
return parse(node.firstChild, came_from)
if node.nodeName=="body":
return parse(node.firstChild, came_from)
parse(dom.firstChild, [])
Это повторяется через структуру AST, и его вывод зависит от типа встреченного узла.Присвоение просто выводит дуги из предыдущего узла (ов) в текущий узел;if
нужны дуги для двух возможностей, а while
нужны дуги, представляющие цикл и возможный провал.Данный код хранит список того, откуда могло произойти выполнение, чтобы в конечном итоге оказаться в текущем местоположении.Функция parse
возвращает местоположение, в котором заканчивается текущий блок.
Обратите внимание, что реализация как while
, так и if
здесь немного ошибочна, и она может упасть при определенных синтаксических ошибках..