@@ -519,9 +519,12 @@ module Make (Config: Cobol_config.T) = struct
519
519
and ('a, 'm) rewindable_history_event =
520
520
{
521
521
preproc_position : Lexing .position ;
522
- event_stage : ('a , 'm ) interim_stage ;
522
+ event_stage : ('a , 'm ) interim_stage_without_tokens ;
523
523
}
524
524
525
+ and ('a, 'm) interim_stage_without_tokens =
526
+ 'm state * 'a Grammar_interpr. env (* Always valid input_needed env. *)
527
+
525
528
let init_rewindable_parse ps ~make_checkpoint =
526
529
{
527
530
init = ps;
@@ -530,17 +533,23 @@ module Make (Config: Cobol_config.T) = struct
530
533
}
531
534
532
535
(* * Stores a stage as part of the memorized rewindable history events. *)
533
- let save_history_event (( ps , _ , _ ) as stage ) (store : _ rewindable_history ) =
536
+ let save_interim_stage ( ps , _ , env ) (store : _ rewindable_history ) =
534
537
let preproc_position = Cobol_preproc. position ps.preproc.pp in
535
538
match store with
539
+ | store'
540
+ when preproc_position.pos_cnum <> preproc_position.pos_bol ->
541
+ (* We must only save positions that correspond to beginning of lines;
542
+ this should only make us skip recording events at the end of
543
+ inputs. *)
544
+ store'
536
545
| { preproc_position = prev_pos; _ } :: store'
537
546
when prev_pos.pos_cnum = preproc_position.pos_cnum &&
538
547
prev_pos.pos_fname = preproc_position.pos_fname ->
539
548
(* Preprocessor did not advance further since last save: replace event
540
549
with new parser state: *)
541
- { preproc_position; event_stage = stage } :: store'
550
+ { preproc_position; event_stage = (ps, env) } :: store'
542
551
| store' ->
543
- { preproc_position; event_stage = stage } :: store'
552
+ { preproc_position; event_stage = (ps, env) } :: store'
544
553
545
554
let rewindable_parser_state = function
546
555
| { stage = Final (_ , ps ) | Trans (ps , _ , _ ); _ } -> ps
@@ -560,7 +569,7 @@ module Make (Config: Cobol_config.T) = struct
560
569
| Trans ((ps , _ , _ ) as state ) ->
561
570
let store, count =
562
571
if count = save_stage then store, succ count
563
- else save_history_event state store, 0
572
+ else save_interim_stage state store, 0
564
573
and stage =
565
574
try on_interim_stage state with e -> on_exn ps e
566
575
in
@@ -574,15 +583,23 @@ module Make (Config: Cobol_config.T) = struct
574
583
pos
575
584
| Indexed { line; char } ->
576
585
let ps = rewindable_parser_state rwps in
577
- let lexpos = Cobol_preproc. position ps.preproc.pp in
578
586
let newline_cnums = Cobol_preproc. newline_cnums ps.preproc.pp in
579
- let pos_bol =
580
- try List. nth newline_cnums (line - 1 )
581
- with Not_found | Invalid_argument _ -> 0
582
- in
583
- Lexing. { lexpos with pos_bol;
584
- pos_cnum = pos_bol + char ;
585
- pos_lnum = line + 1 }
587
+ if newline_cnums = []
588
+ then raise Not_found (* no complete line was processed yet; just skip *)
589
+ else
590
+ let lexpos = Cobol_preproc. position ps.preproc.pp in
591
+ try
592
+ let pos_bol =
593
+ try List. nth newline_cnums (line - 1 )
594
+ with Not_found | Invalid_argument _ -> 0
595
+ in
596
+ Lexing. { lexpos with pos_bol;
597
+ pos_cnum = pos_bol + char ;
598
+ pos_lnum = line + 1 }
599
+ with Failure _ ->
600
+ (* The given line exceeds what was already processed, so we restart
601
+ from the current preprocessor position. *)
602
+ lexpos
586
603
587
604
let find_history_event_preceding ~position ({ store; _ } as rwps ) =
588
605
let lexpos = lexing_postion_of ~position rwps in
@@ -608,10 +625,11 @@ module Make (Config: Cobol_config.T) = struct
608
625
let rwps =
609
626
try
610
627
let event, store = find_history_event_preceding ~position rwps in
611
- let ps, tokens, env = event.event_stage in
628
+ let ps, env = event.event_stage in
612
629
let pp = ps.preproc.pp in
613
- let pp = pp_rewind ? new_position:( Some event.preproc_position) pp in
630
+ let pp = pp_rewind ~ new_position: event.preproc_position pp in
614
631
let ps = { ps with preproc = { ps.preproc with pp } } in
632
+ let ps, tokens = produce_tokens ps in
615
633
{ rwps with stage = Trans (ps, tokens, env); store }
616
634
with Not_found -> (* rewinding before first checkpoint *)
617
635
let pp = pp_rewind rwps.init.preproc.pp in
0 commit comments