2017-09-16 9 views
1

Mon objectif éventuel est d'appliquer des requêtes sql-where-clause-style pour filtrer les données pandas. Certaines recherches m'ont conduit à la méthode infixNotation de Pyparsing.Pyparsing infixNotation dans un arbre d'analyse: un seul opérateur se retrouve dans l'arbre?

Je trouve un exemple de notation infixe ici: http://nullege.com/codes/show/src%40p%40y%40pyparsing-2.0.2%40examples%40simpleBool.py/15/pyparsing.infixNotation/python#

mais qui traite en fait la notation, et je dois utiliser l'arbre plusieurs fois sur des données différentes. En cherchant de l'aide avec les arbres d'analyse, j'ai trouvé ceci: http://pyparsing.wikispaces.com/file/view/fourFn.py/30154950/fourFn.py

et j'ai pris l'implémentation de la pile à partir de là. Cependant, il ne se comporte pas comme je l'espère, alors j'espère que quelqu'un pourra me dire ce que je fais de mal.

est ici le cas le plus simple que je pourrais venir avec:

from pyparsing import Word, alphas, infixNotation, opAssoc 

exprStack=[] 
def pushFirst(strg, loc, toks): 
    exprStack.append(toks[0]) 

def addAnd(): 
    exprStack.append("and") 

varname = Word(alphas).setParseAction(pushFirst) 

operators=[("and", 2, opAssoc.LEFT,addAnd)] 

whereExpr = infixNotation(varname,operators) 

exprStack=[] 
teststring = "cheese and crackers and wine" 
parsed=whereExpr.parseString(teststring) 
for p in exprStack: 
    print p 

Ce que je reçois de ce code est:

cheese 
crackers 
wine 
and 

Ce que je vous attendre à obtenir, de ma compréhension de la façon dont le infix méthode de notation devrait fonctionner, est:

cheese 
crackers 
wine 
and 
and 

J'ai également essayé de le courir avec "fromage et craquelins et gagner e et whine "mais je n'en ai encore qu'un" et "dans ma liste. Qu'est-ce que je ne comprends pas dans l'utilisation de la méthode infixNotation?

Merci

+0

J'ai fini par abandonner l'approche de la pile à la fin, et utilisé l'approche de l'objet préféré de Paul McGuire. Pour ceux qui recherchent des requêtes SQL-where-type appliquées aux données pandas, vous pouvez trouver une version (avec seulement une grammaire limitée) sur github ici: [link] (https://github.com/moink/askapanda) – moink

Répondre

2

Commencez par décorer votre action Parse avec traceParseAction deccorator diagnostic de pyparsing.

@traceParseAction 
def addAnd(): 
    exprStack.append("and") 

traceParseAction montrera la ligne de source adaptée, l'emplacement de départ des jetons appariés et jetons passés à l'action d'analyse syntaxique, et la valeur renvoyée par l'action d'analyse syntaxique:

>>entering addAnd(line: 'cheese and crackers and wine', 0, 
       ([(['cheese', 'and', 'crackers', 'and', 'wine'], {})], {})) 
<<leaving addAnd (ret: None) 

Le Les jetons sont un peu déroutants, car ce que vous obtenez est un objet ParseResults pyparsant, qui possède à la fois une sémantique de liste et de dictée, ainsi le Python repr de l'objet affiche d'abord son contenu, puis son contenu nommé. Ce qui ressemble à un tuple avec une liste et un dict est vraiment le ParseResults, et dans ce cas, c'est un ParseResults dont le premier élément est un autre ParseResults, et cet objet imbriqué est celui contenant votre liste de jetons correspondants.

Ceci est un peu plus facile de voir si vous ajoutez un argument tokens à votre action d'analyse syntaxique, puis imprimer :

def addAnd(tokens): 
    print(tokens.dump()) 
    exprStack.append("and") 

Et vous obtiendrez le plus lisible:

[['cheese', 'and', 'crackers', 'and', 'wine']] 
[0]: 
    ['cheese', 'and', 'crackers', 'and', 'wine'] 

Vous pouvez voir que les jetons appariés contiennent non seulement 'et', mais tous les termes et-ed ensemble, donc vous devrez placer autant de 'et' sur votre exprStack que sur les jetons correspondants.

def addAnd(tokens): 
    exprStack.extend(tokens[0][1::2]) 

Avec ce changement, vous devriez maintenant voir ce que votre pile de retour:

cheese 
crackers 
wine 
and 
and 
+1

Wow, aide de l'auteur de pyparsing lui-même! Merci! – moink