Je travaille avec pyparsing et je l'ai trouvé excellent pour développer un DSL simple qui me permet d'extraire des champs de données de MongoDB et de faire des opérations arithmétiques simples sur eux. J'essaie maintenant d'étendre mes outils de manière à pouvoir appliquer des fonctions de la forme Rank[Person:Height] aux champs et potentiellement inclure des expressions simples en tant qu'arguments aux appels de fonction. J'ai beaucoup de mal à faire fonctionner la syntaxe d'analyse. Voici ce que j'ai jusqu'à présent :
# Define parser
expr = Forward()
integer = Word(nums).setParseAction(EvalConstant)
real = Combine(Word(nums) + "." + Word(nums)).setParseAction(EvalConstant)
# Handle database field references that are coming out of Mongo,
# accounting for the fact that some fields contain whitespace
dbRef = Combine(Word(alphas) + ":" + Word(printables) + \
Optional(" " + Word(alphas) + " " + Word(alphas)))
dbRef.setParseAction(EvalDBref)
# Handle function calls
functionCall = (Keyword("Rank") | Keyword("ZS") | Keyword("Ntile")) + "[" + expr + "]"
functionCall.setParseAction(EvalFunction)
operand = functionCall | dbRef | (real | integer)
signop = oneOf('+ -')
multop = oneOf('* /')
plusop = oneOf('+ -')
# Use parse actions to attach Eval constructors to sub-expressions
expr << operatorPrecedence(operand,
[
(signop, 1, opAssoc.RIGHT, EvalSignOp),
(multop, 2, opAssoc.LEFT, EvalMultOp),
(plusop, 2, opAssoc.LEFT, EvalAddOp),
])
Mon problème est que lorsque je teste une expression simple comme Rank[Person:Height], j'obtiens une exception d'analyse :
ParseException: Expected "]" (at char 19), (line:1, col:20)
Si j'utilise un flottant ou une expression arithmétique comme argument, comme Rank[3 + 1.1], l'analyse fonctionne correctement, et si je simplifie la grammaire de dbRef pour qu'il s'agisse simplement de Word(alphas), cela fonctionne également. Je n'arrive pas à comprendre ce qui ne va pas avec ma grammaire complète. J'ai essayé de réarranger l'ordre des opérandes ainsi que de simplifier la grammaire functionCall, sans succès. Quelqu'un peut-il me dire ce qui ne va pas ?
Une fois que cela fonctionnera, je voudrais faire un dernier pas et introduire le support pour l'assignation de variables dans les expressions .
EDIT : Après d'autres tests, si je supprime les imprimables de la grammaire de dbRef, les choses fonctionnent correctement :
dbRef = Combine(Word(alphas) + OneOrMore(":") + Word(alphanums) + \
Optional("_" + Word(alphas)))
CEPENDANT, si j'ajoute le caractère "-" à dbRef (dont j'ai besoin pour les champs de la base de données comme "Class:S-N"), l'analyseur échoue à nouveau. Je pense que le "-" est consommé par le signop dans mon operatorPrecedence ?