2016-11-05 1 views
1

J'utilise PLY pour analyser les fichiers contenant des blocs imbriqués. En général:Python PLY analyse: portée de la définition

a { 
    b { 

    } 
    c { 
     d { 

     } 
    }  
} 

J'utilise une grammaire simple comme ceci:

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 

Je voudrais savoir que je pourrais être en mesure d'accéder à un nœud « parent » dans l'analyseur. En d'autres termes comment puis-je construire l'AST afin que je puisse retrouver dans mon exemple que d est un enfant de c qui est lui-même enfant de a puisque je dois voir la règle parente dans l'analyseur.

Que dois-je mettre dans p_nodes et p_node de sorte qu'un AST valide peut être construit? Merci.

Répondre

2

Nous aurions besoin de votre classe Node, mais je suppose que c'est quelque chose comme:

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

Ensuite, votre analyseur pourrait ressembler à ça:

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 

Ensuite, vous aurez un vrai AST, avec chaque noeud contenant une référence à tous ses enfants. Finalement, si vous voulez que votre nœud ait une référence à leur parent, vous devez parcourir tous les AST de la racine et le définir comme un attribut sur tous ses enfants, puis faire de même sur ses enfants. .

pour ce faire, changer votre Node classe pour ressembler à ceci:

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

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

et exécuter une fonction similaire à celle-ci:

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

Malheureusement, l'analyseur ne Ne pas autoriser des choses comme 'p [0] = Node (p [3], p [0])'. De plus, je ne vois pas non plus comment je pourrais le faire après la création de l'AST si l'information n'a pas été collectée lors de sa création. Ce qui me bloque également, c'est que la règle 'nodes: node nodes | node' implique que toutes les règles 'node' produites à ce niveau doivent être des nœuds frères dans l'AST et il semble difficile de le faire sans notion de" scope "car au niveau de l'analyseur il y a une récursion, et au niveau AST ces les nœuds doivent être à la même profondeur. – ibi0tux

+0

J'ai mis à jour ma réponse, cela devrait faire ce que vous voulez. Dites-moi si vous avez encore des questions. –

+0

Ok ça fonctionne parfaitement, tu as sauvé mon week-end, merci beaucoup! La notation 'p [0] = [p [1]] + p [2]' était exactement ce qui me manquait. – ibi0tux