Can those who know EDCG check that this was done correctly

Using SWI-Prolog (threaded, 64 bits, version 8.1.24) on Windows.

Being new to using EDCGs just want to make sure I am doing this correctly. The key piece of the code that I am not sure is the correct way to do it with EDCGs is the checking of the end of input. Since the input is a a list, checking for [] is done using

    A/dcg,          % Peek at head of hidden dcg list
    A \= [],

The code simply copies values from an input list (closed list) one value at a time to an output list (open list), but uses the named accumulator dcg instead of creating one.

:- module(edcg_example,
    [
        example/2
    ]).

:- use_module(library(edcg)).

edcg:acc_info(output, T, Out, In, Out=[T|In]). % reverse accumulator

edcg:pred_info(example,0,[dcg,output]).

example -->>
    A/dcg,          % Peek at head of hidden dcg list
    A \= [],
    [H]:dcg,
    [H]:output,
    example,
    !.
example -->> [].

example(Input,Output) :-
    example(Input,Rest,Out_hole_0,Out_hole),
    assertion( Rest == [] ),
    Out_hole = [],
    Output = Out_hole_0.

Listing of code after transformation

?- listing(edcg_example:_).

example(A, B, C, D) :-
    true,
    A\=[],
    A=[H|E],
    true,
    C=[H|F],
    true,
    example(E, B, F, D),
    !.
example(A, A, B, B).

example(Input, Output) :-
    example(Input, Rest, Out_hole_0, Out_hole),
    assertion(Rest==[]),
    Out_hole=[],
    Output=Out_hole_0.
true.

Test cases

:- begin_tests(eos_tests).

eos_test_case_generator(      [],     [] ).
eos_test_case_generator(     [1],    [1] ).
eos_test_case_generator(   [1,2],  [1,2] ).
eos_test_case_generator( [1,2,3],[1,2,3] ).

test(01,[forall(eos_test_case_generator(Input,Output))]) :-
    call_with_time_limit(1,example(Input,Output)).

:- end_tests(eos_tests).

Example run

?- run_tests.
% PL-Unit: eos_tests .... done
% All 4 tests passed
true.

If it looks good a simple yes will do.


EDIT

In doing some rubber duck debugging noticed in the listing

    A\=[],
    A=[H|E],

and so changed the source to

example -->>
    % A/dcg,          % Peek at head of hidden dcg list
    % A \= [],
    [H]:dcg,
    [H]:output,
    example,
    !.
example -->> [].

and the test still passed.

Was about to delete the entire post but figure it might be of value to someone someday.

Still we be nice to here some feedback.

EDCGs for this should be the same as DCGs; and I don’t understand why you would want to check for “end of input”.

If your DCG/EDCG is

foo --> [a], [b].

then an input of [a,b] will be detected properly.

I presume you’re using a variant of phrase/3 or call_dcg/3 to call your rules?

1 Like

No.

Just making sure I understand some of the basic concepts of how EDCGs work before I try them on the code doing the Hex Dump that has several accumulators.

There should be no need to check for end-of-input explicitly; that’s done implicitly by the rules.

After all, phrase/2 is basically (I’m doing this from memory):

phrase(Goal, L) :- call(Goal, L, []).

but there’s no reason it can’t be call(Goal, L, L2), L2=[], so there’s no guarantee that L2 is instantiated – L1, L2 form a difference list, with L2 being eventually instantiated to []. (Also, DCGs work on things other than lists; and with EDCGs that’s even more likely – for example, some of my accumulators are rbtrees.)

Also: https://www.metalevel.at/prolog/dcg (and there are other tutorials).

You meant:

phrase(GRBody, L) :- phrase(GRBody, L, []).
1 Like