next up previous
Next: 17.1 Applying arbitrary methods Up: BinProlog 5.75 User Previous: 16.1 Updatable logical arrays

17 Assumption Grammars

By using backtrackable setarg/3 and logical global variables (lval/3) we can implement easily a superset of DCG grammars practically equivalent with Peter VanRoy's Extended DCGs. We call them Assumption Grammars as no preprocessor is involved in their implementation. It turns out that the technique has the advantage of `meta-programming for free' (without the expensive phrase/3), allows source level debugging and can be made more space and time efficient than the usual preprocessing based implementation. On real examples, their best use is for writing a Prolog compiler (they can contribute to the writing of compact and efficient code with very little programming effort) and for for large natural language processing systems.

Basically, they work as follows:

% tools

begin_dcg(Name,Xs):-lval(dcg,Name,Xs-Xs).

end_dcg(Name,Xs):-lval(dcg,Name,Xs-[]).

w(Word,Name):-
  lval(dcg,Name,State),
  State=_-[Word|Xs2],
  setarg(2,State,Xs2).

begin_dcg(Xs):-begin_dcg(default,Xs).
end_dcg(Xs):-end_dcg(default,Xs).
w(Word):-w(Word,default).

% grammar
x:-ng,v.

ng:-a,n.

a:-w(the).
a:-w(a).

n:-w(cat).
n:-w(dog).

v:-w(walks).
v:-w(sleeps).

% test
go:-begin_dcg(Xs),x,end_dcg(Ys),write(Ys),nl,fail.

?- go.
[the,cat,walks]
[the,cat,sleeps]
[the,dog,walks]
[the,dog,sleeps]
[a,cat,walks]
[a,cat,sleeps]
[a,dog,walks]
[a,dog,sleeps]

The program can be found in progs/setarg_dcg.pl. For reasons of efficiency (i.e. to equal or beat preprocessor based DCGs in terms of both space and time) BinProlog's `Assumption Grammars' have been implemented in C and are accessible through the following set of builtins:

dcg_connect/1  % works like 'C'/3 with 2 hidden arguments
dcg_def/1   % sets the first hidden DCG argument
dcg_val/1   % retrieves the current state of the DCG stream
dcg_tell/1  % focus on a given DCG stream (from 0 to 255)
dcg_telling/1 % returns the number of the current DCGs stream

% INVISIBLE DCG connect operation: normally macro-expanded
'#'(Word):-dcg_connect(Word).

% example: ?-dcg_phrase(1,(#a,#b,#c),X).
dcg_phrase(DcgStream,Axiom,Phrase):-
  dcg_telling(X),dcg_tell(DcgStream),
    dcg_def(Phrase),
      Axiom,
    dcg_val([]),
  dcg_tell(X).

Starting with BinProlog 3.33 dcg_tell/1 is backtrackable, mostly like lval/3. Admissible values for X in dcg_tell(X) are ranging from 1 to 255, which gives (I hope) enough distinct DCG streams for any application.

Invisible grammars consume no heap, as they are based on backtrackable destructive assignment implemented with a technique called value trailing like setarg/3. They consume trail only when a nondeterministic situation (choice-point) arises.

If you try the following program:

% grammar
ax:-ng,v.

ng:-a,n.

a:-dcg_connect(the).
a:-dcg_connect(a).

n:-dcg_connect(cat).
n:-dcg_connect(dog).

v:-dcg_connect(walks).
v:-dcg_connect(sleeps).

go:-
  st(H,T),
  dcg_def(Xs),ax,dcg_val([]),
  pp(Xs,H,T),nl,
  fail.

st(H,T):-statistics(global_stack,[H,_]),statistics(trail,[T,_]).

pp(O,H0,T0):-
  st(H1,T1),T is T1-T0,H is H1-H0,
  write([heap=H,trail=T]),write('==>'),write(O),nl,fail.
pp(_,_,_).

it will print out something like:

[heap = 308,trail = 44]==>[the,cat,walks]
[heap = 308,trail = 32]==>[the,cat,sleeps]
[heap = 308,trail = 32]==>[the,dog,walks]
[heap = 308,trail = 20]==>[the,dog,sleeps]
[heap = 308,trail = 44]==>[a,cat,walks]
[heap = 308,trail = 32]==>[a,cat,sleeps]
[heap = 308,trail = 32]==>[a,dog,walks]
[heap = 308,trail = 20]==>[a,dog,sleeps]





next up previous
Next: 17.1 Applying arbitrary methods Up: BinProlog 5.75 User Previous: 16.1 Updatable logical arrays



Paul Tarau
Thu Apr 3 10:26:39 AST 1997