Go an exception when aborting DCG processing .. but is anyone interested in these?

It’s not fully deterministic:

Code I’m working on (which doesn’t work) in version 8.1.32-10-g1885b056f:

:- use_module(library(clpfd)).

:- debug(dcg).

say(Where,List1,List2) :- \+ \+ debug(dcg,"~q ~q ~q",[Where,List1,List2]).

% greedily grab an "ab"
abba_char(AB,BA) --> 
   [a,b], !, 
   call(say("#1")), 
   abba_char(ABm,BA), {AB #= ABm+1}. 

% greedily grab an "ba"
abba_char(AB,BA) -->
   [b,a], !, 
   call(say("#2")),
   abba_char(AB,BAm), {BA #= BAm+1}.

% lookahead 1 char, it's not a "b", push it back!
abba_char(AB,BA), [C] -->
   [a,C], { C \== b }, !, 
   call(say("#3")),
   abba_char(AB,BA).

% lookahead 1 char, it's not an "a", push it back!
abba_char(AB,BA), [C] -->
   [b,C], { C \== a }, !, 
   call(say("#4")), 
   abba_char(AB,BA).

% characters neither "a" nor "b" are disregarded
abba_char(AB,BA) --> 
   [C], { \+ memberchk(C,[a,b]) }, !, 
   call(say("#5")), 
   abba_char(AB,BA).

% a final "a"
abba_char(0,0) --> 
   [a],!,
   call(say("#5")).

% a final "b"
abba_char(0,0) --> 
   [b],!,
   call(say("#6")).

% no character at all, which in this case means the list is now empty
abba_char(0,0) --> 
   [],
   call(say("#done")).

% helper that eats an atom and gives the parsing result

phrase_chars(X,AB,BA) :- atom_chars(X,Cs),phrase(abba_char(AB,BA),Cs).

:- begin_tests(dcg_chars).

test(0,[true(Truly)]) :- phrase_chars('',AB,BA),Truly = ([AB,BA] == [0,0]).
test(1,[true(Truly)]) :- phrase_chars('abbaabbaba',AB,BA),Truly = ([AB,BA] == [2,3]).
test(2,[true(Truly)]) :- phrase_chars('yabybayyyy',AB,BA),Truly = ([AB,BA] == [1,1]).
test(3,[true(Truly)]) :- phrase_chars('yyyyyyyyya',AB,BA),Truly = ([AB,BA] == [0,0]).
test(4,[true(Truly)]) :- phrase_chars('yyyyyyybaa',AB,BA),Truly = ([AB,BA] == [0,1]).
test(5,[true(Truly)]) :- phrase_chars('yyyyyyyba' ,AB,BA),Truly = ([AB,BA] == [0,1]).
test(6,[true(Truly)]) :- phrase_chars('yaybyayba' ,AB,BA),Truly = ([AB,BA] == [0,1]).
test(7,[true(Truly)]) :- phrase_chars('yaabby'    ,AB,BA),Truly = ([AB,BA] == [1,0]).

:- end_tests(dcg_chars). 

rt(dcg_chars) :- run_tests(dcg_chars).

You get the error as follows:

Run

phrase_chars('yaabby'    ,AB,BA).

then the Prolog Processor goes into an infinite loop. For some reason call//1 resets the lists? It is as yet a mystery to me.

Let it run a second, then call CTRL-C, and then press (a)bort.

In most cases, this ends well, but occasionally, you get the exception above.

The test code is likely irrelevant.

1 Like