En una palabra
Parece que la solución rápida a su problema es definir un REGEX, o un FSA (autómata de estado finito), que reconoce todos los comienzos posibles de los documentos (se permiten falsos positivos, que en realidad no corresponderían a un documento). Luego puede ejecutarlo muy rápido en su entrada para identificar el próximo lugar donde un documento podría comenzar con pocos errores. Puede causar algunas posiciones erróneas para el inicio de un documento, pero el analizador los reconocerá y los abandonará.
Por lo tanto, Finite State Automaton puede ser el nombre del analizador que estaba buscando. :)
El problema
Siempre es difícil entender un problema práctico, especialmente cuando el vocabulario puede tener muchas interpretaciones. La palabra bosque de análisis fue acuñada (afaik) para el análisis sin contexto (CF) de oraciones ambiguas que tienen varios árboles de análisis. Se puede generalizar un poco para analizar una red de oraciones u otros tipos de gramática. De ahí todas las respuestas sobre Earley, GLR, Marpa y analizadores derivados (hay muchos otros) que no fueron relevantes en este caso.
Pero eso aparentemente no es lo que tienes en mente. Desea analizar una cadena única que es una secuencia de documentos inequívocos y obtener un árbol de análisis para cada uno , o algún tipo de representación estructurada, ya que realmente no dice cómo se define la sintaxis de sus documentos, desde dónde se encuentra. Un punto de vista del lenguaje formal. Lo que tiene es un algoritmo y tablas que harán el trabajo de análisis cuando se inicie al comienzo de un documento. Que así sea.
El problema real es que su flujo de documentos contiene basura considerable que separa los documentos. Y parece que su dificultad es escanear esta basura lo suficientemente rápido. Su técnica actual es comenzar desde el principio e intentar escanear desde el primer carácter, y saltar al reinicio en el siguiente carácter cada vez que falle, hasta que escanee un documento completo. Luego repite indicando desde el primer carácter después del documento recién escaneado.
Esa es también la solución sugerida por @amon en la segunda parte de su respuesta .
Puede que no sea una solución muy rápida (no tengo forma de probarlo), porque es poco probable que el código del analizador esté optimizado para iniciarse de manera muy eficiente al comienzo de un documento. En uso normal, hace esto solo una vez, por lo que no es un punto caliente desde el punto de vista de la optimización. Por lo tanto, su felicidad moderada con esta solución no es demasiado sorprendente.
Entonces, lo que realmente necesita es un algoritmo que pueda encontrar rápidamente el comienzo de un documento que comienza con una gran cantidad de basura. Y tienes suerte: tales algoritmos existen. Y estoy seguro de que lo sabes: se llama buscar un REGEX.
La solución simple
Lo que debe hacer es analizar la especificación de sus documentos para encontrar cómo comienzan estos documentos. No puedo decir exactamente cómo, ya que no estoy seguro de cómo se organiza formalmente su especificación de sintaxis. Posiblemente todos comienzan con alguna palabra de una lista finita, posiblemente mezclada con algunos signos de puntuación o números. Eso es para que lo compruebes.
Lo que debe hacer es definir un autómata de estado finito (FSA), o de manera equivalente para la mayoría de los programadores, una expresión regular (REGEX) que pueda reconocer los primeros caracteres de un documento: cuanto más, mejor, pero no tiene por qué ser muy grande (ya que puede llevar tiempo y espacio). Esto debería ser relativamente fácil de hacer desde la especificación de sus documentos, y probablemente se pueda hacer automáticamente con un programa que lea la especificación de sus documentos.
Una vez que haya producido su expresión regular, puede ejecutarla en su flujo de entrada para llegar muy rápidamente al comienzo de su primer (o siguiente) documento de la siguiente manera:
Asumo:
- docstart
es una expresión regular que coincide con el comienzo de todos los documentos
- search(regex, stream)
es una función que las búsquedas stream
para una subcadena que los fósforos regex
. Cuando regresa, el flujo se reduce a su flujo secundario de sufijo que comienza al comienzo de la primera subcadena coincidente, o al flujo vacío si no se encuentra ninguna coincidencia.
- parse(stream)
intenta analizar un documento desde el principio de la secuencia (lo que queda de él) y devuelve el árbol de análisis en cualquier formato, o falla. Cuando regresa, el flujo se reduce a su flujo secundario de sufijo comenzando en la posición que sigue inmediatamente al final del documento analizado. Llama a una excepción si el análisis falla.
forest = empty_forest
search(docstart, stream)
while stream is not empty:
try:
forest = forest + parse(stream)
except
remove first character from stream
search(docstart, stream)
Tenga en cuenta que la eliminación del primer carácter es necesaria para que la próxima búsqueda no vuelva a encontrar la misma coincidencia.
Por supuesto, el acortamiento de la corriente es una imagen. Puede ser solo un índice en la transmisión.
Una nota final es que su expresión regular no necesita ser demasiado precisa, siempre que reconozca todos los comienzos. Si reconoce ocasionalmente una cadena que no puede ser el comienzo de un documento (falso positivo), entonces la única penalización es el costo de una llamada inútil al analizador.
Por lo tanto, eso puede ayudar a simplificar la expresión regular, si es útil.
Sobre la posibilidad de una solución más rápida
La solución anterior debería funcionar bastante bien en la mayoría de los casos. Sin embargo, si realmente tiene una gran cantidad de basura y terabytes de archivo para procesar, puede haber otros algoritmos que se ejecuten más rápido.
La idea se deriva del algoritmo de búsqueda de cadenas de Boyer-Moore . Este algoritmo puede buscar una secuencia para una sola cadena extremadamente rápido porque utiliza un análisis estructural de la cadena para omitir la lectura de la mayor parte de la secuencia, saltando fragmentos sin siquiera mirarlos. Es el algoritmo de búsqueda más rápido para una sola cadena.
La dificultad es que su adaptación a la búsqueda de expresiones regulares, en lugar de una sola cadena, parece muy delicada y podría no funcionar tan bien, dependiendo de las características de la expresión regular que esté considerando. Eso a su vez podría depender de la sintaxis de los documentos que está analizando. Pero no confíe demasiado en mí en esto, ya que no tuve tiempo de hacer una lectura cuidadosa de los documentos que encontré.
Te dejo con uno o dos punteros que encontré en la web, incluido uno que aparentemente es un trabajo de investigación arbitrado , pero debes considerar esto como más especulativo, posiblemente investigativo, para ser considerado solo si tienes problemas de rendimiento. Y probablemente no haya ningún programa de plataforma que lo haga.