Commentaires
Performances
Fonctionnement des expressions rationnelles
PHP Manual

## Masques récursifs

Considérons le cas où il faut rechercher dans une chaîne avec un niveau d'imbrications infini de parenthèses. Sans l'aide de la récursivité, le mieux que nous puissions obtenir est de créer un masque avec un niveau fixé de profondeur d'imbrication. Il n'est pas possible de traiter des masques à niveau d'imbrication variable. PCRE fournit un nouvel outil expérimental qui permet d'utiliser la récursivité dans les masques (entre autres). L'option (?R) est fournie pour servir la cause de la récursivité. Le masque suivant résout le problème des parenthèses (l'option PCRE_EXTENDED est utilisée pour ignorer les espaces) : \( ( (?>[^()]+) | (?R) )* \)

Tout d'abord, le masque recherche une parenthèse ouvrante. Puis, il recherche n'importe quel nombre de sous-chaînes qui sont soit des séquences de caractères non-parenthèses, ou bien une recherche récursive avec le même masque (i.e. une chaîne correctement incluse entre parenthèses). Finalement, il recherche une parenthèse fermante.

Cet exemple particulier contient un nombre illimité de répétitions imbriquées, ce qui fait que l'utilisation de sous-chaînes à utilisation unique pour rechercher les séquences de caractères non parenthèses est important, lorsqu'il s'applique à une chaîne qui n'est pas valide. Par exemple, si on l'applique à (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa() la réponse arrive rapidement. Sinon, si les sous-chaînes à utilisation unique ne sont pas utilisées, la recherche peut prendre un temps très long, car il existe de très nombreuses combinaisons de + et * à tester avant de conclure à l'échec.

Les valeurs utilisées pour capturer les sous-masques sont celles utilisées par les niveaux les plus hauts de récursivité, auxquels la valeur est fixée. Si le masque précédent est utilisé avec (ab(cd)ef) la valeur de la parenthèse capturante est "ef", qui est la dernière valeur lue au niveau supérieur. Si de nouvelles parenthèses sont ajoutées, par exemple : \( ( ( (?>[^()]+) | (?R) )* ) \) alors la chaîne capturée est "ab(cd)ef", c'est-à-dire le contenu de la parenthèse capturante de plus haut niveau. S'il y a plus de 15 parenthèses capturantes dans une chaîne, PCRE doit utiliser plus de mémoire pour stocker ces données. S'il ne peut obtenir cette mémoire supplémentaire, il ne fait que sauver les 15 premières, car il n'y a pas moyen de générer une erreur de mémoire dans le cadre d'une récursivité.

Depuis PHP 4.3.3, (?1), (?2) et suivant peuvent être également utilisés pour les sous masques récursifs. Il est également possible d'utiliser les sous masques nommés : (?P>foo) ou (?P&name).

Si la syntaxe pour une référence de sous-masque récursif (soit par un nombre ou par un nom) est utilisée en dehors des parenthèses à laquelle elle fait référence, il opère comme une sous-routine dans un langage de programmation. Un exemple ci-dessus a montré que le masque (sens|respons)e and \1ibility trouvera "sense and sensibility" et "response and responsibility", mais pas "sense and responsibility". Si on utilise plutôt le masque (sens|respons)e and (?1)ibility alors, il trouvera "sense and responsibility" tout comme les deux autres chaînes. De telles références doivent, dépendant, suivre le sous-masque auquel elles se réfèrent.

La longueur maximale d'un sujet correspond au plus grand nombre positif qu'une variable entière peut contenir. Cependant, PCRE utilise la récursivité pour gérer les sous-masques et les répétitions infinies. Ce qui signifie que l'espace disponible pour la pile peut limiter la taille du sujet qui peut être passé à certains masques.

Commentaires
Performances
Fonctionnement des expressions rationnelles
PHP Manual