+/** Support for Definite Clause Grammars.
+
+A Prolog definite clause grammar (DCG) describes a sequence. Operationally, DCGs
+can be used to parse, generate, complete and check sequences manifested as lists.
+
+Check [The Power of Prolog chapter on DCGs](https://www.metalevel.at/prolog/dcg)
+to learn more about them.
+*/
+
+
:- module(dcgs,
[op(1105, xfy, '|'),
phrase/2,
:- meta_predicate phrase(2, ?, ?).
+%% phrase(+Body, ?Ls).
+%
+% True iff Body describes the list Ls. Body must be a DCG body.
+% It is equivalent to `phrase(Body, Ls, [])`.
+%
+% Examples:
+%
+% ```
+% as --> [].
+% as --> [a], as.
+%
+% ?- phrase(as, Ls).
+% Ls = []
+% ; Ls = "a"
+% ; Ls = "aa"
+% ; Ls = "aaa"
+% ; ... .
+%
+% ?- phrase(as, "aaa").
+% true.
+% ```
+
phrase(GRBody, S0) :-
phrase(GRBody, S0, []).
+%% phrase(+Body, ?Ls, ?Ls0).
+%
+% True iff Body describes part of the list Ls and the rest of Ls is Ls0.
+%
+% Example:
+%
+% ```
+% ?- phrase(seq(X), "aaa", Y).
+% X = [], Y = "aaa"
+% ; X = "a", Y = "aa"
+% ; X = "aa", Y = "a"
+% ; X = "aaa", Y = [].
+% ```
phrase(GRBody, S0, S) :-
strip_module(GRBody, M, GRBody1),
( var(GRBody) ->
nonvar(Term0),
dcg_rule(Term0, Term).
+
+%% seq(Seq)//
+%
% Describes a sequence
seq(Xs, Cs0,Cs) :-
var(Xs),
seq([]) --> [].
seq([E|Es]) --> [E], seq(Es).
+%% seqq(SeqOfSeqs)//
+%
% Describes a sequence of sequences
seqq([]) --> [].
seqq([Es|Ess]) --> seq(Es), seqq(Ess).
+%% ...//
+%
% Describes an arbitrary number of elements
...(Cs0,Cs) :-
Cs0 == [],
/**
-Provides predicate dif/2. dif/2 is a constraint that is true only if both of its
+Provides predicate `dif/2`. `dif/2` is a constraint that is true only if both of its
arguments are different terms.
*/
%% dif(?X, ?Y).
%
-% True iff X and Y are different terms. Unlike \\=/2, dif/2 is more declarative because if X and Y can
+% True iff X and Y are different terms. Unlike `\=/2`, `dif/2` is more declarative because if X and Y can
% unify but they're not yet equal, the decision is delayed, and prevents X and Y to become equal later.
% Examples:
%
-% ?- dif(a, a).
-% false.
-% ?- dif(a, b).
-% true.
-% ?- dif(X, b).
-% dif:dif(X,b).
-% ?- dif(X, b), X = b.
-% false.
+% ```
+% ?- dif(a, a).
+% false.
+% ?- dif(a, b).
+% true.
+% ?- dif(X, b).
+% dif:dif(X,b).
+% ?- dif(X, b), X = b.
+% false.
+% ```
dif(X, Y) :-
X \== Y,
( X \= Y -> true