Patrones recursivos
Considere el problema de comparar una cadena entre paréntesis,
permitiendo paréntesis anidados ilimitados. Sin el uso de
la recursividad, lo mejor que se puede hacer es usar un patrón
que compare hasta alguna profundidad fija de anidamiento. No es
posible manejar una profundidad de anidamiento arbitraria. Perl 5.6 ha
proporcionado una herramienta experimental que permite a las expresiones
regulares actuar recursivamente (entre otras cosas). El elemento
especial (?R) es proporcionado para el caso específico de la recursividad.
Este patrón de PCRE soluciona el problema de los paréntesis (se asume que la
opción PCRE_EXTENDED
está establecida por lo que los espacios en blanco se
ignoran):
\( ( (?>[^()]+) | (?R) )* \)
Primero se compara un paréntesis de apertura. Después compara cualquier
número de subcadenas que pueden ser tanto una secuencia de algo que no sean
paréntesis como una comparación recursiva del patrón mismo
(esto es, una subcadena con los paréntesis correctos). Finalmente hay
un paréntesis de cierre.
Este patrón de ejemplo en particular contiene repeticiones anidadas
ilimitadas, y así, el uso de un sub-patrón de una sóla aplicación para comparar
cadenas que no contengan paréntesis es importante cuando se aplica
el patrón a cadenas que no coinciden. Por ejemplo, cuando
se aplica a
(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa()
produce "no hay conicidencias" rápidamente. Sin embargo, si no se usa un sub-patrón
de una sóla aplicación, la comparación se ejecuta realmente durante
mucho tiempo ya que hay muchas maneras diferentes de que las repeticiones + y *
se puedan repartir el sujeto, y todas tienen que ser comprobadas
antes de que se informe del fallo.
El conjunto de valores para cualquier sub-patrón de captura son aquellos del
nivel último de la recursión en el cual el valor del sub-patrón
es establecido. Si el patrón anterior se compara con
(ab(cd)ef)
el valor del paréntesis de captura es "ef", el cual es
el último valor tomado en el nivel superior. Si se añaden
paréntesis adicionales, dando lugar a
\( ( ( (?>[^()]+) | (?R) )* ) \)
entonces la cadena que capturan
es "ab(cd)ef", el contenido de los paréntesis del nivel superior. Si
hay más de 15 paréntesis de captura en un patrón,
PCRE ha de obtener memoria extra para almacenar la información durante una
recursión, lo cual hace usando pcre_malloc, liberándola
mediante pcre_free después. Si no se puede obtener memoria, se
guarda la información para los primeros 15 paréntesis de captura sólamente, ya que
no hay manera de otorgar un error "out-of-memory" desde dentro de una
recursión.
Se puede usar también (?1)
, (?2)
y así sucesivamente, para los sub-patrones recursivos. Tamién es posible usar sub-patrones
nominados: (?P>nombre)
o
(?&nombre)
.
Si la sintaxis para la referencia de un sub-patrón recursivo (tanto como número o
como nombre) se usa fuera de los paréntesis a los que hace referencia, opera
como una sub-rutina de un lenguaje de programación. Un ejemplo mostrado
anteriormente, tal que el patrón
(abraz|apreci)o de un \1ador
coincide con "abrazo de un abrazador" y con "aprecio de un apreciador", pero
no con "abrazo de un apreciador". Si en su lugar se usa
(abraz|apreci)o de un (?1)ador
,
coincide con "abrazo de un apreciador" así como con las otras
dos cadenas. Tales referencias deben, sin embargo, seguir al sub-patrón al
que hacen referencia.
La longitud máxima de una cadena objetivo es el número positivo más grande
que una variable tipo integer pueda tener. Sin embargo, PCRE usa la recursividad para
tratar sub-patrones y repetición indefinida. Esto significa que el espacio
de pila disponible puede limitar el tamaño de una cadena objetivo que puede ser
procesada por ciertos patrones.