An experiment on a mutually recursive system of closures

Regex in DCG is handy for parsing text. For example,
consider parsing this text block into a matrix 3 x 3,

 1    1+1   1
 1    1+ 1 +1
 -2  -1   0

where delimiters and fillers are defined by regexies. This example is taken from a Prolog cgi page of mine, and pack library(pac) compiles these regex into DCG phrase via constructing deterministic finite state automaton with minimum number of states. In fact,
this post is a bug fix note related to regex in the example. The bug seemed serious at first but fix was fortunately very easy.

Surprisingly, despite of such seemingly heavy preprocessing, so far performance seems not so bad. Although I am wondering why not so bad, I guess this might be due to the SWI-Prolog qlf format in a way of magic.

Instead of going (again ?) into explaining about library(pac), I would like to show a favorite recent query, which should be reproducible on library(pac) v1.9.5, I hope. This query compiles the delimiter and filler, and define a mutually recursive system of closures, and then parse the text codes a + b c into a list [“a + b”, “c”]
according to the regexies.

% swipl

?- use_module(library(pac)).
?- module(pac).

pac: ?- time((	Codes = ` a + b  c `,
		Fregex = "[\s\t\n\r]*",
		Dregex = +("[\t\r\n]" | "\s\s+"),
		pac_word:let_wl(F, Fregex),
		pac_word:let_wl(D, Dregex),
	let(Split, mrec([F, D],
		[ Pred_split  = ( [X, Y, A, B]:-call(F, A, C), !,
					call(Words, X, Y, C, B)),
		  Words = (
					( [X, X, [], []]:-! )
				&	([[[C|W]|Xs], Y, [C|A], B]:-
						call(Word_tail, W, A, A0),
						call(Words, Xs, Y, A0, B))),
		 Word_tail = (
					([[], A, B]:-call(F, A, B), current([], B, B))
				&	([[], A, B]:- call(D, A, B), !)
				&	([[C|W], [C|A], B]:- call(Word_tail, W, A, B)))])),
	 call(Split, Splitted, [], Codes, []))),
	 maplist(string_codes, Strings, Splitted).

% 12,283 inferences, 0.002 CPU in 0.002 seconds (91% CPU, 6318416 Lips)
Codes = [32, 97, 32, 43, 32, 98, 32, 32, 99|...],
Fregex = "[ \t\n\r]*",
Dregex = + ("[\t\r\n]"| "  +"),
F = user:'nt#1',
D = user:'nt#5',
Split = pac:'pac#1'([user:'nt#1', user:'nt#5']),
Pred_split = 'pac#1'([user:'nt#1', user:'nt#5']),
Words = 'pac#2'([user:'nt#1', user:'nt#5']),
Word_tail = 'pac#3'([user:'nt#1', user:'nt#5']),
Splitted = [[97, 32, 43, 32, 98], [99]],
Strings = ["a + b", "c"] .