Expressões regulares + programação lógica. Qual é o resultado?

Olá queridos leitores.

Expressões regulares são uma coisa bem conhecida que é usada em vários projetos, na maioria das vezes para casos não muito complicados de analisar textos estruturados. À primeira vista, estar envolvido em uma tarefa tão diferente como a síntese reversa de modelos de programa (quando houver código de programa gerado automaticamente por algum sistema de acordo com algum modelo de bloco do problema que está sendo resolvido, e é necessário recriar o modelo original usando esse código), bem como sintetizar modelos de programa usando texto Na descrição da tarefa, encontrei o problema de analisar textos, ou melhor, identificar fragmentos de texto em alguns modelos personalizados. Eu queria obter uma solução bastante simples e flexível (personalizável). Expressões regulares dinamicamente não pareciam, porque mesmo em uma tarefa simples como verificar uma palavra em um dicionário, infelizmente, era necessária uma lista cuidadosa de todas as opções nessa expressão. E eles não construíram uma árvore de análise. No entanto, eles poderiam claramente ser melhorados. Isso será discutido.

Portanto, as seguintes tarefas foram definidas:

  1. A expressão regular deve ser capaz de produzir uma árvore de análise. É necessário implementar meios padrão de acesso a essa árvore.
  2. A expressão regular deve poder incluir verificações nos fragmentos encontrados no dicionário (correspondência exata ou não estrita de acordo com Levenshtein), bem como verificações mais complexas em várias tabelas ao mesmo tempo.
  3. Além das verificações simples (listadas acima), eu gostaria de ter mais verificações difusas, por exemplo, a compatibilidade de palavras e expressões, uma rede neural

Analise a árvore.


Em expressões regulares, os fragmentos analisados ​​são identificados pelo número de colchetes. Isso, para dizer o mínimo, é inconveniente; portanto, foi tomada uma decisão sobre a possibilidade de nomear os colchetes. A propósito, são esses nomes que devem aparecer na árvore de análise. A sintaxe foi escolhida simples:

(_)->{_} 

Se após parênteses na expressão original houver algum operador (*, +, etc.), ele "se moverá" atrás da chave direita. Por exemplo:

 (\w+\s)->{A}+ 

Nada impede nomes e parênteses, por exemplo:

 ((\w+)->{ID}\s)->{A}+ 

No último exemplo, a expressão regular modificada gerará uma árvore de análise com alguma raiz condicional; no próximo nível, há instâncias de A (pode haver mais de um); no próximo nível, existem valores de ID. É conveniente acessar essa árvore usando o XPath, que eu implementei, por exemplo, uma solicitação desse tipo é possível:

 //A[2]/ID[text()!=""]/text() 

O Word verifica dicionários, tabelas e uma rede neural simples


A análise de uma expressão regular é muito semelhante à análise de uma expressão lógica simples, por exemplo, na linguagem Prolog. Isso leva à idéia de que fragmentos do tipo Prolog, que serão:

a) cadeias de várias verificações. Isso não é difícil, principalmente porque as variáveis ​​já apareceram (na forma de colchetes);
b) ou reposição de tabelas / dicionários com fragmentos detectados;
c) ou exceções das tabelas / dicionários dos fragmentos detectados;
d) ou uma equipe de criação / treinamento de redes neurais.

A sintaxe geral aqui seria:

 (_)_=>{1,2,...} 

operation_symbol depende da operação: verificação (?), reabastecimento (+), exclusão (-), criação / treinamento (*). Quanto aos predicados, o nome do predicado (padrão ou seu) e uma lista de seus parâmetros entre parênteses. Os parâmetros podem ser constantes, variáveis ​​de entrada, variáveis ​​de saída (prefixadas com um sinal "$"), um sinal de um valor arbitrário "_", uma referência ao valor atual do fragmento expression_ (caractere único "$"). A análise dessa expressão é considerada bem-sucedida se todos os predicados da cadeia forem bem-sucedidos.

Por exemplo, a expressão:

 ([--]+)->{V1}\s+([--]+)->{V2}()?=>{check(V1},check(V2),correlate(V1,V2)} 

seleciona duas palavras consecutivas em russo e as coloca nas variáveis ​​V1 e V2 e, em seguida, verifica essas palavras com a verificação de predicado (pode ser uma verificação simples na tabela) e, em conclusão, com o correlato de predicado (também pode haver uma verificação na tabela). O tipo de verificação (estrita ou não estrita) é determinado pela especificação do predicado.

Se a tabela correlacionada não contiver as próprias palavras, mas alguns códigos de palavras e uma característica de sua compatibilidade, poderá haver uma expressão assim:

 ()->{C1}()->{C2}([--]+)->{check($,$C1}\s+([--]+)->{V2}()?=>{check(V2,$C2),correlate(C1,C2,1)} 

Aqui, duas variáveis ​​são introduzidas pela primeira vez, C1 e C2. O predicado correlato também pode ser uma rede neural com duas entradas (códigos de palavras) e uma saída (compatibilidade), treinada de acordo com alguns conjuntos predefinidos ou dinamicamente montados (durante a operação de expressão regular).

Resta acrescentar que diretivas especiais paralelas e seqüenciais também podem ser especificadas como predicados, que, respectivamente, incluem e calculam o paralelismo de execução na cadeia de predicados (que é convertida na árvore de dependência de predicados, segundo a qual é paralelizada). Além disso, você pode ativar um modo especial no qual é feita uma tentativa de prever dinamicamente o tempo de execução de predicados individuais e decidir se a simultaneidade será eficaz ou vice-versa, trará apenas custos adicionais.

Conclusão


Todas as modificações de expressão regular descritas são implementadas no protótipo (modificação do regexpr.pas padrão) no Free Pascal.

Espero que essas idéias sejam úteis para alguém.

Agora, usando expressões lógicas regulares e programação em um Prolog puro, foi possível, em primeiro lugar, escrever uma adição ao sistema de geração de programas que restaura o modelo de programa original a partir do código gerado anteriormente por ele e, em segundo lugar, criar elementos da linguagem natural para esse sistema interface (a declaração do problema é adotada em um idioma russo muito simplificado e é formulado um modelo do problema, pelo qual o programa já é gerado)

Source: https://habr.com/ru/post/pt415797/


All Articles