-
Notifications
You must be signed in to change notification settings - Fork 1
/
SimCont.ml
342 lines (299 loc) · 11 KB
/
SimCont.ml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
(* SimCont.ml *)
(*
A modfied simStep.ml to operate without the context stack. This requires adding continuation information to the tree.
State between accepting characters is still logically stored in OneChar locations.
*)
(*open Sexplib.Std*)
(*open Sexplib.Sexp*)
(*open Sexplib*)
open CamomileLibrary
open Common
open History
open WhichTest
(*open Pattern*)
open ReadPattern
open CorePattern
open Simulate
open SimStep
open Core.Result
TYPE_CONV_PATH "SimCont"
type contData = { cHistory : history
; cAt : coreQ
}
type contMap = contData HistMap.t
let simCont ?(prevIn=(-1,newline)) (cr : coreResult) : simFeed =
let numTags = Array.length cr.tags
and root = cr.cp
in
let prev = ref prevIn (* Anchors can test facts about preceding character *)
and winners = ref []
and m1 = ref HistMap.empty (* on each iteration vivify possibilities from here *)
and m2 = ref HistMap.empty (* while matching store paused possibilities here *)
and startHistory = { tagA = Array.make numTags (-1)
; repA = Array.make cr.depthCount 0
; orbitA = Array.make cr.orbitCount []
}
in
let cycle here =
prev := here;
m1 := !m2;
m2 := HistMap.empty;
let listWinners = !winners in
winners := [];
listWinners
in
let rec nextStep = function
| StepChar ((_i,_c) as here) ->
spark here;
HistMap.iter !m1 ~f:(process here);
cycle here
| StepEnd indexAtEnd ->
sparkEnd indexAtEnd;
HistMap.iter !m1 ~f:(processEnd indexAtEnd);
cycle (indexAtEnd,newline)
and process ((i,_c) as here) ~key:_ ~data:c =
forOpt c.cAt.postTag (fun tag -> doTagTask i c.cHistory (tag,TagTask));
dispatch here c.cHistory c.cAt
and processEnd indexAtEnd ~key:_ ~data:c =
forOpt c.cAt.postTag (fun tag -> doTagTask indexAtEnd c.cHistory (tag,TagTask));
dispatchEnd indexAtEnd c.cHistory c.cAt
and dispatch ((i,_c) as here) h at =
match at.contTo with
HowReturn q -> doReturn here h q
| HowReturnMidSeq q -> doReturnMidSeq here h q
| HowRoot -> doWin i h
and dispatchEnd indexAtEnd h at =
match at.contTo with
HowReturn q -> doReturnEnd indexAtEnd h q
| HowReturnMidSeq q -> doReturnMidSeqEnd indexAtEnd h q
| HowRoot -> doWin indexAtEnd h
and spark ((i,_c) as here) =
let h = copyHistory startHistory in
doTagTask i h (0,TagTask);
begin
match doEnterNull here h root with
None -> ()
| Some hNullWin -> doWin i hNullWin
end;
doEnter here h root
and sparkEnd indexAtEnd =
let h = copyHistory startHistory in
doTagTask indexAtEnd h (0,TagTask);
match doEnterNullEnd indexAtEnd h root with
None -> ()
| Some hNullWin -> doWin indexAtEnd hNullWin
and doWin i h =
doTagTask i h (1,TagTask);
winners := h :: !winners
and doEnterNullEnd indexAtEnd h q =
let (_,pc) = !prev in
let checkTest (test,(expect,_)) =
expect = (match test with
Test_BOL -> pc = newline
| Test_EOL -> true) in
let tryNull (testSet,_taskList) =
match testSet with
AlwaysTrue -> true
| AlwaysFalse -> false
| CheckAll tests -> List.for_all checkTest (WhichTestMap.to_alist tests)
in
match Core.Core_list.drop_while ~f:(fun x -> not (tryNull x)) q.nullQ with
[] -> None
| ((_testSet,taskList)::_) ->
let hpass = doTasks indexAtEnd (copyHistory h) taskList
in Some hpass
(* doEnterNull with return a new copy of the history when it returns *)
and doEnterNull ((i,c) as _here) h q =
let (_,pc) = !prev in
let checkTest (test,(expect,_)) =
expect = (match test with
Test_BOL -> pc = newline
| Test_EOL -> c = newline) in
let tryNull (testSet,_taskList) =
match testSet with
AlwaysTrue -> true
| AlwaysFalse -> false
| CheckAll tests -> List.for_all checkTest (WhichTestMap.to_alist tests)
in
match Core.Core_list.drop_while ~f:(fun x -> not (tryNull x)) q.nullQ with
[] -> None
| ((_testSet,taskList)::_) ->
let hpass = doTasks i (copyHistory h) taskList
in Some hpass
and doEnter ((i,c) as here) h q =
if (Some 0 = snd q.takes)
then ()
else
begin
forOpt q.preTag (fun tag -> doTagTask i h (tag,TagTask));
match q.unQ with
Or qs -> forList qs (fun qChild -> doEnter here (copyHistory h) qChild)
| Seq (qFront,qBack) ->
begin
match doEnterNull here h qFront with
None -> ()
| Some hSkipFront -> doEnter here hSkipFront qBack
end;
doEnter here h qFront
| Repeat r ->
let doOrbit task = (fun (t,o) -> doOrbitTask i h (t,o,task)) in
begin
if h.repA.(r.repDepth) <> 0
then failwith "impossible: doEnter.Repeat found non-zero h.repA.(r.repDepth)";
doRepTask h (r.repDepth, IncRep r.topCount);
forList r.resetOrbits (doOrbit ResetOrbitTask);
forOpt r.getOrbit (doOrbit EnterOrbitTask);
doEnter here h r.unRep
end
| Test _ ->
begin
match q.takes with
(lo,None) -> Printf.printf "(%d,None)\n" lo
| (lo,Some hi) -> Printf.printf "(%d,Some %d)\n" lo hi
end;
failwith "impossible: doEnter.Test should be unreachable" (* or just be value () *)
| CaptureGroup cg ->
forList cg.preReset (fun tag ->
doTagTask i h (tag,ResetGroupStopTask));
doEnter here h cg.subPat
| OneChar (uc,patIndex) when USet.mem c uc ->
let hid_key = (patIndex,h.repA)
and contData = { cHistory = h
; cAt = q }
in
tryInsertHistory hid_key contData
| OneChar _ -> ()
end
and tryInsertHistory hid_key contData =
match HistMap.find !m2 hid_key with
None -> m2 := HistMap.add ~key:hid_key ~data:contData !m2
| Some oldData ->
match compareHistory cr.tags oldData.cHistory contData.cHistory with
| 1 -> m2 := HistMap.add ~key:hid_key ~data:contData !m2
| _ -> (*Printf.printf " OneChar --discarded--";*) ()
and doReturnEnd indexAtEnd h q =
let continue hContinue =
forOpt q.postTag (fun tag -> doTagTask indexAtEnd hContinue (tag,TagTask));
dispatchEnd indexAtEnd hContinue q
in
match q.unQ with
Repeat r ->
let soFar = h.repA.(r.repDepth)
and doOrbit h' task = (fun (t,o) -> doOrbitTask indexAtEnd h' (t,o,task)) in
if soFar <= 0 then failwith "impossible: doReturn.Repeat found soFar <= 0";
let goLeave hLoop =
doRepTask hLoop (r.repDepth,LeaveRep);
forOpt r.getOrbit (doOrbit hLoop LeaveOrbitTask);
continue hLoop
in
let goLoopNull hLoop =
doRepTask hLoop (r.repDepth,IncRep r.topCount);
forList r.resetOrbits (doOrbit hLoop ResetOrbitTask);
forOpt r.getOrbit (doOrbit hLoop LoopOrbitTask);
(* build special context for nullQ *)
match doEnterNullEnd indexAtEnd hLoop r.unRep with
None -> ()
| Some hLoopNull -> goLeave hLoopNull
in
if soFar < r.lowBound
then goLoopNull h
else goLeave h
| CaptureGroup cg ->
begin
doTagTask indexAtEnd h (cg.postSet,SetGroupStopTask);
continue h
end
| _ -> continue h
and doReturn ((i,_c) as here) h q =
let continue hContinue =
forOpt q.postTag (fun tag -> doTagTask i hContinue (tag,TagTask));
dispatch here hContinue q
in
match q.unQ with
Repeat r ->
let soFar = h.repA.(r.repDepth)
and doOrbit h' task = (fun (t,o) -> doOrbitTask i h' (t,o,task)) in
if soFar <= 0 then failwith "impossible: doReturn.Repeat found soFar <= 0";
let goLoop hLoop = (* this is prerequsite for future doReturn *)
doRepTask hLoop (r.repDepth,IncRep r.topCount);
forList r.resetOrbits (doOrbit hLoop ResetOrbitTask);
forOpt r.getOrbit (doOrbit hLoop LoopOrbitTask);
doEnter here hLoop r.unRep
and goLeave hLeave = (* no guarantee that soFar is at leat r.lowBound *)
doRepTask hLeave (r.repDepth,LeaveRep);
forOpt r.getOrbit (doOrbit hLeave LeaveOrbitTask);
continue hLeave
in
let goLoopNull hLoop =
doRepTask hLoop (r.repDepth,IncRep r.topCount);
forList r.resetOrbits (doOrbit hLoop ResetOrbitTask);
forOpt r.getOrbit (doOrbit hLoop LoopOrbitTask);
match doEnterNull here hLoop r.unRep with
None -> ()
| Some hLoopNull -> goLeave hLoopNull
in
begin
if soFar < r.lowBound
then
begin
goLoopNull (copyHistory h);
goLoop h
end
else
begin
match r.optHiBound with
Some hi when soFar > hi -> failwith "impossible soFar > hi";
| Some hi when soFar = hi -> goLeave h
| _ ->
begin
goLeave (copyHistory h);
goLoop h
end
end
end
| CaptureGroup cg ->
doTagTask i h (cg.postSet,SetGroupStopTask);
continue h
| _ -> continue h
and doReturnMidSeq here h q =
match q.unQ with
Seq (_qFront,qBack) ->
begin
match doEnterNull here h qBack with
None -> ()
| Some hSkipBack -> doReturn here hSkipBack q
end;
doEnter here h qBack
| _ -> failwith "impossible: doReturnMidSeq on a non Seq node!"
and doReturnMidSeqEnd indexAtEnd h q =
match q.unQ with
Seq (_qFront,qBack) ->
begin
match doEnterNullEnd indexAtEnd h qBack with
None -> ()
| Some hSkipBack -> doReturnEnd indexAtEnd hSkipBack q
end
| _ -> failwith "impossible: doReturnMidSeqEnd on a non Seq node!"
in nextStep
let uWrapCont (cr : coreResult) (text : ustring) : o =
let indexAtEnd = String.length text
and textList = stringToList text
and nextStep = simCont cr
and allWins = ref []
in
let rec go = function
| [] ->
let wins = nextStep (StepEnd indexAtEnd) in
allWins := wins @ !allWins;
List.map (fun h -> (interpretGroups 0 cr.groups h,h))
(List.sort (compareHistory cr.tags) !allWins)
| (x::xs) ->
let wins = nextStep (StepChar x) in
allWins := wins @ !allWins;
go xs
in
go textList
let wrapSimCont (pattern : ustring) (text: ustring) : o =
match (parseRegex pattern) with
Error _err -> (*Printf.printf "Error: %s\n" err;*) []
| Ok p -> let cr = toCorePattern p in uWrapCont cr text