36
37:- module(dcg_basics,
38 [ white//0, 39 whites//0, 40 blank//0, 41 blanks//0, 42 nonblank//1, 43 nonblanks//1, 44 blanks_to_nl//0, 45 string//1, 46 string_without//2, 47 48 alpha_to_lower//1, 49 50 digits//1, 51 digit//1, 52 integer//1, 53 float//1, 54 number//1, 55 56 xdigits//1, 57 xdigit//1, 58 xinteger//1, 59
60 prolog_var_name//1, 61 csym//1, 62
63 eol//0, 64 eos//0, 65 remainder//1, 66
67 68 atom//1 69 ]). 70:- use_module(library(lists)). 71:- use_module(library(error)).
105string_without(End, Codes) -->
106 { string(End),
107 !,
108 string_codes(End, EndCodes)
109 },
110 list_string_without(EndCodes, Codes).
111string_without(End, Codes) -->
112 list_string_without(End, Codes).
113
114list_string_without(Not, [C|T]) -->
115 [C],
116 { \+ memberchk(C, Not)
117 },
118 !,
119 list_string_without(Not, T).
120list_string_without(_, []) -->
121 [].
137string([]) -->
138 [].
139string([H|T]) -->
140 [H],
141 string(T).
147blanks -->
148 blank,
149 !,
150 blanks.
151blanks -->
152 [].
161blank -->
162 [C],
163 { nonvar(C),
164 code_type(C, space)
165 }.
171nonblanks([H|T]) -->
172 [H],
173 { code_type(H, graph)
174 },
175 !,
176 nonblanks(T).
177nonblanks([]) -->
178 [].
184nonblank(H) -->
185 [H],
186 { code_type(H, graph)
187 }.
194blanks_to_nl -->
195 "\n",
196 !.
197blanks_to_nl -->
198 blank,
199 !,
200 blanks_to_nl.
201blanks_to_nl -->
202 eos.
210whites -->
211 white,
212 !,
213 whites.
214whites -->
215 [].
222white -->
223 [C],
224 { nonvar(C),
225 code_type(C, white)
226 }.
227
228
229
250alpha_to_lower(L) -->
251 [C],
252 { nonvar(C)
253 -> code_type(C, alpha),
254 code_type(C, to_upper(L))
255 ; L = C
256 }.
257
258
259
272digits([H|T]) -->
273 digit(H),
274 !,
275 digits(T).
276digits([]) -->
277 [].
278
279digit(C) -->
280 [C],
281 { code_type(C, digit)
282 }.
283
284integer(I, Head, Tail) :-
285 nonvar(I),
286 !,
287 format(codes(Head, Tail), '~d', [I]).
288integer(I) -->
289 int_codes(Codes),
290 { number_codes(I, Codes)
291 }.
292
293int_codes([C,D0|D]) -->
294 sign(C),
295 !,
296 digit(D0),
297 digits(D).
298int_codes([D0|D]) -->
299 digit(D0),
300 digits(D).
308float(F, Head, Tail) :-
309 float(F),
310 !,
311 with_output_to(codes(Head, Tail), write(F)).
312float(F) -->
313 number(F),
314 { float(F) }.
322number(N, Head, Tail) :-
323 number(N),
324 !,
325 format(codes(Head, Tail), '~w', N).
326number(N) -->
327 { var(N)
328 },
329 !,
330 int_codes(I),
331 ( dot,
332 digit(DF0),
333 digits(DF)
334 -> {F = [0'., DF0|DF]}
335 ; {F = []}
336 ),
337 ( exp
338 -> int_codes(DI),
339 {E=[0'e|DI]}
340 ; {E = []}
341 ),
342 { append([I, F, E], Codes),
343 number_codes(N, Codes)
344 }.
345number(N) -->
346 { type_error(number, N) }.
347
348sign(0'-) --> "-".
349sign(0'+) --> "+".
350
351dot --> ".".
352
353exp --> "e".
354exp --> "E".
355
356
368xinteger(Val, Head, Tail) :-
369 integer(Val),
370 !,
371 format(codes(Head, Tail), '~16r', [Val]).
372xinteger(Val) -->
373 sign(C),
374 !,
375 xdigit(D0),
376 xdigits(D),
377 { mkval([D0|D], 16, Val0),
378 ( C == 0'-
379 -> Val is -Val0
380 ; Val = Val0
381 )
382 }.
383xinteger(Val) -->
384 xdigit(D0),
385 xdigits(D),
386 { mkval([D0|D], 16, Val)
387 }.
395xdigit(D) -->
396 [C],
397 { code_type(C, xdigit(D))
398 }.
406xdigits([D0|D]) -->
407 xdigit(D0),
408 !,
409 xdigits(D).
410xdigits([]) -->
411 [].
412
413mkval([W0|Weights], Base, Val) :-
414 mkval(Weights, Base, W0, Val).
415
416mkval([], _, W, W).
417mkval([H|T], Base, W0, W) :-
418 W1 is W0*Base+H,
419 mkval(T, Base, W1, W).
420
421
422
430eol --> "\n", !.
431eol --> "\r\n", !.
432eol --> eos.
447eos([], []).
453remainder(List, List, []).
454
455
456
465prolog_var_name(Name) -->
466 [C0], { code_type(C0, prolog_var_start) },
467 !,
468 prolog_id_cont(CL),
469 { atom_codes(Name, [C0|CL]) }.
470
471prolog_id_cont([H|T]) -->
472 [H], { code_type(H, prolog_identifier_continue) },
473 !,
474 prolog_id_cont(T).
475prolog_id_cont([]) --> "".
476
477
478
487csym(Name, Head, Tail) :-
488 nonvar(Name),
489 format(codes(Head, Tail), '~w', [Name]).
490csym(Name) -->
491 [F], {code_type(F, csymf)},
492 csyms(Rest),
493 { atom_codes(Name, [F|Rest]) }.
494
495csyms([H|T]) -->
496 [H], {code_type(H, csym)},
497 !,
498 csyms(T).
499csyms([]) -->
500 "".
501
502
503
512atom(Atom, Head, Tail) :-
513 must_be(ground, Atom),
514 format(codes(Head, Tail), '~w', [Atom])
Various general DCG utilities
This library provides various commonly used DCG primitives acting on list of character codes. Character classification is based on code_type/2.
This module started its life as library(http/dcg_basics) to support the HTTP protocol. Since then, it was increasingly used in code that has no relation to HTTP and therefore this library was moved to the core library.