Parsing Preditivo. Antes de ser abordado o Parsing Preditivo, será apresentado o Analisador Sintático Descendente Recursivo.

Documentos relacionados
O uso de gramáticas traz vantagens para projetistas de linguagens e escritores de compiladores pelas seguintes razões:

Revisão: gramáticas (parte 2)

V Análise Sintática. V.1.1 Gramáticas Livres de Contexto Definições de GLC

Compiladores Aula 4. Celso Olivete Júnior.

Compiladores. Exemplo. Caraterísticas de Gramáticas. A αβ 1 αβ 2. A αx X β 1 β 2. Lembrando... Gramáticas Livres de Contexto

Análise sintática. Análise sintática. Top-down ou descendente. Com retrocesso: por tentativa e erro. Preditiva: para gramáticas LL(1) 09/04/2012

Compiladores Aula 6. Celso Olivete Júnior.

Vantagens de uma Gramática. Sintaxe de uma Linguagem. Analisador Sintático - Parser. Papel do Analisador Sintático. Tiposde Parsers para Gramáticas

Análise Sintática (Cap. 04) Análise Sintática Descendente

Compiladores. Parser LL 10/13/2008

Análise Sintática II: Analisadores Descendentes Preditivos

Compiladores Analisador Sintático. Prof. Antonio Felicio Netto Ciência da Computação

V Teoria de Parsing. Termos Básicos: Parser Analisador Sintático Parsing Analise Sintática Parse Representação da analise efetuada

COMPILADORES. Análise sintática. Prof. Geovane Griesang Universidade de Santa Cruz do Sul UNISC Departamento de informática

Analisadores Descendentes Tabulares; Cjs First Follow

IV Gramáticas Livres de Contexto

Compiladores. Análise Sintática

Compiladores. Análise Sintática

Se o símbolo inicial não fizer parte do conjunto de símbolos férteis, a linguagem gerada pela gramática é vazia.

COMPILADORES. Análise sintática. Prof. Geovane Griesang Universidade de Santa Cruz do Sul UNISC Departamento de informática

Construção de Compiladores Aula 17 - Análise Sintática Descendente

Análise Sintática LL(1)

Construção de Compiladores Aula 16 - Análise Sintática

Plano da aula. Compiladores. Os erros típicos são sintáticos. Análise Sintática. Usando Gramáticas. Os erros típicos são sintáticos

Geração de Código Intermediário

Revisão. Fases da dacompilação

Compiladores Aula 5. Celso Olivete Júnior.

INE5318 Construção de Compiladores. AULA 4: Análise Sintática

Compiladores - Especificando Sintaxe

Compiladores - Análise LL(1)

COMPILADORES. Revisão Linguagens formais Parte 02. Prof. Geovane Griesang

Compiladores - Análise LL(1)

INE5317 Linguagens Formais e Compiladores. AULA 10: Anális e S intática

Análise Sintática. Fabiano Baldo

Análise sintática. Questão. E se a análise sintática pudesse ser modelada por autômatos?

Análise sintática. Prof. Thiago A. S. Pardo. Análise sintática ascendente

Compiladores - Análise Ascendente

Compiladores - Análise Ascendente

Análise Sintática Bottom-up

Construção de Compiladores

Compiladores - Análise SLR

Compiladores - Gramáticas

Linguagens e Programação Gramáticas. Paulo Proença

Compiladores - Gramáticas

Análise sintática. Análise sintática ascendente. Bottom-up, ascendente ou redutiva. Analisadores de precedência de operadores Analisadores LR

Análise Sintáctica. Definições: Conjuntos First() e Follow() Compiladores, Aula Nº 19 João M. P. Cardoso. Conjunto First(β)

Como construir um compilador utilizando ferramentas Java

Compiladores - Análise Preditiva

Análise sintática. Análise sintática ascendente. Parte-se dos símbolos terminais em direção ao símbolo inicial da gramática. Derivação mais à direita

Análise Sintática II. Eduardo Ferreira dos Santos. Outubro, Ciência da Computação Centro Universitário de Brasília UniCEUB 1 / 34

Um Compilador Simples. Definição de uma Linguagem. Estrutura de Vanguarda. Gramática Livre de Contexto. Exemplo 1

Gramáticas Livres de Contexto Parte 1

V.2 Especificação Sintática de Linguagens de Programação

Uma gramática é ambígua se existe alguma cadeia para qual ela tem mais de uma árvore sintática

Compiladores - Gramáticas

Analisadores Sintáticos LR

Apresentação. !! Familiarização com os métodos de construção de compiladores de linguagens e com as técnicas de compilação mais habituais.

MAB Análise Sintática. Wednesday, April 4, 12

Análise Sintática Descendente

Universidade Federal do ABC Rua Santa Adélia, Bairro Bangu - Santo André - SP - Brasil CEP Telefone/Fax:

MAB Análise Sintática. Wednesday, August 31, 11

Introdução Análise Sintática Descendente Análise Sintática Ascendente. Aula Prática. Fernando Antônio Asevedo Nóbrega

BNF (Backus-Naur Form) Gramática Livres de Contexto / Estruturas Recursivas

Linguagens Livres de Contexto

Compiladores. Prof. Bruno Moreno Aula 8 02/05/2011

Compilação: Erros. Detecção de Erros: * Analisadores Top-Down - Preditivo Tabular (LL) - Feito a mão. * Analisadores Botton-Up: - Shift-Reduce (SLR)

INE5317 Linguagens Formais e Compiladores AULA 9: Propriedades e Reconhecimento das Linguagens Livres do Contexto

Aula de 28/10/2013. sticas; Implementação. em Ruby

Análise Sintática Introdução

ACH2043 INTRODUÇÃO À TEORIA DA COMPUTAÇÃO

Marcos Castilho. DInf/UFPR. 21 de março de 2019

Compiladores. Capítulo 3: Análise Sintática Introdução

Compiladores - Análise Recursiva

Disciplina: LINGUAGENS FORMAIS, AUTÔMATOS E COMPUTABILIDADE Prof. Jefferson Morais

Análise Sintática I. Eduardo Ferreira dos Santos. Abril, Ciência da Computação Centro Universitário de Brasília UniCEUB 1 / 42

Revisão de GLC e Analisadores Descendentes

Folha 4.1 Análise sintática descendente

COMPILADORES. Análise sintática. Prof. Geovane Griesang Universidade de Santa Cruz do Sul UNISC Departamento de informática

Reduce: reduz o que está imediatamente à esquerda do foco usando uma produção

ACH2043 INTRODUÇÃO À TEORIA DA COMPUTAÇÃO

Análise sintática. Prof. Thiago A. S. Pardo Tratamento de erros sintáticos

QUESTÃO 1 (0,6 ponto) Classifique os processadores de linguagens com relação aos tipos das linguagens-fonte e objeto.

Compiladores - Análise Recursiva

LFA Aula 09. Gramáticas e Linguagens Livres de Contexto 18/01/2016. Linguagens Formais e Autômatos. Celso Olivete Júnior.

LINGUAGENS FORMAIS E AUTÔMATOS

15/03/2018. Professor Ariel da Silva Dias Aspectos sintáticos e semânticos básicos de linguagens de programação

Compiladores - Análise Preditiva

Concurso Público para provimento de cargo efetivo de Docentes. Edital 20/2015 CIÊNCIA DA COMPUTAÇÃO II Campus Rio Pomba

Função, interação com o compilador Especificação e reconhecimento de tokens Implementação Tratamento de erros. Prof. Thiago A. S.

Gramá3ca Livre de Contexto (GLC)

FERRAMENTA DE AUXÍLIO AO PROCESSO DE DESENVOLVIMENTO DE SOFTWARE INTEGRANDO TECNOLOGIAS OTIMIZADORAS

Paradigmas de Linguagem de Programação

Compiladores. Top-Down x Bottom Up. Plano da aula. Redução exemplo 1. Redução exemplo 1. Lembrando: construir a tabela de análise LL(1) A Abc b B d

Análise Sintática. Eduardo Ferreira dos Santos. Outubro, Ciência da Computação Centro Universitário de Brasília UniCEUB 1 / 18

Linguagens Formais e Autômatos P. Blauth Menezes

Capítulo II Gramáticas

Automata e Linguagens Formais

COMPILADORES. Análise sintática. Prof. Geovane Griesang Universidade de Santa Cruz do Sul UNISC Departamento de informática

Compiladores. Bruno Lopes. Bruno Lopes Compiladores 1 / 30. Instituto de C

Transcrição:

UPE Caruaru Sistemas de Informação Disciplina: Compiladores Prof.: Paulemir G. Campos Parsing Preditivo Antes de ser abordado o Parsing Preditivo, será apresentado o Analisador Sintático Descendente Recursivo. Analisador Sintático Descendente Recursivo (ASDR) O analisador sintático descendente recursivo é escrito na forma de um conjunto de procedimentos, um procedimento para cada elemento não-terminal da gramática (sem retrocesso). Exemplo: Sejam as seguintes produções: <cmd> begin <lista_cmds> end while <condição> do <cmd> if <condição> then <cmd> As palavras_chave begin, while e if indicam qual das alternativas será a única possibilidade de se encontrar um dado comando. Adaptado de notas de aulas do prof. Giuseppe Mongiovi do DI/UFPB. 1

Limitações do ASDR: Entra em ciclo (loop) para gramáticas recursivas à esquerda; Não lida com regras não-determinísticas(a::=αβ e A::=αγ); Na implementação requer uma linguagem com recursividade. Problema de recursividade Para que se possa construir um analisador sintático descendente, uma gramática não pode ter regras recursivas à esquerda (diretas ou indiretas). Uma gramática é recursiva à esquerda se tem produções da forma: U ::= Uα ou U =>+ Uα Nesse caso, qualquer algoritmo que implemente um analisador descendente vai entrar em ciclo ("loop") infinito. Eliminação da recursividade à esquerda Seja a seguinte gramática G(A) A ::= Aα β L(G(A)) = {βα n n = 0, 1,...} A recursividade pode ser eliminada substituindo-se as produções de G(A) por: A ::= βa' A'::= αa' ε é equivalente a A ::= β{α}* Adaptado de notas de aulas do prof. Giuseppe Mongiovi do DI/UFPB. 2

Exemplo: G(E) recursiva (direta) G (E) não recursiva à esquerda à esquerda E ::= E+ T T E ::= T E' E' ::= + T E' ε T ::= T* F F T ::= F T' T' ::= * F T' ε F ::= ID ( E ) F ::= ID ( E ) OBS: Na realidade, a recursividade foi transferida para a direita. Em geral, a recursividade direta à esquerda pode ser eliminada como segue: Sejam as produções do tipo: A ::= Aα 1 Aα 2... Aα m β 1 β 2... β n, com cabeça(β i ) A p/ i = 1, 2,... n Então: A ::= β 1 A β 2 A... β n A A ::= α 1 A α 2 A... α m A ε OBS: o processo elimina toda recursividade direta à esquerda (desde que os α i s ε), mas, não elimina toda recursividade à esquerda. Adaptado de notas de aulas do prof. Giuseppe Mongiovi do DI/UFPB. 3

Exemplo: Seja a seguinte gramática G(S) S ::= Aa b A ::= Ac Sd e G(S) é recursiva à esquerda em S S Aa Sda (S + Sda) Solução: Usar um algoritmo geral de eliminação de recursividade à esquerda. Algoritmo: Elimina a recursividade à esquerda de gramáticas sem ciclos (derivações da forma A + A) e sem ε-produções (produções da forma A ε) 1. Organize os símbolos não_terminais da gramática em uma certa ordem A 1, A 2,...,A n 2. para i := 1 até n faça para j := 1 até i 1 faça substitua cada produção da forma A i ::= A j γ pelas produções A i ::= δ 1 γ δ 2 γ... δ k γ, onde A j ::= δ 1 δ 2... δ k ; elimine a recursividade direta à esquerda das A i s produções Adaptado de notas de aulas do prof. Giuseppe Mongiovi do DI/UFPB. 4

Exemplo: Eliminar a recursividade à esquerda da seguinte Gramática G(S) S ::= Aa b A ::= Ac Sd e A 1 ::= A 2 a b A 2 ::= A 2 c A 1 d e S (A 1 ) não tem recursividade direta à esquerda A 2 ::= A 1 d A 2 ::= A 2 ad bd i j γ δ1 δ2 Eliminando a recursividade direta de A 2 temos: A 1 ::= A 2 a b A 2 ::= bda 2 ea 2 A 2 ::= ca 2 ada 2 ε S ::= Aa b A ::= bda ea A ::= ca ada ε Problema das produções não-determinísticas Regras do tipo: 1) A::=αβ 2) A::=αγ conduzem o analisador sintático a uma situação de indefinição. A partir do ponto A, na árvore de derivação sintática, para se chegar à cadeia α que regra usar, a regra 1 ou a 2? Adaptado de notas de aulas do prof. Giuseppe Mongiovi do DI/UFPB. 5

Esse problema pode ser facilmente contornado transformando essas duas regras em: 3) A ::= αc 4) C ::= β γ Problema da linguagem de programação não recursiva para implementar o analisador sintático Na indisponibilidade de uma linguagem de programação recursiva p/ implementar o analisador (ou por questões de eficiência!!!), podemos utilizar um Analisador Sintático Descendente Preditor ou Parsing Preditivo (ou analisador de gramáticas LL(k)). A idéia do analisador LL(k) ("Left-to-right Left-mostderivation k") é de que basta olharmos no máximo k símbolos à frente na sentença, a partir do ponto em que estamos na ADS, para que possamos decidir que regra de produção aplicar. Adaptado de notas de aulas do prof. Giuseppe Mongiovi do DI/UFPB. 6

Exemplo: S ::= as bs c G(S) é LL(1) w = abc w = bac S ::= abs acs ad G (S) é LL(2) w = abacad w = acad Em termos de linguagens de programação, quase sempre é possível obter-se uma gramática LL(1) que permita o reconhecimento sintático de programas através de um analisador LL(1), que é bastante simples de implementar. ASD Preditor ou Parsing Preditivo Implementa o descendente recursivo utilizando explicitamente uma pilha. A idéia é a seguinte: O analisador sintático recebe uma seqüência de entrada (a sentença a ser analisada); Manipula uma estrutura de dados tipo pilha (onde monta a ADS); Para cada símbolo de entrada, consulta uma tabela de análise sintática para saber que regra aplicar; Emite uma seqüência de saída (regras que estão sendo aplicadas). Adaptado de notas de aulas do prof. Giuseppe Mongiovi do DI/UFPB. 7

Veja o esquema a seguir. Modelo de um Analisador Sintático Preditor a * b + c $ cadeia de entrada E A S P $ Pilha ANALISADOR SINTÁTICO Tabela de Análise Sintática (TAS) Entrada do analisador: seqüência de saída 1 3 4 9 Sentença a ser analisada, seguida por um símbolo delimitador ($). Pilha: contém uma seqüência de símbolos da gramática, precedida pelo indicador de base de pilha ($). Tabela de análise sintática: é uma matriz M[A, a], onde 'A' é um não-terminal e 'a' é um terminal ou dólar ($). Saída do analisador: Constará das produções aplicadas a partir do símbolo inicial (S), na geração da sentença. Adaptado de notas de aulas do prof. Giuseppe Mongiovi do DI/UFPB. 8

Funcionamento do analisador: A partir de X, símbolo do topo da pilha, e de próximo_símbolo, o atual símbolo de entrada, o analisador determina sua ação que pode ser uma das quatro possibilidades a seguir: 1) Se X é um terminal = próximo_símbolo = $, o analisador encerra sua atividade e comunica fim da análise sintática com sucesso; 2) Se X é um terminal = próximo_símbolo $, o analisador elimina X do topo da pilha e avança para o próximo símbolo de entrada; 3) Se X é um terminal próximo_símbolo, o analisador acusa um erro de sintaxe (ativa rotina de tratamento de erros); 4) Se X é um não-terminal, o analisador consulta M[X, próximo_símbolo]. Se a resposta for uma regra de produção X ::= MVU, o analisador desempilha X do topo da pilha e empilha UVM (com M no topo da pilha). Para a saída é enviada a regra de produção usada. Se M[X, próximo_símbolo] = ERRO, o analisador acusa um erro de sintaxe (ativa rotina de tratamento de erros). Adaptado de notas de aulas do prof. Giuseppe Mongiovi do DI/UFPB. 9

Exemplo: Sejam a gramática G(S) e a respectiva tabela de análise sintática. (1) S ::= aas (3) A ::= a (2) S ::= b (4) A ::= bsa a b $ S 1 2 ERRO A 3 4 ERRO Dada a sentença w = abbab$, o analisador sintático assumiria as seguintes configurações durante a análise: ENTRADA PILHA SAÍDA abbab$ $S abbab$ $SAa 1 bbab$ $SA 1 bbab$ $SASb 1 4 bab$ $SAS 1 4 bab$ $SAb 1 4 2 ab$ $SA 1 4 2 ab$ $Sa 1 4 2 3 b$ $S 1 4 2 3 b$ $b 1 4 2 3 2 $ $ 1 4 2 3 2 Adaptado de notas de aulas do prof. Giuseppe Mongiovi do DI/UFPB. 10

Vejamos o algoritmo do analisador preditor. Algoritmo do analisador preditor início /* seja X o símbolo do topo da pilha e próximo_símbolo o símbolo atual da entrada*/ enquanto X $ faça { se X é terminal então se X = próximo_símbolo então { elimine X do topo da pilha; leia_próximo_símbolo(); } senão ERRO(); senão se M[X, próximo_símbolo] = "X::=Y1Y2...Yk" então{ elimine X do topo da pilha; empilhe Yk,..., Y2, Y1 } senão ERRO(); } se próximo_símbolo $ então ERRO(); fim Adaptado de notas de aulas do prof. Giuseppe Mongiovi do DI/UFPB. 11

Obtenção da Tabela (ou matriz) de Análise Sintática Para construí-la, precisamos introduzir dois novos conceitos (ou relações) em gramáticas. São os conceitos de Primeiro ("First") e Seguidor ("Follow"). Primeiro(α) = {x x V T, α =>* xβ, α V +, β V*} se α =>* ε então ε Primeiro(α) } Seguidor(A) = {a S=>* αaaβ, a V T, A V N, α,β V*, e S símbolo inicial} se S =>* αa então ε Seguidor(A) Exemplo: Dada a gramática: E ::= TE' E' ::= +TE' ε T ::= FT' T' ::= *FT' ε F ::= ( E ) id Temos: Primeiro(E) = { (, id } Primeiro(E') = { +, ε } Primeiro(T) = { (, id } Primeiro(T') = { *, ε } Primeiro(F) = { (, id } Seguidor(E) = Seguidor(E') = { ), ε } Seguidor(T) = Seguidor(T') = { +, ), ε } Seguidor(F) = { +, *, ), ε } Adaptado de notas de aulas do prof. Giuseppe Mongiovi do DI/UFPB. 12

Obtenção do conjunto Seguidor(A) Algoritmo: Obtém o conjunto SEGUIDOR para todos os não terminais de uma gramática G(S). SEGUIDOR(S) ε Para toda produção A αbβ faça SEGUIDOR(B) PRIMEIRO(β) ε; Repita Para toda produção A αb ou A αbβ com ε PRIMEIRO(β)faça SEGUIDOR(B) SEGUIDOR(A) Até não adicionar nenhum símbolo a qualquer conjunto SEGUIDOR Algoritmo para a obtenção da tabela (matriz) de análise sintática início para cada produção A ::= α da gramática, faça { para cada símbolo terminal a Primeiro(α), faça adicione a produção A ::= α em M[A, a]; se ε Primeiro(α), adicione a produção A ::= α em M[A, b], para cada terminal b Seguidor(A); se ε Primeiro(α) e ε Seguidor(A), adicione a produção A ::= α em M[A, $] } indique situação de ERRO para todas as posições indefinidas de M[A, a]; fim Adaptado de notas de aulas do prof. Giuseppe Mongiovi do DI/UFPB. 13

Exemplo: Para a gramática abaixo, obtém-se: (1) E ::= TE' (5) T' ::= *FT' (2) E' ::= +TE' (6) T' ::= ε (3) E' ::= ε (7) F ::= ( E ) (4) T ::= FT' (8) F ::= id id + * ( ) $ E 1 1 E' 2 3 3 T 4 4 T' 6 5 6 6 F 8 7 O algoritmo dado é válido para qualquer gramática, porém, para algumas gramáticas(ambíguas e/ou recursivas à esquerda), a matriz M possui algumas entradas multiplamente definidas; Exemplo: A gramática abaixo é ambígua. 1) <cmd> ::= if <cond> then <cmd> <pelse> 2) <cmd> ::= <atribuição> 3) <cmd> ::= <ativação> 4) <pelse> ::= else <cmd> 5) <pelse> ::= ε 6) <cond> ::= b 7) <cond> ::= a A sentença w = if b then if a then <atribuição> else <ativação> pode ser interpretada de duas formas diferentes. Adaptado de notas de aulas do prof. Giuseppe Mongiovi do DI/UFPB. 14

ou: if b then if a then <atribuição> else <ativação> if b then if a then <atribuição> else <ativação> Em termos de árvore de derivação sintática temos: <cmd> if <cond> then <cmd> <pelse> b ε if <cond> then <cmd> <pelse> a <atribuição> else <cmd> <ativação> Adaptado de notas de aulas do prof. Giuseppe Mongiovi do DI/UFPB. 15

ou <cmd> if <cond> then <cmd> <pelse> b if <cond> then <cmd> a <atribuição> <pelse> ε else <cmd> <ativação> As condições para executar o comando <atribuição> são as mesmas nas duas interpretações (a = b = verdadeira) Para executar o comando <ativação> as condições diferem: (b = verdadeira e a = falso) p/ a 1 a e (b = falso e a = *) p/ a 2 a Para essa gramática, teríamos a seguinte matriz de análise sintática: a b if then else $ <cmd> 1 <pelse> 4 / 5 5 <cond> 7 6 Adaptado de notas de aulas do prof. Giuseppe Mongiovi do DI/UFPB. 16

Gramáticas LL(1) São aquelas cujas tabelas de análise sintática possuem no máximo uma produção para cada par (A, a), onde A V N e a V T {$} Pode ser demonstrado que: Se A ::= α β são duas produções distintas de G, então G é uma gramática LL(1) se somente se 1) Primeiro(α) Primeiro(β) 2) Se β * ε, então α só deriva cadeias do tipo α *a... onde a Seguidor(A). Implementação do Analisador Sintático Descendente LL(1) Um analisador sintático preditor pode ser implementado facilmente utilizando-se certas convenções: A principal: codificar todos os símbolos usados na representação da gramática (terminais e não-terminais) através de números inteiros. Símbolos terminais - usar os códigos que foram atribuídos pelo analisador léxico; Símbolos não-terminais - podem ser codificados através de números negativos (para não serem confundidos com os terminais). Adaptado de notas de aulas do prof. Giuseppe Mongiovi do DI/UFPB. 17

Exemplo: Seja a gramática G(E): (1) E ::= TE' (5) T' ::= *FT' (2) E' ::= +TE' (6) T' ::= ε (3) E' ::= ε (7) F ::= ( E ) (4) T ::= FT' (8) F ::= id podemos utilizar a seguinte codificação: Símbolo Código id 1 + 11 * 13 ( 21 ) 22 $ 99 /* fim de sentença/pilha */ E -1 E' -2 T -3 T' -4 F -5 Usar as seguintes estruturas de dados: Pilha de análise: vetor de inteiros; Matriz de análise: matriz de inteiros; Vetor de regras: vetor de inteiros para conter todas as regras de produção codificadas. Adaptado de notas de aulas do prof. Giuseppe Mongiovi do DI/UFPB. 18

A representação para a matriz de análise e o vetor de regras são indicadas a seguir. id + * ( ) $ E 1 1 E' 2 3 3 T 4 4 T' 6 5 6 6 F 8 7 OBS. As posições em branco são situações de erro. Representação das regras Cabeças de regras 1 1 2 4 3 8 4 9 5 12 6 16 7 17 8 21 Vetor de regras -3-2 0 11-3 -2 0 0-5 -4 0 13-5 -4 0 0 21-1 22 0 1 0 O vetor de regras contém todas as regras de produção da gramática, já devidamente codificadas para facilitar o trabalho do analisador. Adaptado de notas de aulas do prof. Giuseppe Mongiovi do DI/UFPB. 19

Uma posição M[Não-terminal, Terminal] da matriz de análise sempre vai conter: um índice para o vetor de cabeças de regras indicando que produção deve ser aplicada para, partindo-se de Não-terminal, chegar-se a Terminal; uma indicação de ERRO para dizer que não é possível derivar Não-terminal e chegar-se em terminal. Referências Notas de aulas do prof. Giuseppe Mongiovi do DI/UFPB, 2002. Appel, A. W. Modern Compiler Implementation in C. Cambridge University Press, 1998. (Capítulo 3, seção 3.2). Adaptado de notas de aulas do prof. Giuseppe Mongiovi do DI/UFPB. 20