Comment faire pour examiner les expressions rationnelles dans l’API Perl

Je travaille sur un code qui doit sérialiser les expressions rationnelles Perl, y compris tous les indicateurs de regex. Seul un sous-ensemble d’indicateurs est pris en charge. Je dois donc détecter quand des indicateurs non pris en charge, tels que /u figurent dans l’object regex.

La version actuelle du code fait ceci:

 static void serialize_regex_flags(buffer *buf, SV *sv) { char flags[] = {0,0,0,0,0,0}; unsigned int i = 0, f = 0; STRLEN ssortingng_length; char *ssortingng = SvPV(sv, ssortingng_length); 

Ensuite, traite manuellement ssortingng par caractère pour rechercher des indicateurs.

Le problème ici est que la chaîne de caractères des drapeaux de regex a changé (je pense en Perl 5.14) de par exemple (?i-xsm:foo) à (?^i:foo) , ce qui rend l’parsing très pénible.

Je pourrais vérifier la version de perl , ou simplement écrire l’parsingur pour gérer les deux cas, mais quelque chose me dit qu’il doit y avoir une méthode d’introspection supérieure disponible.

En Perl, vous utiliseriez re::regexp_pattern .

  my $re = qr/foo/i; my ($pat, $mods) = re::regexp_pattern($re); say $pat; # foo say $mods; # i 

Comme vous pouvez le constater à partir de la source de regexp_pattern , l’API n’a pas de fonction permettant d’obtenir ces informations; je vous recommande donc d’appeler cette fonction également à partir de XS.

perlcall couvre l’appelant des fonctions Perl depuis C. J’ai créé le code non testé suivant:

 /* Calls re::regexp_pattern to extract the pattern * and flags from a comstackd regex. * * When re isn't a comstackd regex, returns false, * and *pat_ptr and *flags_ptr are set to NULL. * * The caller must free() *pat_ptr and *flags_ptr. */ 

 static int regexp_pattern(char ** pat_ptr, char ** flags_ptr, SV * re) { dSP; int count; ENTER; SAVETMPS; PUSHMARK(SP); XPUSHs(re); PUTBACK; count = call_pv("re::regexp_pattern", G_ARRAY); SPAGAIN; if (count == 2) { /* Pop last one first. */ SV * flags_sv = POPs; SV * pat_sv = POPs; /* XXX Assumes no NUL in pattern */ char * pat = SvPVutf8_nolen(pat_sv); char * flags = SvPVutf8_nolen(flags_sv); *pat_ptr = strdup(pat); *flags_ptr = strdup(flags); } else { *pat_ptr = NULL; *flags_ptr = NULL; } PUTBACK; FREETMPS; LEAVE; return *pat_ptr != NULL; } 

Usage:

 SV * re = ...; char * pat; char * flags; regexp_pattern(&pat, &flags, re); 
 use Data::Dump::Streamer ':util'; my ($pattern, $flags) = regex( qr/foo/i ); print "pattern: $pattern, flags: $flags\n"; # pattern: foo, flags: i 

Mais si vous essayez de restreindre des fonctionnalités plus récentes, vous avez beaucoup plus de travail à faire que simplement vérifier / u.