Python PLY解析:定义范围

时间:2016-11-05 16:09:54

标签: python parsing grammar abstract-syntax-tree

我正在使用PLY来解析包含嵌套块的文件。 通常:

a {
    b {

    }
    c {
        d {

        }
    }    
}

我使用的是一个简单的语法:

def p_nodes(p):
    '''
    nodes : node nodes
          | node
    '''
    # ??

def p_node(p):
    '''
    node : IDENTIFIER OPEN_CURLY_BRACE node_çontent CLOSE_CURLY_BRACE
    '''
    p[0] = Node(p[3])#FIXME?

def p_node_content(p):
    '''
    node_content : nodes
                 |
    '''
    if len(p) > 1:
        p[0] = p[1]
    else
        p[0] = None

我想知道我能够访问解析器中的“父”节点。换句话说,如何构建AST以便我可以在我的示例中检索dc的孩子,a本身就是p_nodes的孩子,因为我必须能看到父规则在解析器中。

我应该在p_node和{{1}}中放置什么才能构建有效的AST?感谢。

1 个答案:

答案 0 :(得分:2)

我们需要你的Node课程,但我认为它类似于:

class Node:
    def __init__(self, children):
        self.children = children
        self.type = None

然后你的解析器看起来像那样:

def p_nodes(p):
    '''
    nodes : node nodes
          | node
    '''
    if len(p) > 2:
        p[0] = [p[1]] + p[2]
    else
        p[0] = [p[1]] 

def p_node(p):
    '''
    node : IDENTIFIER OPEN_CURLY_BRACE node_content CLOSE_CURLY_BRACE
    '''
    p[0] = Node(p[3])

def p_node_content(p):
    '''
    node_content : nodes
                 |
    '''
    if len(p) > 1:
        p[0] = p[1]
    else
        p[0] = None

然后你将拥有一个真正的AST,每个节点都包含对其所有孩子的引用。

最后,如果你希望你的节点有一个对它们父节点的引用,你必须从根节点迭代所有的AST并将其设置为所有子节点的属性,然后在它的子节点上执行相同操作......

为此,请将您的Node课程更改为:

class Node:
    def __init__(self, children):
        self.children = children
        self.parent = None

    def set_parent(self, parent):
        self.parent = parent

并运行与此类似的功能:

def set_parent_to_AST(root_node):
    for node in root_node.children:
        node.set_parent(root_node)
        set_parent_to_AST(node)