Em poucas palavras
Parece que a solução rápida para o seu problema é definir um REGEX, ou um FSA (autômato de estado finito), que reconheça todos os possíveis inícios de documentos (são permitidos falsos positivos, que na verdade não corresponderiam a um documento). Em seguida, você pode executá-lo com muita rapidez para identificar o próximo local onde um documento pode começar com poucos erros. Isso pode causar algumas posições incorretas no início do documento, mas elas serão reconhecidas pelo analisador e abandonadas.
Portanto, o Finite State Automaton pode ser o nome do analisador que você estava procurando. :)
O problema
É sempre difícil entender um problema prático, especialmente quando o vocabulário pode ter muitas interpretações. A palavra floresta de análise foi cunhada (afaik) para análise sem contexto (CF) de sentenças ambíguas que possuem várias árvores de análise. Pode ser generalizado um pouco para analisar uma treliça de frases ou para outros tipos de gramática. Portanto, todas as respostas sobre Earley, GLR, Marpa e analisadores de derivativos (existem muitas outras) que não foram relevantes neste caso.
Mas aparentemente não é isso que você tem em mente. Você deseja analisar uma sequência única que é uma sequência de documentos inequívocos e obter uma árvore de análise para cada um , ou algum tipo de representação estruturada, uma vez que você realmente não diz como a sintaxe de seus documentos é definida, de onde ela se encontra. um ponto de vista formal da linguagem. O que você tem é um algoritmo e tabelas que farão o trabalho de análise quando iniciados no início de um documento. Que assim seja.
O problema real é que seu fluxo de documentos contém um lixo considerável que separa os documentos. E parece que sua dificuldade é verificar esse lixo com rapidez suficiente. Sua técnica atual é começar do início e tentar digitalizar a partir do primeiro caractere, e pular para a reinicialização no próximo caractere sempre que falhar, até você digitalizar todo o documento. Em seguida, repita a indicação do primeiro caractere após a digitalização do documento.
Essa também é a solução sugerida por @amon na segunda parte de sua resposta .
Pode não ser uma solução muito rápida (não tenho como testar), porque é improvável que o código do analisador seja otimizado para ser iniciado com muita eficiência no início de um documento. Em uso normal, isso é feito apenas uma vez, para que não seja um ponto de acesso do ponto de vista da otimização. Portanto, sua felicidade moderada com esta solução não é muito surpreendente.
Então, o que você realmente precisa é de um algoritmo que encontre rapidamente o início de um documento que começa com uma grande quantidade de lixo. E você tem sorte: esses algoritmos existem. E eu tenho certeza que você sabe disso: é chamado de busca por um REGEX.
A solução simples
O que você precisa fazer é analisar a especificação de seus documentos para descobrir como esses documentos começam. Não sei exatamente como, pois não tenho certeza de como suas especificações de sintaxe são organizadas formalmente. Possivelmente todos eles começam com alguma palavra de uma lista finita, possivelmente misturada com alguma pontuação ou números. Isso é para você verificar.
O que você precisa fazer é definir um autômato de estado finito (FSA) ou, para a maioria dos programadores, uma expressão regular (REGEX) capaz de reconhecer os primeiros caracteres de um documento: quanto mais, melhor, mas não precisa ser muito. grande (pois isso pode levar tempo e espaço). Isso deve ser relativamente fácil de fazer a partir da especificação de seus documentos e provavelmente pode ser feito automaticamente com um programa que lê a especificação de seus documentos.
Depois de produzir seu regexp, você pode executá-lo no fluxo de entrada para chegar muito rapidamente ao início do seu primeiro (ou próximo) documento da seguinte maneira:
Eu assumo:
- docstart
é um regex que corresponde ao início de todos os documentos
- search(regex, stream)
é uma função que pesquisa stream
um substring que corresponda regex
. Quando ele retorna, o fluxo é reduzido ao seu sub-fluxo de sufixo, começando no início da primeira substring correspondente ou ao fluxo vazio, se nenhuma correspondência for encontrada.
- parse(stream)
tenta analisar um documento desde o início do fluxo (o que resta dele) e retorna a árvore de análise em qualquer formato ou falha. Quando ele retorna, o fluxo é reduzido ao seu subfluxo de sufixo, iniciando na posição imediatamente após o final do documento analisado. Chama uma exceção se a análise falhar.
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)
Observe que a remoção do primeiro caractere é necessária para que a próxima pesquisa não encontre novamente a mesma correspondência.
Obviamente, encurtar o fluxo é uma imagem. Pode ser apenas um índice no fluxo.
Uma observação final é que seu regex não precisa ser muito preciso, desde que reconheça todos os inícios. Se, ocasionalmente, reconhecer uma sequência que não possa ser o início de um documento (falso positivo), a única penalidade será o custo de uma chamada inútil para o analisador.
Portanto, isso pode ajudar a simplificar a regex, se útil.
Sobre a possibilidade de uma solução mais rápida
A solução acima deve funcionar muito bem na maioria dos casos. No entanto, se você tiver realmente muito lixo e terabytes de arquivo para processar, pode haver outros algoritmos que são executados mais rapidamente.
A idéia é derivada do algoritmo de busca de string de Boyer-Moore . Esse algoritmo pode pesquisar um fluxo em busca de uma única sequência extremamente rápida, porque usa uma análise estrutural da sequência para pular a leitura da maior parte do fluxo, pulando fragmentos sem sequer olhar para eles. É o algoritmo de pesquisa mais rápida para uma única string.
A dificuldade é que sua adaptação à pesquisa de expressões regulares, em vez de uma única sequência, parece muito delicada e pode não funcionar tão bem, dependendo dos recursos da expressão regular que você está considerando. Por sua vez, isso pode depender da sintaxe dos documentos que você está analisando. Mas não confie muito em mim, pois não tive tempo de fazer uma leitura cuidadosa dos documentos que encontrei.
Estou deixando você com um ou dois indicadores que encontrei na Web, incluindo um que aparentemente é um trabalho de pesquisa de referência , mas você deve considerar isso como mais especulativo, possivelmente pesquisador, a ser considerado apenas se você tiver fortes problemas de desempenho. E provavelmente não existe um programa de prateleira que o faça.