# Example that shows how to use call\_dcg/3 to implement state/context?

**URL:** <https://swi-prolog.discourse.group/t/example-that-shows-how-to-use-call-dcg-3-to-implement-state-context/939>\
**Category:** Help!\
**Created:** [July 10, 2019, 2:33am UTC](https://swi-prolog.discourse.group/t/example-that-shows-how-to-use-call-dcg-3-to-implement-state-context/939 "2019-07-10T02:33:38Z")\
**Posts on this page:** 1\
**Showing post:** 2

<div class="post-metadata">

**Author:** ![EricGT](https://avatars.discourse-cdn.com/v4/letter/e/f1d935/32.png) [@EricGT](https://swi-prolog.discourse.group/u/EricGT)\
**Post date:** [July 10, 2019, 4:51am UTC](https://swi-prolog.discourse.group/t/example-that-shows-how-to-use-call-dcg-3-to-implement-state-context/939/2 "2019-07-10T04:51:34Z")

</div>

To me the question is a bit confusing but understandably why it is confusing is because you are just learning about DCGs. As such I will answer this by taking various parts of the question out and and answer them but not in the order asked.

> [@prodog](#):
>
> I noticed that the help page on call\_dcg/3 seems to indicate you can use this call to do this

I don’t think I have ever used [call\_dcg/3](https://www.swi-prolog.org/pldoc/doc_for?object=call_dcg/3) ([source](https://github.com/SWI-Prolog/swipl-devel/blob/4bbfbecd32eda899b03e38e6a60054bdb493e579/boot/dcg.pl#L368-L376)) except once to check it out to see how it works, I essentially use just [phrase/3](https://www.swi-prolog.org/pldoc/doc_for?object=phrase/3) ([source](https://github.com/SWI-Prolog/swipl-devel/blob/4bbfbecd32eda899b03e38e6a60054bdb493e579/boot/dcg.pl#L363-L366)) instead. The reason being that in the documentation it notes,

> This predicate (call\_dcg/3) was introduced after type checking was added to [phrase/3](https://www.swi-prolog.org/pldoc/man?predicate=phrase/3).

In looking at the [source](https://github.com/SWI-Prolog/swipl-devel/blob/4bbfbecd32eda899b03e38e6a60054bdb493e579/boot/dcg.pl#L368-L376) one notices that phrase/3 executes call\_dcg/3 but phrase/3 also has some type checking. I have never found the type checking of phrase/3 to cause me problems. Also most example you find will use phrase/2 which is just

```prolog
phrase(RuleSet, Input) :-
    phrase(RuleSet, Input, []).

```

so essentially, phrase/2 is phrase/3 with the third parameter being set to `[]`.

So the example below will use phrase/3.

* * *

> [@prodog](#):
>
> I have a DCG app coming up where I’m going to want to carry some state variables around during the parse.

Use phrase/2 or phrase/3.

* * *

> [@prodog](#):
>
> Is there a sophisticated example around that shows how to do this using SWI-Prolog?

I don’t know what you mean by sophisticated, so I will give what I consider a plain and simple example.

For the example I will use [digits//1](https://www.swi-prolog.org/pldoc/man?predicate=digits//1) ([source](https://github.com/SWI-Prolog/swipl-devel/blob/ad9b759017f959218b72e2dbe38aa986b8717220/library/dcg/basics.pl#L262-L271)) from library [DCG basics](https://www.swi-prolog.org/pldoc/doc/_SWI_/library/dcg/basics.pl) - ([predicates](https://www.swi-prolog.org/pldoc/man?section=summary-lib-dcgbasics))

Notice that the signature of `digits//1` has two `/` and not one. This is because digits//1 is to not be though of as a Prolog predicate with 1 argument but a clause with 1 visible argument. In reality it is also digits/3, a predicate with 3 arguments. To see this use [listing/1](https://www.swi-prolog.org/pldoc/man?predicate=listing/1), e.g.

```prolog
?- listing(digits/3).
dcg_basics:digits([H|T], A, B) :-
    digit(H, A, C),
    !,
    D=C,
    digits(T, D, B).
dcg_basics:digits([], A, A).

true.

```

compare that with the source code

```prolog
digits([H|T]) -->
	digit(H), !,
	digits(T).
digits([]) -->
	[].

```

listing/1 with digits//1 also works.

```prolog
?- listing(digits//1).
dcg_basics:digits([H|T], A, B) :-
    digit(H, A, C),
    !,
    D=C,
    digits(T, D, B).
dcg_basics:digits([], A, A).

true.

```

If you change the `A` and `B` to `S0` and `S`  
and `C` to `S1`  
and `D` to `S2`  
you get

```prolog
dcg_basics:digits([H|T], S0, S) :-
    digit(H, S0, S1),
    !,
    S2=S1,
    digits(T, S2, S).
dcg_basics:digits([], S0, S0).

```

which is the `S0` and `S` from [call\_dcg/3](https://www.swi-prolog.org/pldoc/doc_for?object=call_dcg/3). So `S0` and `S` are hidden state variables you are looking to pass around.

For the actual example I will use Prolog unit tests so that you will and others will have the basic template for doing this and so that you can add more test easily without having to write the basic code over and over.

```prolog
:- use_module(library(dcg/basics)).

:- begin_tests(digits).

digits_test_case("1",[49],[]).
digits_test_case("1",[0'1],[]).

test(001, [forall(digits_test_case(Input,Expected_digits,Expected_rest))]) :-
    string_codes(Input,Codes),
    DCG = digits(Digits),
    phrase(DCG,Codes,Rest),
    assertion( Rest == Expected_rest ),
    assertion( Digits == Expected_digits ).

:- end_tests(digits).

```

To use this consult the code as normal, then `run_tests`.

```prolog
?- consult("C:/Users/Eric/Documents/Projects/Prolog/swi-discourse_004.pl").
true.

?- run_tests.
% PL-Unit: digits .. done
% All 2 tests passed
true.

```

This shows that the code was successfully loaded and that the two test case ran successfully.

The two test case are identical, but the expected result, while being the same, is written with two different ways of portraying the [ASCII](http://www.asciitable.com/) character 1. The first is as the character code as a decimal, `49` and the second is as a special Prolog form that uses the human readable glyph for the number one, `1` but so that it is converted to the character code during complication, the `0'` prefix tells the compiler to covert this to a character code.

To add more test cases just edit the code and save

```prolog
digits_test_case("9",[0'9],[]).
digits_test_case("123",[0'1,0'2,0'3],[]).

```

then run make.

```prolog
?- make.
% c:/users/eric/documents/projects/prolog/swi-discourse_004 compiled 0.00 sec, 1 clauses
% PL-Unit: digits .... done
% All 4 tests passed
true.

```

The code loaded, compiled, ran 4 tests, and all 4 tests passed.

* * *

When using DCGs, some people like to process the data as characters codes and some people like to process the data as atoms. It took me a while to get this. The code in the library dcg/basics processes the data as character codes so be fore warned.

You should also be aware of [set\_prolog\_flag/2](https://www.swi-prolog.org/pldoc/doc_for?object=set_prolog_flag/2) and the option [doublequotes](https://www.swi-prolog.org/pldoc/man?section=flags#flag:double_quotes). See: [The string type and its double quoted syntax](https://www.swi-prolog.org/pldoc/man?section=strings). I used it in this earlier [example](https://swi-prolog.discourse.group/t/are-dcgs-just-syntactic-sugar/933/15)

* * *

Since digits//1 is really digits/3 you can also do this

```prolog
digits(Digits,S0,S).

```

If you add this test case to the example which uses digits/3 instead

```prolog
test(002, [forall(digits_test_case(Input,Expected_digits,Expected_rest))]) :-
    string_codes(Input,Codes),
    digits(Digits,Codes,Rest),
    assertion( Rest == Expected_rest ),
    assertion( Digits == Expected_digits ).

```

then you get

```prolog
?- make.
% c:/users/eric/documents/projects/prolog/swi-discourse_004 compiled 0.00 sec, 2 clauses
% PL-Unit: digits ........ done
% All 8 tests passed
true.

```

So the 4 test of test case `01` worked and the same 4 test with test `02` also worked the same.

---

_[View the full topic](https://swi-prolog.discourse.group/t/example-that-shows-how-to-use-call-dcg-3-to-implement-state-context/939)._
