I must say that I don’t know enough about the scoping of cuts, so the source code of sequence/3 is baffling me… in the sense that I cannot find the exact point of failure (the nearest point seems to be located near line 128 in dcg/high_order.pl).
In the following module, I tried to report the problem, and also to show what I was expecting, in a (partial) implementation, named naive_seq/3
.
Of course, I would like test(ko1) and test(ko2) to succeed…
:- module(test_parse,
[]).
:- begin_tests(test_parse).
:- use_module(library(dcg/basics)).
:- use_module(library(dcg/high_order)).
:- use_module(library(plunit)).
codes(`1 2 3 | 4 5 6`).
integers_ko1(Is) --> sequence(integer, whites, Is).
integers_ko2(Is) --> sequence(integer, white, Is).
integers_ok1([]) --> [].
integers_ok1([I|Is]) --> integer(I), ( " " -> integers_ok1(Is) ; {Is = []} ).
naive_seq(OnElem, OnSep, Es) -->
{var(Es)} -> naive_seq_(Es, OnElem, OnSep).
naive_seq_([], _OnElem, _OnSep) --> [].
naive_seq_([H|T], OnElem, OnSep) -->
call(OnElem, H),
( OnSep -> naive_seq_(T, OnElem, OnSep) ; {T = []} ).
integers_ok2(Is) --> naive_seq(integer, whites, Is).
integers_ok3(Is) --> naive_seq(integer, white, Is).
test(ko1, [fail]) :-
codes(Cs),
phrase((
integers_ko1(_),
whites,
"|",
whites,
integers_ko1(_)), Cs).
test(ko2, [fail]) :-
codes(Cs),
phrase((
integers_ko2(_),
whites,
"|",
whites,
integers_ko2(_)), Cs).
test(ok1, [true(Is1=[1,2,3]), true(Is2=[4,5,6])]) :-
codes(Cs),
phrase((
integers_ok1(Is1),
whites,
"|",
whites,
integers_ok1(Is2)), Cs).
test(ok2, [true(Is1=[1,2,3]), true(Is2=[4,5,6])]) :-
codes(Cs),
phrase((
integers_ok2(Is1),
whites,
"|",
whites,
integers_ok2(Is2)), Cs).
test(ok3, [true(Is1=[1,2,3]), true(Is2=[4,5,6])]) :-
codes(Cs),
phrase((
integers_ok3(Is1),
whites,
"|",
whites,
integers_ok3(Is2)), Cs).
:- end_tests(test_parse).
Sideway question: is a cut after → (like seen on line 128 of dcg/high_order.pl) an efficiency booster ? I thought that the arrow already implemented the cut. I’m wrong ?