java-如何使用Python生成AST(以XML表示)的控制流?
作者:互联网
我有XML格式的AST WHILE语言(http://www.program-analysis.com/while.html).目前,我不处理函数调用或递归.我需要为该程序生成控制流.
一个示例程序(//后面的数字表示解析器生成的标签):
begin
x:=1; // 1
z:= 2+x; // 2
x := x+z; // 3
y:=z-x+z; // 4
w:=x+y+z; // 5
while(not (y<z)) { // 12
x:=x+1; // 6
if (w <=x) { // 9
w:= w-x; // 7
}
else {
w:=w+x; // 8
}
z:=z-1; // 10
y:=y+1; // 11
}
x:=z+y; // 13
w:=x; // 14
end
上述程序的AST表示为:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<program>
<assignment label="1" variable="x">
<value>
<number value="1"/>
</value>
</assignment>
<assignment label="2" variable="z">
<value>
<binary operator="+">
<left>
<number value="2"/>
</left>
<right>
<variable name="x"/>
</right>
</binary>
</value>
</assignment>
<assignment label="3" variable="x">
<value>
<binary operator="+">
<left>
<variable name="x"/>
</left>
<right>
<variable name="z"/>
</right>
</binary>
</value>
</assignment>
<assignment label="4" variable="y">
<value>
<binary operator="+">
<left>
<binary operator="-">
<left>
<variable name="z"/>
</left>
<right>
<variable name="x"/>
</right>
</binary>
</left>
<right>
<variable name="z"/>
</right>
</binary>
</value>
</assignment>
<assignment label="5" variable="w">
<value>
<binary operator="+">
<left>
<binary operator="+">
<left>
<variable name="x"/>
</left>
<right>
<variable name="y"/>
</right>
</binary>
</left>
<right>
<variable name="z"/>
</right>
</binary>
</value>
</assignment>
<while condition-label="12">
<condition>
<not>
<binary operator="<">
<left>
<variable name="y"/>
</left>
<right>
<variable name="z"/>
</right>
</binary>
</not>
</condition>
<body>
<assignment label="6" variable="x">
<value>
<binary operator="+">
<left>
<variable name="x"/>
</left>
<right>
<number value="1"/>
</right>
</binary>
</value>
</assignment>
<if condition-label="9">
<condition>
<binary operator="<=">
<left>
<variable name="w"/>
</left>
<right>
<variable name="x"/>
</right>
</binary>
</condition>
<true-branch>
<assignment label="7" variable="w">
<value>
<binary operator="-">
<left>
<variable name="w"/>
</left>
<right>
<variable name="x"/>
</right>
</binary>
</value>
</assignment>
</true-branch>
<false-branch>
<assignment label="8" variable="w">
<value>
<binary operator="+">
<left>
<variable name="w"/>
</left>
<right>
<variable name="x"/>
</right>
</binary>
</value>
</assignment>
</false-branch>
</if>
<assignment label="10" variable="z">
<value>
<binary operator="-">
<left>
<variable name="z"/>
</left>
<right>
<number value="1"/>
</right>
</binary>
</value>
</assignment>
<assignment label="11" variable="y">
<value>
<binary operator="+">
<left>
<variable name="y"/>
</left>
<right>
<number value="1"/>
</right>
</binary>
</value>
</assignment>
</body>
</while>
<assignment label="13" variable="x">
<value>
<binary operator="+">
<left>
<variable name="z"/>
</left>
<right>
<variable name="y"/>
</right>
</binary>
</value>
</assignment>
<assignment label="14" variable="w">
<value>
<variable name="x"/>
</value>
</assignment>
</program>
我需要生成程序的控制流.
上述程序的控制流程如下:
1->2,
2->3,
3->4,
4->5,
5->12,
12->6,
12->13,
11->12,
6->9 ,
9->7,
9->8,
7->10,
8->10,
10->11,
13->14.
注意:while可以嵌套if语句,而while语句可以嵌套,反之亦然.我最好在Python / Java / C中寻找通用解决方案.
提前致谢,
罗伊
解决方法:
这是一种可能的解决方案.它以与示例稍有不同的顺序返回弧,但这没关系.
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和if的实现都有些拙劣,它将落在某些语法错误上.
标签:abstract-syntax-tree,static-analysis,xml,python,java 来源: https://codeday.me/bug/20191201/2082994.html