2009-03-11 12 views
2

J'essaye le pyparsing de python pour l'analyse. Je me suis coincé en faisant l'analyseur récursif.J'ai besoin de l'aide pour faire l'analyseur récursif utilisant pyparsing

Laissez-moi vous expliquer le problème

Je veux rendre le produit cartésien des éléments. La syntaxe est

cross({elements },{element}) 

Je mets de manière plus spécifique

cross({a},{c1}) or cross({a,b},{c1}) or cross({a,b,c,d},{c1}) or 

donc la forme générale est le premier groupe aura n éléments (a, b, c, d). Le second groupe aura un élément qui sera donc produit final cartésien.

La syntaxe doit être fait récursif, car il peut passer au niveau n comme

cross(cross({a,b},{c1}),{c2}) 

Cela signifie traverser a, b avec c1. Disons que nous aboutissons. Nous traversons à nouveau y avec c2

Cela peut être jusqu'à croix de niveau n (croix (croix (croix ......

Ce que je veux est d'avoir l'objet à initialiser en utilisant setparseAction

Donc, je vais avoir 2 classes

class object1(object): 
    This will be used by a,b,c,d 

class object2(object): 
     This will hold cross elements 

je besoin d'aide sur ce que je ne suis pas en mesure de faire l'analyseur récursif. Vous

Répondre

6

devriez regarder les définitions d'autres langues pour voir comment cela est habituellement manipulé.

Par exemple, regardez comment la multiplication est définie.

Il n'est pas

{expression} * {expression} 

Parce que la récursion est difficile à traiter, et il n'y a pas implicite commande de gauche à droite. Ce que vous voyez le plus souvent, ce sont des choses comme

{term} + {factor} 
{factor} * {unary-expression} 

Qui place les priorités et un ordre de gauche à droite autour des opérateurs. Regardez quelque chose comme http://www.cs.man.ac.uk/~pjj/bnf/c_syntax.bnf pour des exemples de comment les choses comme ceci sont généralement structurées.

+0

Je ne avez pas besoin de l'expression à utiliser. J'ai besoin de cela en python en utilisant le pyparsing seulement. La syntaxe est écrite est fixe et je pense que cela peut être fait en utilisant l'analyseur récursif. –

+0

@asb: Comme d'autres n'utilisent pas d'analyseurs récursifs pour ce genre de choses, je suggère que vous pourriez avoir plus de succès si vous changez la définition (pas la syntaxe, mais la façon dont elle est définie) pour éliminer la récursivité déroutante. –

3

Je suis d'accord avec @ S.Lott vous devriez reconsidérer votre grammaire.

définitions récursives peuvent être introduites en utilisant Forward():

from pyparsing import (Literal, Word, OneOrMore, Forward, nums, alphas) 

def BNF(): 
    """ 
    element  :: id 
    elements  :: '{' element [ ',' element ]+ '}' 
        | 'cross' '(' elements ',' '{' element '}' ')' 
    """ 
    lcb, rcb, lb, rb, comma = [Literal(c).suppress() for c in '{}(),'] 
    element = Word(alphas, alphas+nums+"_") # id 
    elements = Forward() 
    elements << ((lcb + element + OneOrMore(comma + element) + rcb) 
       | (Literal('cross') + lb + elements + comma 
        + lcb + element + rcb + rb)) 
    return elements 

print BNF().parseString("cross(cross({a,b},{c1}),{c2})") 

Sortie:

['cross', 'cross', 'a', 'b', 'c1', 'c2'] 
3

Je ne sais pas si cela est une aide, mais voici comment vous feriez ce que vous voulez lepl. Puisque la grammaire semble correcte, je suppose qu'il serait facile de traduire en pypars.

from lepl import * 

def compile_parser(): 

    class Cross(Node): pass 

    word = Token('[a-z0-9]+') 
    par, en, bra, ket = [~Token('\\'+c) for c in '(){}'] 
    comma = ~Token(',') 

    cross = Delayed() 
    vector = bra & word[1:,comma] & ket     > list 
    arg = vector | cross 
    cross += ~word('cross') & par & arg[2,comma] & en > Cross 

    parser = cross.string_parser() 
    return lambda expr: parser(expr)[0] 


if __name__ == '__main__': 

    parser = compile_parser() 
    print parser('cross({a},{c1})') 
    print parser('cross({a,b},{c1})') 
    print parser('cross({a,b,c,d},{c1})') 
    print parser('cross(cross({a,b},{c1}),{c2})') 

La sortie est:

Cross 
+- [u'a'] 
`- [u'c1'] 

Cross 
+- [u'a', u'b'] 
`- [u'c1'] 

Cross 
+- [u'a', u'b', u'c', u'd'] 
`- [u'c1'] 

Cross 
+- Cross 
| +- [u'a', u'b'] 
| `- [u'c1'] 
`- [u'c2'] 
Questions connexes