Algo fácil de hacer en Prolog es escribir ``parsers''. De hecho Prolog fué usado inicialmente para procesamiento de lenguaje natural. Prolog tiene la facilidad de traducir directamente sus cláusulas de Horn en DCGs.
DCG son una extensión de CFG:
Ejemplo de CFG (solo 1 símbolo del lado izq.)
oracion --> sujeto, predicado. sujeto --> articulo, sustantivo. predicado --> verbo, sujeto. predicado --> verbo. articulo --> [el]. articulo --> [la]. sustantivo --> [manzana]. sustantivo --> [hombre]. verbo --> [come]La primera regla dice que una oración está compuesta por un sujeto seguida de un predicado.
En Prolog podríamos ``parsear'' una oración, donde los símbolos terminales simplemente tienen lo que aceptan y los demás símbolos son listas con frases que aceptan. Una forma simple (pero ineficiente) de hacerlo es:
oracion(Lista) :- sujeto(Suj), predicado(Pred), append(Suj,Pred,Lista). sujeto(Suj) :- articulo(Art), sustantivo(Sust), append(Art,Sust,Suj). articulo([el]). articulo([la]).Esto se puede mejorar, eliminando el ``append'' si cada parte de la oración nos dice cuanto ocupa:
?- oracion([el,hombre,come,la,manzana],[]). oracion(L1,L3)) :- sujeto(L1,L2), predicado(L2,L3). sujeto(L1,L3) :- articulo(L1,L2), sustantivo(L2,L3). predicado(L1,L3) :- verbo(L1,L2), sujeto(L2,L3). predicado(L1,L2) :- verbo(L1,L2). articulo([el|T],T). articulo([la|T],T). sustantivo([hombre|T],T). sustantivo([manzana|T],T). verbo([come|T],T).Hay que notar que lo mismo se puede representar (casi igual) como diferencia de listas, i.e., oracion(L1-L3) :- ...
Prolog tiene una forma de traducir la representación de arriba en
notación de CFG + le dá facilidad de incluir argumentos y llamar a
predicados de Prolog. Esto es, nosotros especificamos como un CFG y se
traduce al código de arriba. Para hacer preguntas hay que recordar
que se hizo la traducción, i.e.:
?- oracion([el,hombre,come,la,manzana],[]).
Algunos Prolog (no todos) tienen ``phrase'':
?- phrase(oracion,[el,hombre,come,la,manzana]). ?- phrase(sujeto,[la,manzana]).
En la notación, se permiten incluir llamados entre corchetes. También podemos añadir más argumentos. Por ejemplo, si queremos guardar el árbol que genera el ``parser'', podemos poner:
oracion(oracion(S,P)) --> sujeto(S) predicado(P). sujeto(suj(A,S)) --> articulo(A), sustantivo(S). predicado(pred(V,S)) --> verbo(V), sujeto(S). predicado(pred(V)) --> verbo(V). articulo(art(el)) --> [el]. ... ?- oracion(Arbol,[el,hombre,come,la,manzana],[]). Arbol = oracion(suj(art(el), sust(hombre)), pred(verb(come), suj(art(la), sust(manzana)))).Algo común es checar por género y número:
oracion --> sujeto(Num), predicado(Num). sujeto(N) --> articulo(Num,Gen), sustantivo(Num,Gen). predicado(Num) --> verbo(Num), sujeto(_). articulo(sing,fem) --> [la]. articulo(sing,masc) --> [el]. articulo(plural,fem) --> [las]. articulo(plural,masc) --> [los]. verbo(sing) --> [come]. verbo(plural) --> [comen]. sustantivo(sing,masc) --> [hombre]. sustantivo(sing,fem) --> [manzana].
Para ``parsear'' una expresión matemática y regresar su resultado:
expr(Z) --> term(X), ``+'', expr(Y), {Z is X + Y}. expr(Z) --> term(X), ``-'', expr(Y), {Z is X - Y}. expr(Z) --> term(X). term(Z) --> numero(X), ``*'', term(Y), {Z is X * Y}. term(Z) --> numero(X), ``/'', term(Y), {Z is X / Y}. term(Z) --> numero(Z). numero(N) --> ``+'', numero(N). numero(N) --> ``-'', numero(M), {N is - M}. numero(N) --> [X], {48 =< X, X =< 57, N is X - 48}.Alternativamente, se puede poner la expresion en un lista, todos los que están entre doble comillas, cambian a elementos en listas, e.g., ``+'' =
numero(N) --> [N], {member(N,[0,1,2,3,4,5,6,7,8,9])}.
Con DCG podemos hacer más que con CFG (e.g.,
)
s --> [a], s(i). s(I) --> [a], s(i(I)). s(I) --> nb(I), nc(I). nb(i(I)) --> [b], nb(I). nb(i) --> [b]. nc(i(I)) --> [c], nc(I). nc(i) --> [c].
emorales 2012-05-03