2016-11-05 32 views
1

我正在使用PLY解析包含嵌套块的文件。 典型:Python 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_nodesp_node中输入什么信息才能建立有效的AST?谢谢。

回答

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) 
+0

不幸的是,分析器干不允许像'p [0] = Node(p [3],p [0])'这样的东西。此外,如果信息在创建期间尚未收集,我不会在创建AST后看到如何做到这一点。 什么也让我卡住是规则'节点:节点节点|节点“意味着在这个层次上产生的所有节点规则必须是AST中的兄弟节点,并且如果没有”范围“概念,似乎很难做到这一点,因为在解析器级别存在递归,并且在AST级别上这些节点必须处于相同的深度。 – ibi0tux

+0

我已经更新了我的答案,应该做你想做的。告诉我你是否还有一些问题。 –

+0

好吧,这个作品完美,你保存了我的周末,非常感谢你! 'p [0] = [p [1]] + p [2]'符号正是我所错过的。 – ibi0tux