It is common for DCGs that naked variables are rewrapped
as phrase/3 during translation. So that one can implement
A^n B^n not only for when A and B are terminals, but also
when A and B are arbitrary DCGs goals.
Here is the code for that:
s(_,_) --> [].
s(A,B) --> A, s(A,B), B.
Here one sees the translation that is done by SWI-Prolog.
As one can see the naked variables have been converted
to phrase/3 goals:
?- listing.
s(_, _, A, A).
s(A, C, B, F) :-
phrase(A, B, D),
s(A, C, D, E),
phrase(C, E, F).
Here is a sample run, for terminals A and B:
?- phrase(s("alfa","beta"),X), atom_codes(Y,X).
X = [],
Y = '' ;
X = [97, 108, 102, 97, 98, 101, 116, 97],
Y = alfabeta ;
X = [97, 108, 102, 97, 97, 108, 102, 97, 98|...],
Y = alfaalfabetabeta ;
X = [97, 108, 102, 97, 97, 108, 102, 97, 97|...],
Y = alfaalfaalfabetabetabeta .
Here is a sample run, for some DCG goals as A and B:
bit --> "0".
bit --> "1".
?- length(L,8), phrase(s(("(",bit),(bit,")")),L), atom_codes(R,L).
L = [40, 48, 40, 48, 48, 41, 48, 41],
R = '(0(00)0)' ;
L = [40, 48, 40, 48, 48, 41, 49, 41],
R = '(0(00)1)' ;
L = [40, 48, 40, 48, 49, 41, 48, 41],
R = '(0(01)0)' ;
Etc..
Bye