P-FLAT --- Prolog toolkit for Formal Languages and Automata Theory

Artur Miguel Dias

Última modificação: 21/Mar/2006
Enviar comentários e correcções para amd@di.fct.unl.pt

Changelog

21/MAR/2006 Foi corrigido um erro na expressão regular usada nos primeiros exemplos, nesta página.
10/MAR/2006 Primeira versão deste documento.

Apresentação

O P-FLAT consiste numa implementação pedagógica duma parte substancial dos conceitos estudados em LFA. Está escrito em Prolog, sendo o código da implementação bastante fiel às definições apresentadas na cadeira.

Interactua-se com o sistema através a linha de comandos do Prolog ou usando scripts escritos em Prolog.

As entidades suportadas pelo programa são as seguintes:

três níveis de utilização do P-FLAT:

O P-FLAT está sendo desenvolvido por Michel Wermelinger e Artur Miguel Dias. A ideia original foi de Michel Wermelinger. Eis um curto artigo onde se apresenta o sistema de forma introdutória.


Activação

Para correr o P-FLAT no Linux, use o comando "pl -s pflat.pl". No Windows basta clicar no ícone do ficheiro "pflat.pl".


Uso através da linha de comando

Efectuemos algumas experiências simples usando a expressão regular (0 + 1 0* 1)*, que descreve a linguagem das sequências binárias onde o símbolo "1" ocorre um número par de vezes. No que se segue, o input do utilizador aparece a vermelho. Repare também que a expressão regular teve de ser escrita usando sintaxe modificada, para poder ser lida pelo Prolog.

Eis a documentação dos predicados usados nesta secção, copiada directamente do ficheiro fonte do P-FLAT: Para ter uma ideia das outras habilidades do P-FLAT, veja a secção "Predicados disponíveis", perto do final deste documento.

Escrita de scripts

Apesar de ser possível usar o P-FLAT da forma exemplificada na secção anterior, trabalhando directamente sobre a linha de comando, muitas vezes é melhor registar em ficheiro as declarações e os comandos que nos interessam e depois consultar esse ficheiro. Cria-se assim um script prático de usar e que pode ser guardado para o futuro.

A escrita de um script pode revelar-se um pouco trabalhosa se se pretender produzir output elaborado. Para ajudar, o P-FLAT disponibiliza os predicados execute/1 e execute/3 que sabem executar comandos, gerando automaticamente output razoavelmente expressivo.

Para exemplificar, eis um script contendo uma declaração e diversos comandos:

Para consultar o ficheiro "fich.pl", você faz: Neste caso, o output produzido é quase igual ao da secção anterior.

Os ficheiros "tutorial.pl" e "examples.pl" fazem parte da distribuição do P-FLAT. São scripts que ilustram diversos aspectos da utilização do P-FLAT.

Eis a documentação dos predicados execute/1 e execute/3, copiada directamente do ficheiro fonte do P-FLAT:


Declarações

O P-FLAT permite declarar entidades em ficheiro, associando um nome a cada uma delas. Por exemplo, é desta forma que se declara uma expressão regular chamada evenRE. Apresentam-se agora diversas declarações para ilustrar todo o tipo de entidades declaráveis em P-FLAT (existem nove tipos ao todo):

Declaração de linguagens e de predicados

No P-FLAT, quase todos os tipos de declarações são auto-suficientes, no sentido em que a própria declaração já inclui toda a informação necessária para caracterizar a entidade em causa. Há duas excepções: as declarações de linguagens e as declarações de predicados.

Declaração de linguagens

Deve complementar-se a declaração duma linguagem com um conjunto de factos Prolog que exemplificam palavras que pertencem à linguagem e palavras que não pertencem à linguagem. Chama-se a esse factos testes unitários. Os testes unitários têm a forma

e afirmam que a palavra Word pertence ou não à linguagem Name, consoante o valor de Boolean.

Para exemplificar, eis uma declaração mais completa da linguagem evenL:

Recomendamos que você defina sempre pelos menos 5 casos positivos e cinco casos negativos, tendo ainda o cuidado de identificar as situações limite mais importantes.

A importância dos testes unitários

Imagine que você tem em mente uma determinada linguagem e pretende representá-la usando uma das técnicas estudadas em LFA, digamos usando um autómato finito. Nesse caso, deve declarar primeiro a linguagem e associar-lhe um conjunto de testes unitários. Só depois é que deve tentar escrever o autómato. Vale a pena o primeiro passo pelas seguintes razões:

Declaração de predicados

Cada predicado P-FLAT é obrigatoriamente definido usando um predicado Prolog com aridade 1. O predicado Prolog tem de ter o mesmo nome do predicado declarado.

Para exemplificar, eis a declaração completa do predicado evenP:

Os predicados constituem a forma mais directa de definir linguagens no P-FLAT. Um predicado P define directamente a linguagem {w: P(w)}).

Validações

Validação de declarações

Para validar uma declaração, usa-se o comando onde Name representa o nome da entidade a validar.

Use sempre o comando check_declaration/1 após cada declaração. Assim, como neste exemplo:

Vale a pena validar todas as declarações, pois são dezenas as situações inválidas e as situações suspeitas que o P-FLAT consegue detectar. As primeiras dão origem a mensagens de erro e as segundas dão origem a warnings.

só para dar uma ideia, eis apenas alguns dos muitos problemas que o P-FLAT detecta:

Validação de definições

Para validar uma definição face a um conjunto de testes unitários, usa-se o comando onde Def representa uma entidade que supostamente caracteriza a linguagem Lang. A definição Def é validada face ao conjunto de testes unitários para Lang.

Use sempre o comando test_definition/2 após cada declaração, para validar a entidade declarada. Isto aplica-se a predicados, expressões regulares, autómatos finitos, gramáticas independentes do contexto, autómatos de pilha e máquinas de Turing.

Como para cada declaração é importante validar, não só a declaração, como também a entidade declarada, torna-se quase inevitável que cada declaração acabe por conduzir à escrita de três linhas. Assim:


Juntando tudo

Juntando tudo o que aprendemos até agora, eis um exemplo realista de script, cujo estilo você poderá imitar.

Neste script primeiro declara-se a linguagem evalL, escrevem-se diversos testes unitários para ela e valida-se a declaração. Seguidamente, declara-se a expressão regular evenRE, valida-se a correcção dessa declaração e valida-se a definição evenRE face à linguagem evenL. Só depois de ter tudo validado, é que se começam a fazer experiências com a expressão regular.


Predicados disponíveis

Predicados universais

Alguns dos predicados do P-FLAT aplicam-se a quase todas as entidades e por isso dizem-se predicados universais. Eis a documentação dos predicados universais, copiada directamente do ficheiro fonte do P-FLAT:

Predicados particulares

Outros predicados do P-FLAT só se aplicam a a entidades particulares, pelo que se dizem predicados particulares. Em muitos casos, o nome de cada predicado particular tem um prefixo que indica o tipo de entidade a que se aplica. Eis a documentação dos predicados particulares mais importantes, copiada directamente do ficheiro fonte do P-FLAT:


Aprender mais sobre o P-FLAT

Se desejar ficar um perito no P-FLAT, então consulte o script "tutorial.pl" e observe o output a ser gerado ao mesmo tempo que estuda o código Prolog que lhe deu origem. É muito instrutivo.

Corra também o script "examples.pl".

Finalmente, a fonte de informação mais detalhada para o P-FLAT é o seu próprio código fonte. O código segue fielmente as definições apresentadas nas aulas teóricas e encontra-se profusamente comentado.