Newsgroups: comp.lang.prolog
Path: cantaloupe.srv.cs.cmu.edu!rochester!cornellcs!travelers.mail.cornell.edu!news.kei.com!news.mathworks.com!newsfeed.internetmci.com!howland.reston.ans.net!swrinde!ihnp4.ucsd.edu!munnari.oz.au!cs.mu.OZ.AU!munta.cs.mu.OZ.AU!fjh
From: fjh@munta.cs.mu.OZ.AU (Fergus Henderson)
Subject: Re: DCG's (was: Can you do this?)
Message-ID: <9529813.25170@mulga.cs.mu.OZ.AU>
Sender: news@cs.mu.OZ.AU (CS-Usenet)
Organization: Computer Science, University of Melbourne, Australia
References: <1995Oct17.191133.1@vax.sbu.ac.uk> <30864FF8.1A90@vms.uci.kun.nl> <LUDEMANN.95Oct19121524@expernet5.expernet.com> <anewman-2010950649240001@137.124.91.130>
Date: Wed, 25 Oct 1995 03:55:22 GMT
Lines: 70

anewman@epidigm.geg.mot.com (M. Alan Newman) writes:

>ludemann@expernet.com wrote:
>
>> flatten([]) --> [].
>> flatten([X|Y]) --> flatten(X), flatten(Y).
>> flatten(X) --> {atomic(X), X \== []}, [X].
>> 
>> flatten(List, Flattened) :- phrase(flatten(List), Flattened).
>
>What are the reasons for/against using phrase/2 as above (assuming
>standard token list expansion), instead of:
>
>flatten(List, Flattened) :- flatten(List, Flattened, []).

The reason against it is that is just what you said - it assumes
the standard token list expansion.

Using phrase/2 can be considered a higher-level, more declarative notion.
Instead of requiring preprocessing, phrase/2 could be implemented
as a simple meta-interpreter:

	phrase(Phrase, Tokens) :-
		dcg_parse(Phrase, Tokens, []).

	dcg_parse([], Tokens, Tokens).
	dcg_parse([X|Xs], [X|Ys], Zs) :-
		dcg_parse(Xs, Ys, Zs).
	dcg_parse({Goal}, Tokens, Tokens) :- Goal.
	dcg_parse((A, B), Tokens0, Tokens) :-
		dcg_parse(A, Tokens0, Tokens1),
		dcg_parse(B, Tokens0, Tokens1).
	dcg_parse((A ; B), Tokens0, Tokens) :-
		dcg_parse(A, Tokens0, Tokens)
		;
		dcg_parse(B, Tokens0, Tokens).
	dcg_parse(DCG_Head, Tokens0, Tokens) :-
		DCG_Head --> DCG_Body,
		dcg_parse(DCG_Body, Tokens0, Tokens).

This is a very elegant way of specifying the semantics of DCGs.  (Or at
least it is until you start trying to deal with quantifiers, negation,
if-then-else, and cut - that's the trouble with meta-programming
in Prolog!)  It gives DCGs a simple and very direct declarative
semantics.  This is better than the more indirect translation semantics
which is required if you want to assume that DCGs are implemented using the
standard DCG expansion.

Of course, without partial evaluation this is a lot less efficient
than the way DCGs are typically implemented via expand_term.

But the nice thing about using phrase/2, at least in theory, is that
it leaves open the opportunity to plug in a smarter parsing tool
which could generate very efficient mostly non-backtracking parsers
using standard parser generator techniques.  In practice, I haven't
seen any such tools :-(.

>In particular, are there any problems intermixing DCG and non-DCG clauses?
>For example, having a predicate whose three clause (heads) are:
>
>foo(A, B) :- ...
>foo --> ...
>foo(A, B) :- ...
>
>and, similarly, invoking this predicate by either goal:
>  foo(A, B)   or    phrase(foo, A, B)

There are no practical problems, provided you're willing to stick to
implementations that use the standard DCG expansion.

