Академический Документы
Профессиональный Документы
Культура Документы
Juazeiro,
Junho de 2010
1
Documentação para o Programa que tem
como entrada uma Gramática Livre de
Contexto (GLC) e saída uma GLC Isenta de
Produções Unitárias
Juazeiro,
Junho de 2010
2
Sumário
1. Resumo.........................................................................................................................4
2. Fundamentação Teórica.............................................................................................5
3. Material e Método
3.1 Materiais Utilizados..............................................................................................6
3.2 Metodologia Utilizada..........................................................................................6
3.3 Estrutura do Programa........................................................................................6
4. Manual de Instalação..................................................................................................8
5. Manual do Usuário......................................................................................................8
6. Resultados.....................................................................................................................9
7. Referências.................................................................................................................11
8. Anexo..........................................................................................................................12
3
1. Resumo
4
2. Fundamentação Teórica
Uma GLC com produções unitárias é aquela gramática cuja suas produções são da
forma A→B, em que A e B são não-terminais. Essas produções costumam ser
descartadas das gramáticas livres de contexto porque nada acrescentam às formas
sentenciais às quais são aplicadas, constituindo mera renomeação de símbolos (no caso,
de A para B).
De acordo com o teorema para eliminação de produções unitárias encontrado em
[1], toda linguagem livre de contexto pode ser gerada por uma gramática livre de
contexto isenta de produções unitárias.
O Algoritmo abaixo mostra como transformar gramáticas livres de contexto
arbitrárias em outras equivalentes sem produções unitárias.
Eliminação de produções unitárias em gramáticas livres de contexto:
• Entrada: uma gramática livre e contexto G = (V, Σ, P, S).
• Saída: uma gramática livre de contexto G′ = (V, Σ, P′, S), tal que L(G′)= L(G) e
G′ não contém produções unitárias.
• Método:
1. Para cada A ∈ N, constrói-se NA tal que NA = {B ∈ N | A ⇒* B1} da
seguinte forma:
a) N0 ← {A};
b) i ← 1;
c) Ni ← Ni−1 ∪ {C | B → C ∈ P e B ∈ Ni−1};
d) Se Ni = Ni−1, então:
1. i ← i+1;
2. Desviar para (1.c);
Caso contrário:
NA ← Ni−1;
2. P′ ← {A → α ∈ P | α N};
3. Para todo B ∈ NA, se B → α ∈ P, e α N, então P' ← P' ∪ {A → α}.
1
Devem-se considerar apenas as derivações que são obtidas pela aplicação exclusiva de regras unitárias.
5
3. Material e Método
O projeto como todo está dividido em quatro classes todas no mesmo pacote
(package automotos) que juntas regem todo o funcionamento do programa. A classe
Utils.java foi criada para somente devolver a classe que a chama a extensão dos
arquivos existentes no computador do usuário. Para tanto, ela implementa o método
getExtension(File f) que obtém o tipo de extensão do arquivo correspondente passado
6
como argumento. Já a classe ExtencaoTxt.java estende a classe FileFilter que é usada
para indicar quais arquivos no sistema do usuário são mostrados na caixa de diálogo de
navegação de arquivos, com isso a classe ExtencaoTxt.java usa um objeto da classe
Utils.java a fim de comparar todas as extensões dos arquivos e mostrar somente os
diretório e os arquivos .txt do sistema.
Outra classe que compõe o projeto é a classe GramaticaLC.java. É nessa classe
que se encontra toda lógica programacional envolvida no projeto. Nela foi desenvolvida
toda a interface que auxilia o usuário a interagir com o programa para obter a gramática
livre de contexto isenta de produções unitárias que gera a mesma linguagem da
gramática digitada ou carregada de um arquivo pelo usuário. A classe usa os respectivos
métodos para abrir um arquivo de texto solicitado pelo usuário, obter a gramática livre
de contexto sem produções unitárias e salvar a referida gramática, bem como métodos
para quando o usuário solicitar ajuda e desejar sair do sistema.
O método booleano validarGramatica() da classe GramaticaLC.java retorna
true se a gramática é válida ou false se inválida, ou seja, o método analisa a entrada
digitada pelo usuário e mostra uma mensagem de erro se a gramática for inválida. Só é
aceita as gramática que obedecerem a forma definida pelo projeto, conforme visto
anteriormente na Metodologia Utilizada. Na seção 9 é mostrada sua implementação.
Ainda dentro da classe GramaticaLC.java, um método bastante útil para a
implementação do projeto e que tem como base o algoritmo descrito na seção 2
(Fundamentação Teórica) para eliminação de produções unitárias é o método
eliminarProducoesUnitarias(). Esse método declara duas matrizes bidimensionais do
tipo char (p e p2) para guardar as respectivas regras de produções das gramáticas livres
de contexto, onde em cada linha da matriz tem-se os caracteres com os símbolos de cada
regra de produção composta pela gramática. Na matriz p é atribuída os símbolos
(caracteres) das regras de produção da gramática digitada pelo usuário ou lida de um
arquivo texto. Já a matriz p2 é utilizada para guardar os símbolos das regras da
gramática livre de contexto isentas de produções unitárias, ou seja, em cada linha de p2
vai ter todos os caracteres representando os símbolos de cada regra da gramática sem
produções unitárias.
O método eliminarProducoesUnitarias() utiliza o método booleano
isUnitaria(char[] producao) que é usado para verificar se a regra de produção passada
como argumento para esse método é unitária. O método eliminarProducoesUnitarias()
se encontra em anexo na seção 9.
Por fim, a classe Main.java que é responsável pela execução do projeto. Nela é
criada um objeto do tipo GramaticaLC chamando o construtor dessa classe, onde é
iniciado toda execução do projeto.
7
4. Manual de instalação
Primeiramente, para usufruir das facilidades oferecidas pelo programa, o usuário
deve ter o Sistema Operacional Windows (XP/Vista/7/98/2000/2003) com o Java
Runtime Environment (JRE) instalado (JRE significa Ambiente de Tempo de
Execução Java, e é utilizado para executar as aplicações da plataforma Java). Se caso o
usuário não tiver o JRE em seu sistema, poderá fazer o download em:
http://javadl.sun.com/webapps/download/AutoDL?BundleId=38663&file=/jre-6u19-
windows-i586-s.exe.
Após verificar que o JRE está devidamente instalado, o usuário poderá copiar
para o seu computador no diretório a sua escolha o arquivo com o nome
ProjetoAutomatos que se encontra no cd de instalação, logo após ter instalado o arquivo
no computador o usuário poderá remover o cd, chegando ao fim o processo de
instalação.
5. Manual do usuário
Obedecidas as orientações descritas na seção Manual de Instalação, o usuário
poderá executar o programa clicando no arquivo ProjetoAutomatos que se encontra no
diretório em que o usuário instalou o programa, assim uma janela abrirá para começar a
interação com o usuário, como mostra a Figura 01.
O usuário poderá digitar no campo “Digite a Gramática Livre de Contexto que
gera a linguagem:” uma GLC e clicar no botão “Ok”, logo após, se a garmática digitada
estiver na forma correta, conforme as regras da subseção 3.2, uma GLC isenta de
produções unitárias que gera a mesma linguagem da referida GLC digitada pelo usuário
aparecerá no campo “Gramática Livre de Contexto sem Produções Unitárias:”, como
ilustra a Figura 2.
Além disso, o usuário poderá abrir um arquivo texto que tem como conteúdo
uma GLC na barra de menu “Arquivo” no item “Abrir” da interface para ser carregado
para o programa.
Se o usuário quiser salvar a GLC isenta de produções unitárias em um arquivo
texto é só clicar no botão “Salvar Gramática”, desse modo é criado um arquivo com o
nome GLCsemRUnitarias.txt no diretório onde se encontra o programa. O arquivo
gerado contém as regras de produções da GLC inicial de entrada e as regras de
produções isenta de regras unitárias da GLC de saída que gera a mesma linguagem da
gramática inicial.
6. Resultados
Na tela inicial do programa apresentada na Figura 01, foi digitado uma GLC no
campo “Digite a Gramática Livre de Contexto que gera a linguagem:”, logo após
clicou-se em “Ok”, como a gramática está de acordo com as regras da subseção 3.2, no
campo “Gramática Livre de Contexto sem Produções Unitárias:” será visualizada uma
GLC isenta de produções unitárias que gera a mesma linguagem da referida GLC
digitada pelo usuário.
Assim, o programa garante que sendo digitada uma GLC, uma GLC isenta de
produções unitárias que gera a mesma linguagem é produzida, conforme o teorema
citado na seção 2.
8
Figura 01: Interface do programa com sua configuração inicial.
9
7. Referências
[1] Ramos, M. V. M.; T. H.; Neto J. J.; Vega, I. S.. Linguagens Formais: Teoria,
Modelagem e Implementação. Bookman, 2009.
1
8. Anexo
1
}
} else
{
return false; /* se o usuário digitou ao final da gramática
o símbolo # a gramática é inválida */
}
}
}
}
return true; // se o usuário digitou uma gramática válida o método retorna true
}
/* método que proporciona a eliminação das regras de produções unitárias das regras da
gramática */
public void eliminarProducoesUnitarias()
{
int i = 0, j = 0, k = 0, nl = 0, achouIgual = 0, mp = 0;
/* nl corresponde a quantidade de não-terminais na matriz de não-terminais N,
a variável mp significa a quantidade de símbolos da maior regra de produção da
gramática de entrada, sendo usada para definir o tamanho da coluna da matriz de
regras de produções usada para manipular a lógica do método */
/* o for é usado para contar quantas produções existem na gramática digitada pelo
usuário ou lida de um arquivo texto */
for(; i < s.length; i++)
{
if(s[i] == 35) /* compara se o símbolo corrente é o caracter '#', pois cada
regra é separada por '#' */
{
contp++; // incrementa o número de regras de produções
if(k > mp) // verifica se ocorreu uma regra com maior número de símbolos
{
mp = k; // a variável mp recebe a maior quantidade de símbolos
}
1
/*esta parte (contp++ e mp++) esta garantindo que nenhum vetor seja indexado
fora da faixa, acrescetando um símbolo ou uma produção a mais */
contp++;
mp++;
1
caso seja verdadeiro achouigual =1 */
for (j = 0; j < nl; j++)
{
if (p[i][0] == N[j][0])
{
N[j][nc[j]] = p[i][1];
achouIgual = 1;
nc[j]++;
}
}
/*caso o terminal com produção unitária ainda não esteja
em N ela será copiada*/
if (achouIgual == 0)
{
N[nl][0] = p[i][0];
N[nl][1] = p[i][1];
/*nc é para contar quantos não terminais o não terminal
em questão contém, por exemplo SA#SB#SC então nc[S]=4,
contando com ele mesmo */
nc[nl] = nc[nl] + 2;
nl++;
}
}
} //coloca as produções não unitárias na matriz pnu
else {
for (j = 0; j < mp; j++)
{
pnu[k][j] = p[i][j];
}
k++;
}
}
1
}
}
if (achouIgual == 0)
{
N[i][nc[i]] = N[j][w];
nc[i]++;
}
}
}
}
}
}
/* achou igual vai "apontar" para a última linha da matriz p2 para colocar as
produções não unitárias */
for (i = 0, achouIgual = 0; i < contp * contp; i++)
{
if (p2[achouIgual][0] >= 65 && p2[achouIgual][0] <= 90)
{
achouIgual++;
}
}
//copia as produções não unitárias contida em pnu para p2
int aux = 0;
for (i = 0; i < contp; i++)
{
1
aux = 0;
1
}
}
s2 = new char[aux];
/* aqui é passado para o vetor char s2 a GLC isenta de produções unitárias que está
em p2 */
for (i = k = 0; p2[i][0] != 0; i++, k++)
{
//copia as produções para s2
for (j = 0; j < mp; j++)
{
//copia para s2 apenas valores válidos
if ((p2[i][j] >= 65 && p2[i][j] <= 90) || (p2[i][j] >= 97 && p2[i][j] <= 122))
{
if (k < aux)
{
s2[k] = p2[i][j];
k++;
}
}
}
if (s2[k - 1] == '#') /* tira o caracter '#' repetidos que ficam com a retiradas das
produções repetidas */
{
k--;
}
}