编程语言
首页 > 编程语言> > java-如何使用Python生成AST(以XML表示)的控制流?

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="&lt;">
                    <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="&lt;=">
                        <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