How to identify if a predicate is a DCG?

In creating a predicate to generate the list of possible predicates that can be exported from a module, noticed that for DCGs the predicate indicator is showing up as a standard predicate indicator and not as DCG predicate indicator.

Standard predicate indicator

cr/3

DCG predicate indicator

cr//1

Is there a way to identify if a predicate is a DCG?


Current code to generate the list of possible predicates that can be exported.

build_export(M,Exports) :-
    module_property(M,file(F)),
    use_module(F),
    setof(Predicate_indicator,local_predicate(M:Predicate_indicator),Exports).

local_predicate(M:Name/Arity) :-
    current_predicate(M:Name/Arity),
    compound_name_arity(Head,Name,Arity),
    \+ predicate_property(M:Head,imported_from(_)).

Example run

?- build_export(dcg_basics,E);true.
E = ['$mode'/2, '$pldoc'/4, '$pldoc_link'/2, alpha_to_lower/3, atom/3, blank/2, blanks/2, blanks_to_nl/2, digit/3, digits/3, dot/2, eos/2, exp/2, float/3, int_codes/3, integer/3, list_string_without/4, mkval/3, mkval/4, nonblank/3, nonblanks/3, number/3, prolog_id_cont/3, prolog_var_name/3, remainder/3, sign/3, string/3, string_without/4, white/2, whites/2, xdigit/3, xdigits/3, xinteger/3] ;
true.

Actual export list

?- module_property(dcg_basics,exports(E)).
E = [whites/2, white/2, string_without/4, digits/3, remainder/3, atom/3, prolog_var_name/3, eos/2, xdigit/3, xinteger/3, number/3, xdigits/3, integer/3, float/3, string/3, alpha_to_lower/3, digit/3, blanks_to_nl/2, nonblank/3, nonblanks/3, blanks/2, blank/2].

For the use of ;true added to the query see: Help: I want the whole answer


EDIT

Update with knowledge from Jan W. in following post.

Current code in file module_exports.pl.

build_export(M,Exports) :-
    current_module(M), !,
    setof(Predicate_indicator,local_predicate_generator(M:Predicate_indicator),Exports).
build_export(M,_) :-
    format(string(Lines),'Module `~w'' not loaded.~nPlease use consult/1 or use_module/1 to load the module.~n',[M]),
    print_message_lines(user_error,kind(error),[Lines]).

local_predicate_generator(PI) :-
    current_predicate(M:Name/Arity),
    local_predicate(M:Name/Arity),
    dcg_indicator(M:Name/Arity,PI).

local_predicate(M:Name/Arity) :-
    compound_name_arity(Head,Name,Arity),
    \+ predicate_property(M:Head,imported_from(_)).

dcg_indicator(M:Name/Arity0,PI) :-
    compound_name_arity(Head,Name,Arity0),
    (
        predicate_property(M:Head,non_terminal)
    ->
        Arity is Arity0 - 2,
        PI = M:Name//Arity
    ;
        PI = M:Name/Arity0
    ).

Example run

Welcome to SWI-Prolog (threaded, 64 bits, version 8.3.4-11-g1db629e24)

?- working_directory(_,'C:/Users/Groot/Documents').
true.

?- [module_exports].
true.

?- build_export(dcg_basics,Exports);true.
ERROR: Module `dcg_basics' not loaded.
Please use consult/1 or use_module/1 to load the module.

true ;
true.

?- use_module(library(dcg/basics)).
true.

?- build_export(dcg_basics,Exports);true.
Exports = [mkval/3, mkval/4, alpha_to_lower//1, atom//1, blank//0, blanks//0, blanks_to_nl//0, digit//1, ... // ...|...] [write]
Exports = [mkval/3, mkval/4, alpha_to_lower//1, atom//1, blank//0, blanks//0, blanks_to_nl//0, digit//1, digits//1, dot//0, eos//0, exp//0, float//1, int_codes//1, integer//1, list_string_without//2, nonblank//1, nonblanks//1, number//1, prolog_id_cont//1, prolog_var_name//1, remainder//1, sign//1, string//1, string_without//2, white//0, whites//0, xdigit//1, xdigits//1, xinteger//1] ;
true.

The actual source code for module dcg_basics is on your local drive. The GitHub version which will be identical at the time of writing this post.

For recent versions there is predicate_property/2 with the property non_terminal

1 Like