Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@mndrix
Last active September 29, 2018 17:41
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mndrix/572871177fa477e79ddb to your computer and use it in GitHub Desktop.
Save mndrix/572871177fa477e79ddb to your computer and use it in GitHub Desktop.
Prolog DCG utility predicates
% at_least//2 is like at_least//3 but ignores the specific matches found.
:- meta_predicate at_least(+,3,*,*).
at_least(N,Goal) -->
at_least(N,Goal,_).
% at_least(N,Goal,Matches) consumes at least N matches of Goal.
% after that, it consumes as much as possible.
:- meta_predicate at_least(+,3,?,*,*).
at_least(N0,Goal,[X|Xs]) -->
{ N0 > 0 },
!,
call(Goal,X),
{ N is N0 - 1 },
at_least(N,Goal,Xs).
at_least(0,Goal,Xs) -->
greedy(Goal,Xs).
% exactly(N,Goal) consumes exactly N matches of Goal.
:- meta_predicate exactly(+,3,*,*).
exactly(N,Goal) -->
exactly(N,Goal,_).
% exactly(N,Goal,Matches) consumes exactly N matches of Goal.
:- meta_predicate exactly(+,3,?,*,*).
exactly(0,Goal,[]) -->
\+ call(Goal,_).
exactly(N0,Goal,[X|Xs]) -->
{ N0 #> 0 },
{ N #= N0 - 1 },
call(Goal,X),
exactly(N,Goal,Xs).
% match as few Goal as possible
:- meta_predicate generous(3,-,*,*).
generous(_Goal,[]) -->
[].
generous(Goal,[X|Xs]) -->
call(Goal,X),
generous(Goal,Xs).
:- meta_predicate greedy(3,*,*).
greedy(Goal) -->
greedy(Goal,_).
% match as many copies of Goal as possible
:- meta_predicate amalog_dcg:greedy(3,-,*,*).
greedy(Goal,[X|Xs]) -->
( call(Goal,X) -> [] ),
greedy(Goal,Xs).
greedy(_,[]) -->
[].
%% list(ElemDCG, SeparatorDCG, Elems)//
%
% Describes a list in which the elements match ElemDCG and the
% separators match SeparatorDCG. Elems is the list of elements found.
% The set of patterns matched by ElemDCG and SeparatorDCG
% should be disjoint. Both DCG goals are called with one extra argument.
:- meta_predicate list(3,2,?,?,?).
list(ElemDCG, SepDCG, [Elem|Tail]) -->
call(ElemDCG, Elem),
( call(SepDCG),
!,
list(ElemDCG, SepDCG, Tail)
; "",
{ Tail = [] }
).
% followed_by(Goal) is true if Goal would match. Consumes nothing.
:- meta_predicate amalog_dcg:followed_by(//,*,*).
followed_by(Goal) -->
\+ \+ Goal.
% match the end of string
eos([],[]).
%% when_generating(:Goal)//
%
% Call Goal when DCG operates in generator mode.
:- meta_predicate when_generating(0,?,?).
when_generating(Goal) -->
( parsing -> []; { call(Goal) } ).
%% when_parsing(:Goal)//
%
% Call Goal when DCG operates in parsing mode.
:- meta_predicate when_parsing(0,?,?).
when_parsing(Goal) -->
( parsing -> { call(Goal) }; [] ).
%% parsing// is semidet.
%
% True if DCG is operating as a parser. Specifically,
% the DCG list is not a variable.
parsing(H,H) :-
nonvar(H).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment