Podemos adicionar um qualquer número de argumentos aos símbolos não terminais que estamos a definir numa DCG. Podemos querer acrescentar argumentos, por exemplo, para conseguirmos acordo de número. Caso contrário o analisador sintáctico pode terminar com sucesso com uma frase gramaticalmente incorrecta. Por exemplo todas as frases seguintes estão gramaticalmente incorrectas:
Os homem vira o disco
O homem vira os disco
Os homens vira o disco
No exemplo que se segue vamos adicionar o argumento Numero, que pode estar instanciado quer com singular quer com plural, de modo a sermos capazes de garantir acordo de número. Adicionamos também um outro argumento que nos permitirá distinguir pessoas de coisas. Deste modo, seremos capazes de diferenciar entre o nome homem (pessoa) e o nome disco (coisa) e fazer com que a frase ``o homem vira o disco'' seja aceite enquanto que a frase``o disco vira o homem'' não...
frase -->
sintagma_nominal(Numero,pessoa),
sintagma_verbal(Numero).
sintagma_nominal(Numero,Tipo) -->
determinante(Numero),
nome(Numero,Tipo).
sintagma_verbal(Numero) -->
verbo(Numero),
sintagma_nominal(Numero,coisa).
determinante(singular) --> [o].
determinante(plural) --> [os].
nome(singular,pessoa) --> [homem].
nome(plural,pessoa) --> [homens].
nome(singular,coisa) --> [disco].
verbo(singular) --> [vira].
verbo(singular) --> [viram].
Também é útil acrescentar argumentos quando pretendemos ver o resultado de um
cálculo que ocorre durante o processo de análise sintáctica. Vejamos um exemplo.
Queremos uma gramática que sirva para definir expressões aritméticas simples
(envolvendo números de 0 a 9) e que calcule o valor das expressões. Considere-se
-2+3*5+1
como um exemplo de uma expressão aritmética. No nosso programa lógico Z é o argumento adicional:
expr(Z) --> termo(X), [+], expr(Y), {Z is X + Y}.
expr(Z) --> termo(X), [-], expr(Y), {Z is X - Y}.
expr(Z) --> termo(Z).
termo(Z) --> numero(X), [*], termo(Y), {Z is X * Y}.
termo(Z) --> numero(X), [/], termo(Y), {Z is X / Y}.
termo(Z) --> numero(Z).
numero(N) --> [+], numero(N).
numero(N) --> [-], numero(X), {N is 0 - X}.
numero(N) --> [N], {number(N), 0 =< N, N =< 9}.
Uma possível execução desta gramática será:
?- expr(Z,[-,2,+,3,*,5,+,1],[]).
Z = 14
Vamos agora imaginar que estamos interessados em saber, dada uma frase de entrada, qual a árvore de derivação que representa a estrutura de tal frase. Para isso vamos usar argumentos extra... De maneira a devolvermos a árvore de derivação, vamos adicionar um argumento extra a cada predicado. Este argumento indica que estamos interessados em ver a árvore de derivação construída a partir das árvores das sub frases. Se o interpretador de Prolog poder encontrar um sintagma nominal seguido por um sintagma verbal, as duas árvores de derivação serão combinadas de modo a formar uma árvore de derivação maior, que usa o nome de predicado frase, e que constituirá a árvore da frase completa. Na DCG que se segue Num representa o argumento para o acordo de número; enquanto SN, SV, ... representam os argumentos para a árvore de derivação.
frase(frase(SN,SV)) -->
sintagma_nominal(Num,SN),
sintagma_verbal(Num,SV).
sintagma_nominal(Num,sintagma_nominal(D,N)) -->
determinante(Num,D),
nome(Num,N).
sintagma_verbal(Num,sintagma_verbal(V,SN)) -->
verbo(Num,V),
sintagma_nominal(Num,SN).
determinante(singular,determinante(o)) --> [o].
determinante(singular,determinante(a)) --> [a].
determinante(singular,determinante(um)) --> [um].
determinante(plural,determinante(os)) --> [os].
nome(singular,nome(homem)) --> [homem].
nome(singular,nome(mulher)) --> [mulher].
nome(plural,nome(homens)) --> [homens].
nome(singular,nome(disco)) --> [disco].
nome(singular,nome(livro)) --> [livro].
verbo(singular,verbo(vira)) --> [vira].
verbo(singular,verbo(viram)) --> [viram].
verbo(singular,verbo(escreve)) --> [escreve].
O que se segue é a árvore de derivação (escrita ``toda bonitinha'') para a frase ``a mulher escreve um livro'':
?- frase(A,[a,mulher,escreve,um,livro],[]).
A = frase(
sintagma_nominal(
determinante(a),
nome(mulher)
),
sintagma_verbal(
verbo(escreve),
sintagma_nominal(
determinante(um),
nome(livro)
)
)
)