18
19:- module(snobol, [
20 any//1
21 , notany//1
22 , arb//0
23 , arbno//1
24 , bal//1
25 , span//1
26 , break//1
27 , len//1
28 , rem//0
29 , ($)//2
30 , op(400,yfx,$)
31 ]).
53:- meta_predicate arbno(//,?,?), $(//,?,?,?). 54
66$(P,L,S1,S2) :- phrase(P,S1,S2), dlist(L,S1,S2).
67
69dlist(Cs,L1,L2) :- is_list(Cs), !, append(Cs,L2,L1).
70dlist([],L1,L2) :- L1==L2, !.
71dlist([C|Cs],L1,L3) :- must_be(nonvar,L1), L1=[C|L2], dlist(Cs,L2,L3).
74rem(_,[]).
77abort(_,_) :- throw(abort).
81any(L) --> [X], {member(X,L)}.
85notany(L) --> [X], {maplist(dif(X),L)}.
89arb --> []; [_], arb.
94arbno(P) --> []; call_dcg(P), arbno(P).
98span(L) --> any(L), span_tail(L).
99span_tail(_, [], []).
100span_tail(L) --> span(L).
101span_tail(L, [X|T], [X|T]) :- maplist(dif(X), L).
105break(_, [], []).
106break(L) --> notany(L), break(L).
107break(L, [X|T], [X|T]) :- member(X, L).
112len(N, L1, L2) :- length(L, N), append(L, L2, L1).
118bal(Delims) --> bal_one(Delims), arbno(bal_one(Delims)).
119bal_one(Delims) --> {Delims=[O,C]}, [O], bal(Delims), [C].
120bal_one(Delims) --> notany(Delims)
SNOBOL-inspired DCG operators
NB. FAIL is just {fail} or dcg_core:fail SUCCEED is {repeat} or dcg_core:repeat. FENCE is ! (cut).
Sequence capture in SNOBOL ($) is also $ here: use Phrase $ List to capture the sequence matched by Phrase in the List.
ABORT cannot be implemented in plain Prolog because there is no ancestral cut operator. Instead abort//0 just throws an exception which you must arrange to catch yourself.
POS, RPOS, TAB and RTAB are not context-free rules and can only be implemented in paired-state DCG which counts the current position in the string. */