1:- module(dcg_tools,
    2         [
    3             any//1,
    4             nl//0,
    5             space//0,
    6             space//1,
    7             spaces//0,
    8             sp//0,
    9
   10             optional//1,
   11             optional//2,
   12             constant//1,
   13             '|'//3,
   14             (//)//2,
   15
   16             uppercase//1,
   17             lowercase//1,
   18             letter//1,
   19             word//1,
   20             symbol//1,
   21             digit//1,
   22             natural//1,
   23             integer//1,
   24
   25             list//1,
   26             list//2,
   27             list//3,
   28             non_greedy//1,
   29             non_greedy//2
   30         ]).   31
   32:- use_module(library(delay)).   33
   34:- multifile delay:mode/1.
   35delay:mode(lists:append(ground,_)).
   36delay:mode(lists:append(_,ground)).
   37delay:mode(dcg_tools:number_codes_(ground,_)).
   38delay:mode(dcg_tools:number_codes_(_,ground)).
   39
   40
   41% Higher order predicates
   42optional(Dcg)      --> optional(Dcg, _).
   43optional(Dcg, Res) --> call(Dcg, Res) | {Res = ``}.
   44constant(A) --> seq(A).
   45'|'(Dcg1, Dcg2, X) --> call(Dcg1, X) | call(Dcg2, X).
   46
   47//(P1,P2,S1,S2) :- call_dcg(P1,S1,S2), call_dcg(P2,S1,S2).
   48
   49
   50
   51seq([])     --> [].
   52seq([E|Es]) --> [E], seq(Es).
   53
   54any(X)    --> [X].
   55nl        --> `\n`.
   56space     --> ` `.
   57space(_)  --> ` `.
   58spaces    --> list(space).
   59sp        --> list(space).
   60
   61digitCode(C)  --> [C], {code_type(C, digit)}.
   62symbolCode(C) --> [C], {code_type(C, punct)}.
   63lowercaseCode(C) --> [C], {code_type(C, lower)}.
   64uppercaseCode(C) --> [C], {code_type(C, upper)}.
   65letterCode(C) --> lowercaseCode(C) | uppercaseCode(C).
   66
   67lowercase(L) --> {delay(atom_codes(L, [C]))}, lowercaseCode(C).
   68uppercase(L) --> {delay(atom_codes(L, [C]))}, uppercaseCode(C).
   69letter(L)    --> lowercase(L) | uppercase(L).
   70word(W)      --> {delay(atom_codes(W, Cs))},
   71                 list(letter, Cs).
   72symbol(S)    --> {delay(atom_codes(S, [C]))}, symbolCode(C).
   73
   74
   75number_codes_(A,B) :- catch(number_codes(A,B), _, false).
   76
   77digit(D)   --> {delay(number_codes_(D, [C]))},
   78               digitCode(C).
   79natural(N) --> {delay(number_codes_(N, Ds))},
   80               list(digitCode, Ds).
   81integer(N) --> {delay(number_codes_(N, Codes)),
   82                delay(append([Sign, Ds], Codes))},
   83               optional(sign,Sign), list(digitCode, Ds).
   84
   85sign([0'-]) --> `-`.
   86sign([0'+]) --> `+`.
   87
   88
   89% Greedy and non greedy
   90:- meta_predicate non_greedy(3,*,*).   91non_greedy(Goal) --> non_greedy(Goal,_).
   92
   93:- meta_predicate non_greedy(3,-,*,*).   94non_greedy(_Goal,[]) --> [].
   95non_greedy(Goal,[X|Xs]) --> call(Goal,X), non_greedy(Goal,Xs).
   96
   97:- meta_predicate list(3,?,?,?).   98list(ElemDCG) -->
   99    list(ElemDCG, _).
  100
  101:- meta_predicate list(3,?,?,?).  102list(ElemDCG, [Elem|Tail]) -->
  103    call(ElemDCG, Elem),
  104    list(ElemDCG, Tail).
  105list(_, []) --> [].
  106
  107:- meta_predicate list(3,2,?,?,?).  108list(ElemDCG, SepDCG, [Elem|Tail]) -->
  109    call(ElemDCG, Elem),
  110    (call(SepDCG), list(ElemDCG, SepDCG, Tail) ; {Tail=[]})