/****************************************************************************/ /******************************* 02/08/92 ***********************************/ /****************************************************************************/ /********** **********/ /********** **********/ /********** TP NUMERO 5 **********/ /********** **********/ /********** **********/ /********** CONSTRUCTION D'UN ANALYSEUR INTERACTIF **********/ /********** **********/ /********** **********/ /****************************************************************************/ /****************************************************************************/ /****************************************************************************/ /****************************************************************************/ /* BASE DE FAITS INITIALE */ /****************************************************************************/ det(le,masculin). det(la,feminin). adj(petit,masculin,avant). adj(verte,feminin,apres). verbe(trottine,intransitif). verbe(rampe,intransitif). verbe(croque,transitif). verbe(est,etat). nom(herisson,masculin). nom(chenille,feminin). adv(tres). adv(rapidement). /****************************************************************************/ e:-emacs('ph5.pro'). /****************************************************************************/ /* Affichage d'une phrase */ /****************************************************************************/ putphrase([],_):- write(' '). putphrase([T|Q],o):- /* Phrase affirmative. */ write(' '),write(T),putphrase(Q,o). putphrase([T|Q],n):- /* Phrase negative. */ write(' '), (verbe(T,_),write('ne '),write(T),write(' pas');write(T)) ,putphrase(Q,n). /****************************************************************************/ /* Lecture d'une phrase */ /* Type indique si la phrase lue est une question ou une affirmation. */ /****************************************************************************/ getphrase(L,Type):- get0(Car), getreste(Car,L1), (L1=[est,ce,que|L], Type=question; Type=affirm, L=L1). /****************************************************************************/ /* Decomposition de la lecture d'une phrase et transformation de la phrase */ /* en une liste de mots. */ /****************************************************************************/ getreste(46,[]):-!. getreste(32,L):-!,getphrase(L,_). getreste(Lettre,[Mot|Mliste]):- getmot(Lettre,Lliste,Suivant), name(Mot,Lliste),!, getreste(Suivant,Mliste). /****************************************************************************/ /* Lecture d'un mot. Les majuscules sont transformees en minuscules. */ /****************************************************************************/ getmot(46,[],46):-!. getmot(32,[],32):-!. getmot(Lettre,Liste,Suiv):- Lettre=<90, Lettre>=64,!, Lettre1 is Lettre+32, getmot(Lettre1,Liste,Suiv). getmot(Lettre,[Lettre|Lliste],Suiv):- get0(C), getmot(C,Lliste,Suiv). /****************************************************************************/ /* Analyse syntaxique et grammaticale d'une phrase. */ /****************************************************************************/ phrase(L,ph(SN,SV),Type):-trace, sn(L,RL,Nom,SN,Type), abolish(gramcorrect,0), sv(RL,[],Nom,SV,Type). /****************************************************************************/ /* Verification de l'appartenance du determinant T a la base de faits et en */ /* cas d'echec, on interroge l'utilisateur puis on verifie si les */ /* renseignements qu'il a fourni correspondent au fait recherche. */ /****************************************************************************/ deter([T|Q],Q,Genre,det(T)):- det(T,Genre),!; question(det,T),!, det(T,Genre). /***************************************************************************/ /* On refait la meme chose que pour le determinant. Cependant, du fait */ /* qu'une phrase ne comporte pas forcement d'adjectif, on ajoute une */ /* clause qui traite ce cas particulier. */ /***************************************************************************/ adject([],[],_,_,''). adject([T|Q],[T|Q],Genre,Place,''):- /* phrase sans adjectif. */ not(adj(T,Genre,Place)), (Place=avant, sujet([T],_,Genre,_); Place=apres, gverbal([T|Q],_,_,_)). adject([T|Q],Q1,Genre,Place,(adjectif(T),A)):- (adj(T,Genre,Place),!; question(adj,T),!, adj(T,Genre,Place)), adject(Q,Q1,Genre,Place,A). /****************************************************************************/ /* Pour le nom, on refait comme pour le determinant, mais connaissant deja */ /* le genre du determinant, on provoque l'echec si le genre du nom n'est */ /* pas identique. */ /****************************************************************************/ sujet([T|Q],Q,Genre,nom(T)):- nom(T,Genre1),!, Genre1==Genre; question(nom,T),!, nom(T,Genre). /***************************************************************************/ /* Analyse syntaxique puis semantique du syntagme nominal. */ /***************************************************************************/ sn([],[],_,'',_). sn(L,RL,T3,sn(D,Av,N,Ap),Type):- deter(L,[T2|Q],Genre,D), adject([T2|Q],[T3|Q3],Genre,avant,Av), sujet([T3|Q3],RL3,Genre,N), adject(RL3,RL,Genre,apres,Ap), assertz(gramcorrect),!, ([T2|Q]\==[T3|Q3], sens([T2,T3],Type); true),!, (RL3\==RL, RL3=[T4|_], sens([T4,T3],Type); true). /***************************************************************************/ /* Recherche d'un verbe dans la base de faits, et en cas d'echec, on */ /* interroge l'utilisateur. On verifie ensuite les renseignements qu'il a */ /* fourni. */ /***************************************************************************/ gverbal([T|Q],Q,verbe(T),Mode):- verbe(T,Mode),!; question(verbe,T),!, verbe(T,Mode). /***************************************************************************/ /* On procede pour l'adverbe de la meme maniere que pour l'adjectif. */ /***************************************************************************/ adverbe([],[],''). adverbe([T|Q],[T|Q],''):- not(adv(T)), (det(T,_),!; adject([T],[],_,_,_),!). adverbe([T|Q],Q,adverbe(T)):- adv(T),!; question(adverbe,T). /***************************************************************************/ /* Analyse syntaxique puis semantique du syntagme verbal. */ /***************************************************************************/ sv([T|Q],RL,Nom,sv(V,Adv,SN),Type):- /* Verbe transitif */ gverbal([T|Q],RL1,V,Mode), /* ou */ adverbe(RL1,RL2,Adv), /* intransitif. */ (Mode==transitif, sn(RL2,RL,Complement,SN,Type); RL=RL2, SN=''), assertz(gramcorrect),!, (RL1\==RL2,RL1=[T1|_], sens([T1,T],Type); true),!, sens([T,Nom,Complement],Type). sv([T|Q],RL,Nom,sv(V,Adv,Adj),Type):- /* Verbe d'etat. */ gverbal([T|Q],[T1|Q1],V,etat), adverbe([T1|Q1],[T2],Adv), nom(Nom,Genre), adject([T2],RL,Genre,_,Adj), assertz(gramcorrect),!, ([T1|Q1]\==[T2], sens([T1,T],Type); true),!, sens([T2,Nom],Type). /****************************************************************************/ /* Questionnaire syntaxique permettant de definir les nouveaux mots */ /* entres par l'utilisateur. */ /****************************************************************************/ question(det,Mot):- write('Le mot "'),write(Mot),write('" est-il un determinant ? '),nl, read(R),!, R==oui,!, write('Ce determinant est-il masculin ? '),nl, read(G), (G==oui, Genre=masculin; G==non, Genre=feminin), assertz(det(Mot,Genre)). question(nom,Mot):- write('Le mot "'),write(Mot),write('" est-il un nom ? '),nl, read(R),!, R==oui,!, write('Ce nom est-il masculin ? '),nl, read(G), (G==oui, Genre=masculin; G==non, Genre=feminin), assertz(nom(Mot,Genre)). question(adj,Mot):- write('Le mot "'),write(Mot),write('" est-il un adjectif ? '),nl, read(R),!, R==oui,!, write('Cet adjectif est-il masculin ? '),nl, read(G), (G==oui, Genre=masculin; G==non, Genre=feminin),!, write('Cet adjectif se place devant le nom ?'),nl, read(P), (P==oui, Place=avant; P==non, Place=apres), assertz(adj(Mot,Genre,Place)). question(verbe,Mot):- write('Le mot "'),write(Mot),write('" est-il un verbe ? '),nl, read(R),!, R==oui,!, write('Ce verbe est-il transitif ? '),nl, read(G), (G==oui, Genre=transitif; G==non, write('Ce verbe est-il intransitif ? '),nl, read(G2),!, (G2==oui, Genre=intransitif; G2==non, Genre=etat)), assertz(verbe(Mot,Genre)). question(adverbe,Mot):- write('Le mot "'),write(Mot),write('" est-il un adverbe ? '),nl, read(R),!, R==oui, assertz(adv(Mot)). /****************************************************************************/ /* Verification semantique. Si la base de faits ne contient pas la clause */ /* semantique recherchee, alors si la phrase etudiee est une affirmation, */ /* on demande a l'utilisateur de confirmer la semantique de sa phrase. */ /****************************************************************************/ sens([X|Q],Type):- Y=..[X|Q],!, (Y,!; Type==affirm, quest_sens(X,Q), assertz(Y)). /****************************************************************************/ /* Questionnaire semantique obligeant l'utilisateur a confirmer la */ /* semantique de la phrase dont il vient de demander l'analyse. */ /****************************************************************************/ quest_sens(F,[Mot]):- /* Confirmation de la semantique */ nom(Mot,Genre), /* entre un adjectif et le nom */ det(D,Genre), /* auquel il se rapporte. */ write('Est ce que '), write(D),write(' '),write(Mot),write(' peut etre '),write(F), write(' ?'),nl, read(R),!, R==oui. quest_sens(F,[Mot]):- /* Idem entre adverbe et verbe. */ write('est ce que l''adverbe "'),write(F), write('" peut suivre le verbe "'),write(Mot), write('" du point de vue semantique ? '),nl, read(R),!, R==oui. quest_sens(F,[Nom,Complement]):- /* Idem entre sujet, verbe, compl. */ write('Est ce que la phrase "'), nom(Nom,Genre),det(D,Genre), write(D),write(' '),write(Nom),write(' '),write(F),write(' '), (var(Complement); nom(Complement,Genre1), det(D1,Genre1), write(D1),write(' '),write(Complement)), write('" a un sens ?'),nl, read(R),!, R==oui. /****************************************************************************/ /* La clause essai permet de lancer l'analyse syntaxique et semantique */ /* d'une phrase. Si la phrase est une question, alors la clause essai */ /* repond oui ou non en fonction de la reussite ou de l'echec de la clause */ /* d'analyse. Si la phrase est une affirmation, alors la clause renvoie */ /* l'analyse syntaxique de la phrase a condition bien sur que l'analyse ait */ /* reussie. Si l'analyse a echoue, alors grace au fait gramcorrect, on */ /* indique la cause de l'echec : raison grammaticale ou semantique. */ /****************************************************************************/ essai:-write('Tapez une phrase'),nl, getphrase(L,Type),get0(C),nl, (phrase(L,Phrase_Analysee,Type),nl, (Type==affirm, write('La phrase "'), putphrase(L,o), write('" est correcte ! '),nl, write('Analyse syntaxique de la phrase :'),nl, write(Phrase_Analysee); write('Oui,'), putphrase(L,o), write('.')), nl; (gramcorrect, (Type==affirm, write('La phrase "'), putphrase(L,o), write('" est semantiquement incorrecte !'); write('Non,'), putphrase(L,n), write('.')), nl; write('La phrase "'), putphrase(L,o), write('" est grammaticalement incorrecte'),nl)), nl,nl, essai.