2008-10-26 5 views
4

Je suis en train de faire correspondre des identifiants, mais maintenant j'ai un problème: mes identifiants sont autorisés à contenir des caractères Unicode. Par conséquent, l'ancienne façon de faire les choses ne suffit pas:Correspond à unicode dans les expressions rationnelles de ply

t_IDENTIFIER = r"[A-Za-z](\\.|[A-Za-z_0-9])*" 

Dans my markup language analyseur I correspondre les caractères unicode en permettant à tous les caractères sauf ceux que j'utilise explicitement, parce que mon langage de balisage a seulement deux ou trois personnages que je dois échapper de cette façon.

Comment puis-je faire correspondre tous les caractères Unicode avec les expressions rationnelles python et ply? Est-ce aussi une bonne idée? Je voudrais que les gens utilisent des identifiants comme Ω »« foo² väli π comme identifiants (noms de variables et autres) dans leurs programmes. Zut! Je veux que les gens puissent écrire des programmes dans leur propre langue si c'est pratique! Quoi qu'il en soit, unicode est supporté de nos jours dans une grande variété d'endroits, et il devrait se propager. Edit: Les classes de caractères POSIX ne semblent pas être reconnues par les expressions rationnelles python.

>>> import re 
>>> item = re.compile(r'[[:word:]]') 
>>> print item.match('e') 
None 

Modifier: Pour mieux expliquer ce dont j'ai besoin. J'aurais besoin d'un regex qui correspond à tous les caractères imprimables Unicode, mais pas aux caractères ASCII. Editer: r "\ w" fait un peu ce que je veux, mais il ne correspond pas à «», et j'ai aussi besoin d'une regex qui ne correspond pas aux nombres.

+0

Il ne semble pas que Python PCRE comprend des classes sous-jacentes soit: \ p {} IsAlpha – Axeman

Répondre

5

le module re prend en charge la syntaxe \ w qui:

Si UNICODE est défini, cela correspond aux caractères [0-9_] plus tout ce qui est classé comme alphanumérique dans la base de données de propriétés de caractère Unicode .

donc les exemples ci-dessous montre comment faire correspondre les identifiants unicode:

>>> import re 
>>> m = re.compile('(?u)[^\W0-9]\w*') 
>>> m.match('a') 
<_sre.SRE_Match object at 0xb7d75410> 
>>> m.match('9') 
>>> m.match('ab') 
<_sre.SRE_Match object at 0xb7c258e0> 
>>> m.match('a9') 
<_sre.SRE_Match object at 0xb7d75410> 
>>> m.match('unicöde') 
<_sre.SRE_Match object at 0xb7c258e0> 
>>> m.match('ödipus') 
<_sre.SRE_Match object at 0xb7d75410> 

donc l'expression que vous recherchez est: (u) [^ \ W0-9] \ w *

+0

Maintenant. C'est une solution satisfaisante! – Cheery

+0

La citation de la documentation Python est correcte, mais les exemples sont trompeurs. Vous pouvez simplement utiliser l'indicateur UNICODE avec \ w au lieu de l'expression inutilement longue donnée: 're.match (r '\ w +'," ünıcodê ", re.UNICODE)' – Walter

+2

Walter, vous n'avez pas correctement lu la question: 1) le but est un identifiant dans un langage de programmation, qui ne commence généralement pas par 0-9. 2) l'analyseur (ply) s'occupe de l'analyse, et il ne peut pas être contrôlé comment il va invoquer match, donc (? U) est nécessaire. –

1

a résolu le problème avec l'aide de Vinko.

Je me suis rendu compte que l'obtention de la gamme Unicode est complètement bête. Je vais donc faire ceci:

symbols = re.escape(''.join([chr(i) for i in xrange(33, 127) if not chr(i).isalnum()])) 
symnums = re.escape(''.join([chr(i) for i in xrange(33, 127) if not chr(i).isalnum()])) 

t_IDENTIFIER = "[^%s](\\.|[^%s])*" % (symnums, symbols) 

Je ne connais pas les classifications de caractères Unicode. Si ce truc unicode commence à devenir trop compliqué, je peux juste mettre l'original en place. Le support UTF-8 assure toujours le support aux jetons STRING, ce qui est plus important.

Editer: D'autre part, je commence à comprendre pourquoi il n'y a pas beaucoup de support Unicode dans les langages de programmation .. C'est un bidouille moche, pas une solution satisfaisante.

3

vous devez passer des paramètres passe reflags dans lex.lex:

lex.lex(reflags=re.UNICODE) 
Questions connexes