
El aforismo "Si al principio no tienes éxito, inténtalo, inténtalo de nuevo" se formaliza en la coincidencia de patrones en un proceso llamado retrocediendo .Retroceder es cómo el comparador verifica todas las combinaciones posibles que podrían coincidir.Esta publicación utiliza algunas funciones secretas en el comparador de patrones de JMP para exponer el proceso de retroceso. La única declaración a continuación es una combinación de patrones moderadamente complicada.Pero incluso las coincidencias simples (y expresiones regulares) usarán el retroceso.
Secreto 1: la función Log() en la línea 21 genera una salida en la ventana de registro de JMP. El >> anterior está tomando el texto previamente emparejado e imprimiéndolo, junto con una posición de base cero en la fuente y la etiqueta de texto suministrada. Esto no tiene nada que ver con el retroceso y todo que ver con la depuración. Puede usar este secreto para depurar sus propios patrones.
Secreto 2: PatTest() tiene tres argumentos, aunque solo se usa uno. Todo esto se trata de dar marcha atrás. El JSL en el segundo argumento se ejecuta en la dirección de seguimiento hacia adelante y el JSL en el tercer argumento se ejecuta en la dirección de seguimiento hacia atrás.
Secreto 3: PatMatch() normalmente optimiza la falla, lo mejor que puede. Cuando ve que no quedará suficiente texto en la cadena de origen para que coincida con la longitud mínima restante del patrón, se detiene. La opción FULLSCAN desactiva esa optimización. Para este ejemplo, el retroceso parecerá detenerse prematuramente sin la opción FULLSCAN.
Secreto 4: PatFail() se puede usar para encontrar todas las coincidencias posibles al forzar que cada coincidencia falle y se consideren alternativas.
Aquí está el código y la salida con una explicación a continuación.
Pat Match(
"EDACGDE", // a contrived string to exercise backtracking
(
Pat Len( 1 ) >> p // match a character, store in p
+
Pat Test(
p > "B", // test
Write( "p=", p, " " ), // advance
Write( "retry\!n" ) // backtrack
)
+
Pat Arb() // skip zero or more characters
+
Pat Len( 1 ) >> q // match another, store in q
+
Pat Test(
p < q & q < "F", // test
Write( "q=", q, " " ), // advance
Write( "retry " ) // backtrack
)
) >> Log( "FOUND" ) // a debugging tool
+
Pat Fail(), // try alternatives
NULL, // no replacement
FULLSCAN // to the bitter end
);
p=E q=D reintentar q=A reintentar q=C reintentar q=G reintentar q=D reintentar q=E reintentar reintentar
p=D q=A reintentar q=C reintentar q=G reintentar q=D reintentar q=E
1(ENCONTRADO) DACGDE
reintentar reintentar
p=un reintento
p=C q=G reintentar q=D
3 (ENCONTRADO) CGD
reintentar q=E
3(ENCONTRADO) CGDE
reintentar reintentar
p=G q=D reintentar q=E reintentar reintentar
p=D q=E
5(ENCONTRADO) DE
reintentar reintentar
p=E reintentar
0
Explicación
Primero, el cero final. Ese es el código de retorno, y dice que la coincidencia falló. El partido en realidad FUNDAR cuatro coincidencias, pero PatFail() hizo que buscara otra. Esto se espera.
A continuación, las P y las Q. p comienza en E y la prueba para >B es feliz. PatArb() es reacio e inicialmente no omite nada. q obtiene la D siguiendo a la E. Pero la prueba es infeliz esta vez; q entre p y "F" no es cierto. ¡Hora de retroceder! El LEN(1) que puso la D en q devuelve la D y PatArb() tiene la oportunidad de hacer algo diferente. Esta vez toma a regañadientes a un personaje, el D. El PatLen(1) luego da la A a la q. Al final de la primera línea, hay dos reintentos; el segundo es para p. La siguiente línea muestra p obteniendo el segundo carácter, D. Dado que la coincidencia de patrón no está anclada, se permite que el comienzo de la coincidencia flote hacia adelante a través del texto como parte del proceso de retroceso; esta vez el partido avanza con el PatArb tomando más y más hasta que ocurre el primer éxito. >>Log("FOUND") registra el éxito en el registro, luego PatFail() hace que continúe el retroceso.
Si no está claro, puede probar pruebas más simples e instrumentarlas con el método >>LOG("tag") para tener una idea de lo que está sucediendo.
En este punto, debería quedar claro por qué este partido dura mucho, mucho tiempo:

aunque puede ver que no puede tener éxito porque la cadena de aaaa... aaa no tiene b en ninguna parte, el comparador tiene que descubrir eso probando muchas combinaciones tontas: salte 2 caracteres seguidos de salte 3... y salte 3 seguido del salto 2... etc, etc, etc.... Retroceder no puede arreglar un patrón mal escrito. Esa barra de progreso no significa que esté casi terminada. (No hay razón para poner patarb dentro de patrepeat, excepto para ver este cuadro de diálogo. Patarb ya coincide con un número arbitrario de caracteres).
actualización 1 de febrero de 2017: reparación del formato para la nueva comunidad.