Question

Ce code fonctionne:

from pyparsing import *

zipRE = "\d{5}(?:[-\s]\d{4})?" 
fooRE = "^\!\s+.*"

zipcode = Regex( zipRE )
foo = Regex( fooRE )

query = ( zipcode | foo )



tests = [ "80517", "C6H5OH", "90001-3234", "! sfs" ]

for t in tests:
    try:
        results = query.parseString( t )
        print t,"->", results
    except ParseException, pe:
        print pe

Je suis coincé sur deux questions:

1 - Comment utiliser une fonction personnalisée pour analyser un jeton. Par exemple, si je voulais utiliser une logique personnalisée au lieu d'une expression régulière pour déterminer si un numéro est un code postal. Au lieu de:

zipcode = Regex( zipRE )

peut-être:

zipcode = MyFunc()

2 - Comment puis-je déterminer quelle chaîne parse TO. « 80001 » à parse « zipcode » mais comment puis-je déterminer cela en utilisant pyparsing? Je ne suis pas l'analyse syntaxique une chaîne pour son contenu, mais simplement de déterminer quel genre de requête est.

Était-ce utile?

La solution

Votre deuxième question est facile, donc je vais répondre à cette première. Modifier requête pour attribuer des noms de résultats aux différentes expressions:

query = ( zipcode("zip") | foo("foo") ) 

Maintenant, vous pouvez appeler getName () sur le résultat renvoyé:

print t,"->", results, results.getName()

Giving:

80517 -> ['80517'] zip
Expected Re:('\\d{5}(?:[-\\s]\\d{4})?') (at char 0), (line:1, col:1)
90001-3234 -> ['90001-3234'] zip
! sfs -> ['! sfs'] foo

Si vous allez utiliser le fooness ou zipness du résultat d'appeler une autre fonction, vous pouvez le faire lors de l'analyse en attachant une action d'analyse syntaxique à vos expressions foo et zipcode:

# enclose zipcodes in '*'s, foos in '#'s
zipcode.setParseAction(lambda t: '*' + t[0] + '*')
foo.setParseAction(lambda t: '#' + t[0] + '#')

query = ( zipcode("zip") | foo("foo") ) 

donne maintenant:

80517 -> ['*80517*'] zip
Expected Re:('\\d{5}(?:[-\\s]\\d{4})?') (at char 0), (line:1, col:1)
90001-3234 -> ['*90001-3234*'] zip
! sfs -> ['#! sfs#'] foo

Pour votre première question, je ne sais pas exactement quel genre de fonction que vous voulez dire. Pyparsing fournit beaucoup plus de cours d'analyse syntaxique que juste Regex (comme Word, les mots-clés, littérales, CaselessLiteral), et vous rédigez votre analyseur en les combinant avec « + », « | », « ^ », « ~ », « @ » et '*' les opérateurs. Par exemple, si vous voulez analyser un numéro de sécurité sociale des États-Unis, mais pas utiliser une expression régulière, vous pouvez utiliser:

ssn = Combine(Word(nums,exact=3) + '-' + 
        Word(nums,exact=2) + '-' + Word(nums,exact=4))

mot correspond CONTIGUS « mots » composés des caractères donnés dans son constructeur, combiner concaténer les jetons appariés en un seul jeton.

Si vous voulez analyser pour obtenir une liste potentielle de ces chiffres, délimité par l « / » de, utilisez:

delimitedList(ssn, '/')

ou s'il y avait entre 1 et 3 ces chiffres, sans delimters, utilisez:

ssn * (1,3)

Et toute expression peut avoir des noms de résultats ou analyser les actions qui leur sont rattachés, pour enrichir davantage les résultats ou la analysables fonctionnalité lors de l'analyse. Vous pouvez même créer des parseurs récursifs, comme les listes imbriquées des parenthèses, des expressions arithmétiques, etc. en utilisant la classe Forward.

Mon intention quand j'ai écrit pyparsing était que cette composition de parseurs de blocs de construction de base serait la principale forme pour la création d'un analyseur. Il était seulement dans une version ultérieure que j'ai ajouté Regex comme (ce que je pensais était) la soupape d'échappement ultime - si les gens ne pouvaient construire leur analyseur, ils pourraient se rabattre sur le format de regex, qui a définitivement prouvé sa puissance au fil du temps.

Ou, comme une autre affiche l'indique, vous pouvez ouvrir la source de pyparsing, et la sous-classe l'une des classes existantes, ou d'écrire vos propres, suivant leur structure. Voici une classe qui correspondrait à des caractères paires:

class PairOf(Token):
    """Token for matching words composed of a pair
       of characters in a given set.
    """
    def __init__( self, chars ):
        super(PairOf,self).__init__()
        self.pair_chars = set(chars)

    def parseImpl( self, instring, loc, doActions=True ):
        if (loc < len(instring)-1 and 
           instring[loc] in self.pair_chars and
           instring[loc+1] == instring[loc]):
            return loc+2, instring[loc:loc+2]
        else:
            raise ParseException(instring, loc, "Not at a pair of characters")

Alors que:

punc = r"~!@#$%^&*_-+=|\?/"
parser = OneOrMore(Word(alphas) | PairOf(punc))
print parser.parseString("Does ** this match @@@@ %% the parser?")

donne:

['Does', '**', 'this', 'match', '@@', '@@', '%%', 'the', 'parser']

(Notez l'omission du seul arrière '?)

Autres conseils

Vous pouvez utiliser séparément et code postal foo, afin que vous sachiez que l'on les matches de chaîne.

zipresults = zipcode.parseString( t )
fooresults = foo.parseString( t )

Je n'ai pas le module pyparsing, mais Regex doit être une classe, pas une fonction.

Qu'est-ce que vous pouvez faire est de la sous-classe et les méthodes de remplacement si nécessaire pour personnaliser le comportement, puis utilisez vos sous-classes à la place.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top