Is there a way or an algorithm to convert DCG into normal definite clauses in Prolog?

别等时光非礼了梦想. 提交于 2019-12-01 06:06:51

You are on the right track! Keep on going and you will get to something like this:

expr(Xs0,Xs) :-                         % expr -->
   term(Xs0,Xs1),                       %    term,
   addterm(Xs1,Xs).                     %    addterm.

addterm(Xs0,Xs) :-                      % addterm --> 
   Xs0 = Xs.                            %    [].
addterm(Xs0,Xs) :-                      % addterm -->
   Xs0 = [+|Xs1],                       %    [+], 
   expr(Xs1,Xs).                        %    expr. 

term(Xs0,Xs) :-                         % term --> 
   factor(Xs0,Xs1),                     %    factor,
   multfactor(Xs1,Xs).                  %    multfactor.

multfactor(Xs0,Xs) :-                   % multfactor -->
   Xs0 = Xs.                            %    [].
multfactor(Xs0,Xs) :-                   % multfactor -->
   Xs0 = [*|Xs1],                       %    [*],
   term(Xs1,Xs).                        %    term.  

factor(Xs0,Xs) :-                       % factor --> 
   Xs0 = [I|Xs],                        %    [I],
   integer(I).                          %    {integer(I)}.
factor(Xs0,Xs) :-                       % factor --> 
   Xs0 = ['('|Xs1],                     %    ['('], 
   expr(Xs1,Xs2),                       %    expr,
   Xs2 = [')'|Xs]. `                    %    [')'].      

If your Prolog system provides an expand_term/2 built-in predicate, you can use usually to expand grammar rules into clauses. For example:

?- expand_term((a --> b, c), Clause).
Clause = (a(_G1012, _G1013):-b(_G1012, _G1028), c(_G1028, _G1013)).

For a bit more readable output (and for this purpose only), try:

?- expand_term((a --> b, c), Clause), numbervars(Clause, 0, _).
Clause = (a(A, B):-b(A, C), c(C, B)).

numbervars/3 is a de facto standard predicate found on most Prolog systems.

Some Prolog systems translate DCGs to clauses in a way that is different from the one in the answers by @repeat and @PauloMoura: direct unification of terminals with members of the list that is being analyzed/generated is replaced by a call to a predicate 'C'/3. For instance

a(X) --> b(X), [x, y], c(X).

is translated to

a(A,B,C) :-
  b(A,B,D),
  'C'(D,x,E),
  'C'(E,y,F),
  c(A,F,C).

This predicate is predefined in those systems to do the unification as in those answers, by the clause

'C'([X|S],X,S).

but it can be redefined by the user if needed.

This is part of the definition of DCGs, first put forth in Fernando Pereira and David Warren paper Definite clause grammars for language analysis, in Artificial Intelligence, 13, 1980, and is one of the differences to Alain Colmerauer et al. previous paper Metamorphosis Grammars. The use of the 'C'/3 predicate, originaly named connects, makes the DCG independent of the way the string to be parsed/generated is represented: in the translation given above there is nothing that requires that the variables B to F stand for lists, and 'C'/3 can be redefined to interpret them as other kind of terms. In order not to avoid efficiency losses the paper recommends preprocessing of DCGs clauses during compilation in case lists are used.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!