2016-02-18 1 views
1

Travailler mon chemin à travers:Pyparsing: Définition rapide de l'analyseur de référence correcte?

Pyparsing Quick Reference, Chapter 3: Small Example -

L'analyseur exemple est censé correspondre à des identifiants Python valides, donc

'a_#' 

devrait être invalide, comme l'auteur commente à être, non? Cependant, au bas de la page:

---Test for 'a_#' 
    Matches: ['a', '_'] 

Voici l'analyseur:

first = pp.Word(pp.alphas+"_", exact=1) 
rest = pp.Word(pp.alphanums+"_") 
identifier = first+pp.Optional(rest) 

Je ne sais pas, donc je voudrais quelques commentaires avant de contacter l'auteur. En outre, j'essaye de le corriger en construisant un analyseur qui accepterait seulement la gamme de caractères définie dans la chaîne entière, ainsi il ne correspondrait pas à un préfixe de celui-ci. Vous n'arrivez pas à bien faire - un conseil?

Répondre

1

Yikes! Construire un identifiant en utilisant deux Word s est gaspilleur, inefficace, et juste une mauvaise pratique de pyparsing. Je pense que l'auteur faisait cela comme une accumulation de montrer comment Combine pourrait être utilisé ici, mais afterword, il devrait montrer la meilleure alternative en utilisant une seule expression Word.

Word a un format à deux arguments (clairement décrit in the online docs) pour seulement cette situation:

valid_ident_leading_chars = alphas + '_' 
valid_ident_body_chars = alphanums + '_' 
identifier = Word(valid_ident_leading_chars, valid_ident_body_chars) 

(BTW, cela équivaut à:

identifier = Regex('['+valid_ident_leading_chars+']['+valid_ident_body_chars+']*') 

Et si vous regardez dans le pyparsing code, vous verrez que Word implémente sa correspondance en construisant cette expression très régulière.)

Cela va toujours analyser la partie principale de 'a_ #', identique à une expression régulière. Si vous voulez que votre test échoue car la chaîne complète n'a pas été analysée, utilisez:

identifier.parseString('a_#', parseAll=True) 

Pour simplifier l'écriture de tests, vous pouvez également utiliser « == » - lorsque l'on compare une expression pyparsing avec une chaîne, l'expression exécutera expr.parseString(comparison_string, parseAll=True) et retournera vrai/faux selon qu'une exception ParseException a été levée ou non.

assert 'a_' == identifier # <-- will pass 
assert 'a_#' == identifier # <-- will fail 
+0

Salut, Paul! Je suppose que j'ai peut-être commencé avec vos tutoriels [Construire des analyseurs de descente récursifs avec Python] (http://www.onlamp.com/lpt/a/6435) et [Utiliser le module pyparsing] (http: //www.ptmcg. com/geo/python/howtousepyparsing.html), mais j'ai commencé avec John Shipman [pyparsing quick reference: un outil de traitement de texte Python] (http://infohost.nmt.edu/tcc/help/pubs/pyparsing/web/index .html) parce qu'il a été mis à jour le plus récemment (2013). Merci beaucoup pour tout le travail que vous avez mis à la disposition de la communauté sur Pyparsing - et, bien sûr, pour l'excellente réponse exhaustive! – Zubo