Next: DCG ``Pascal'' Up: Mais exemplos Previous: DCG ``email''

DCG ``grafo''

Pretendemos construir um programa em Prolog, usando uma DCG, que permita descrever um grafo, dirigido não pesado, por meio de frases em português. Desta maneira, não teremos de introduzir os factos arco correspondentes directamente na Base de Conhecimento (BC). Por exemplo, se quisermos descrever o grafo



dizemos ``grafo g1: 1 ligado a 2, 4; 2 ligado a 3.'' e o programa encarregar-se-á de acrescentar à BC os factos

         arco(g1,1,2).
         arco(g1,1,4).
         arco(g1,2,3).

Segue-se uma solução.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Gramatica 'Grafo'
%%
%% Implementacao por Delfim F. Marado Torres
%% 25/Maio/1999
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

         gramGrafo -->
           nome(G),
           listaVertices(G).

         nome(NomeGrafo) -->
           [grafo, NomeGrafo, :].

         listaVertices(G) -->
           vertices(G),
           outros(G).

         vertices(G) -->
           [N, ligado, a],
           lista(G,N).



         lista(G,N1) -->
           [N2],
           { acrescentaBC(G,N1,N2) },
           resto(G,N1).

         resto(_,_) -->
           [].
         resto(G,N) -->
           [','],
           lista(G,N).

         outros(_) -->
           ['.'].
         outros(G) -->
           [';'],
           listaVertices(G).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Accoes Semanticas da Gramatica
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

         acrescentaBC(G,N1,N2) :-
           assertz(arco(G,N1,N2)),
           nl,
           write('A clausula '),
           write(arco(G,N1,N2)),
           write(' foi adicionada com sucesso.'),
           nl.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Predicado Principal: grafo/1
%% Recebe uma string em vez de uma lista.
%%
%% EXEMPLO:
%%   ?- grafo('grafo g1: 1 ligado a 2,4; 2 ligado a 3.').
%%
%%   A clausula arco(g1,1,2) foi adicionada com sucesso.
%%
%%   A clausula arco(g1,1,4) foi adicionada com sucesso.
%%
%%   A clausula arco(g1,2,3) foi adicionada com sucesso.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

         grafo(String) :-
           converte(String,Lista),!,
           gramGrafo(Lista,[]).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Transforma uma frase em lingua natural,
%% dada como uma string de palavras separadas
%% por espacos, numa lista cujos elementos sao
%% as palavras.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

         converte(S,L) :-
           name(S,LA1),
           adicionaEspacos(LA1,LA2),
           conv(LA2,L).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Os caracteres ':' ';' ',' '.' '!' '?' podem
 % estar escritos juntos a uma palavra, mas contam
% como uma palavra separada... (simbolos terminais
 % na gramatica).
%
 % Desta maneira, escrever
%    'grafo g1: 1 ligado a 2,4; 2 ligado a 3.'
 % sera equivalente a escrever
%    'grafo g1 : 1 ligado a 2 , 4 ; 2 ligado a 3 .'
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% 32 = codigo ASCII do espaco
 %
% 58 = codigo ASCII ':'
 % 59 = codigo ASCII ';'
% 44 = codigo ASCII ','
 % 46 = codigo ASCII '.'
% 33 = codigo ASCII '!'
 % 63 = codigo ASCII '?'
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

         adicionaEspacos([],[]).
         adicionaEspacos([X|R1],[32,X,32|R2]) :-
           member(X,[58,59,44,46,33,63]),
           adicionaEspacos(R1,R2).
         adicionaEspacos([X|R1],[X|R2]) :-
           adicionaEspacos(R1,R2).

         conv([],[]).
         conv(LA,[P|R]) :-
           palavra(LA,PA,RA), name(P,PA), conv(RA,R).

         palavra([],[],[]).
         palavra([32|R],[],L) :-
           desprezaEspacos(R,L).
         palavra([X|R1],[X|R2],L) :-
           palavra(R1,R2,L).

         desprezaEspacos([32|R1],R) :-
           desprezaEspacos(R1,R).
         desprezaEspacos(L,L).




1999-05-26