Skip to content

Commit 2f1306f

Browse files
committed
Run the pre-precessor once before building the first parser checkpoint
This completely removes the need to handle cases of dummy left-most positions in the source overlay module.
1 parent 1eff14b commit 2f1306f

File tree

2 files changed

+23
-35
lines changed

2 files changed

+23
-35
lines changed

src/lsp/cobol_parser/parser_engine.ml

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ module Make (Config: Cobol_config.T) = struct
219219

220220
(* --- *)
221221

222-
let do_parse: type m. m state -> _ -> _ * m state =
222+
let do_parse: type m. m state -> _ -> _ -> _ * m state =
223223

224224
let rec next_tokens ({ preproc = { tokzr; _ }; _ } as ps) tokens =
225225
match Tokzr.next_token tokzr tokens with
@@ -423,16 +423,22 @@ module Make (Config: Cobol_config.T) = struct
423423
Some v, ps
424424

425425
in
426-
fun ps c -> normal ps [] c
426+
fun ps tokens c -> normal ps tokens c
427427

428428
let parse ?verbose ?show ~recovery
429-
(type m) ~(memory: m memory) pp checkpoint
429+
(type m) ~(memory: m memory) pp make_checkpoint
430430
: ('a option, m) output * _ =
431431
let ps = init_parser ?verbose ?show ~recovery
432432
~tokenizer_memory:memory pp in
433433
let res, ps =
434434
(* TODO: catch in a deeper context to grab parsed tokens *)
435-
try do_parse ps checkpoint with e -> None, add_diag (DIAGS.of_exn e) ps
435+
let ps, tokens = produce_tokens ps in
436+
let first_pos = match tokens with
437+
| [] -> Cobol_preproc.position ps.preproc.pp
438+
| t :: _ -> Cobol_common.Srcloc.start_pos ~@t
439+
in
440+
try do_parse ps tokens (make_checkpoint first_pos)
441+
with e -> None, add_diag (DIAGS.of_exn e) ps
436442
in
437443
match memory with
438444
| Amnesic ->
@@ -482,9 +488,8 @@ let parse
482488
init_source_format = source_format}
483489
in
484490
let module P = Make (val config) in
485-
P.parse ?verbose ?show ~memory ~recovery pp @@
486-
Grammar.Incremental.compilation_group @@
487-
Cobol_preproc.position pp
491+
P.parse ?verbose ?show ~memory ~recovery pp
492+
Grammar.Incremental.compilation_group
488493
end
489494
in
490495
{

src/lsp/cobol_preproc/src_overlay.ml

Lines changed: 11 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,6 @@ type manager =
6767
over_right_gap: limit Links.t; (** associates the right limit of a token to
6868
the left limit of the next *)
6969
cache: (srcloc * limit) Links.t;
70-
leftmost_in_file: (string, limit) Hashtbl.t;
7170
id: string; (** manager identifier (for logging/debugging) *)
7271
}
7372

@@ -80,37 +79,25 @@ let new_manager: string -> manager =
8079
right_of = Links.create 42;
8180
over_right_gap = Links.create 42;
8281
cache = Links.create 42;
83-
leftmost_in_file = Hashtbl.create 3;
8482
id = Pretty.to_string "%s-%u" manager_name !id;
8583
}
8684

8785
(** Returns left and right (potentially fresh) limits for the given source
8886
location; for any given file, must be called with the leftmost location
8987
first. *)
90-
(* TODO: try to see whether registering the leftmost location in each file could
91-
be done more efficiently wihtout a membership test on each new location (but
92-
the pre-processor does not provide change-of-file info to the parser). *)
9388
let limits: manager -> srcloc -> limit * limit = fun ctx loc ->
9489
let s, e = match Cobol_common.Srcloc.as_unique_lexloc loc with
9590
| Some lexloc -> lexloc
9691
| _ -> Limit.make_virtual (), Limit.make_virtual ()
9792
in
9893
Links.replace ctx.right_of s (loc, e); (* replace to deal with duplicates *)
99-
if not (Hashtbl.mem ctx.leftmost_in_file s.pos_fname)
100-
then Hashtbl.add ctx.leftmost_in_file s.pos_fname s;
10194
s, e
10295

10396
(** Links token limits *)
10497
let link_limits ctx left right =
10598
(* Replace to deal with overriding of limits during recovery. *)
10699
Links.replace ctx.over_right_gap left right
107100

108-
(** [leftmost_limit_in ~filename ctx] finds the leftmost limit from a location
109-
in [filename] that is registered in [ctx] (internal). Use with moderation
110-
as this is quite inefficient. *)
111-
let leftmost_limit_in ~filename ctx =
112-
Hashtbl.find_opt ctx.leftmost_in_file filename
113-
114101
(** Returns a source location that spans between two given limits; returns a
115102
valid pointwise location if the two given limits are physically equal. *)
116103
let join_limits: manager -> limit * limit -> srcloc = fun ctx (s, e) ->
@@ -124,7 +111,7 @@ let join_limits: manager -> limit * limit -> srcloc = fun ctx (s, e) ->
124111
in
125112
Cobol_common.Srcloc.raw (pos, pos)
126113
in
127-
let try_limits (s, e) =
114+
let try_limits (s, e: limit * limit) =
128115

129116
let rec proceed_from ?loc s = (* start search from left limit [s] *)
130117
check ?loc @@ Links.find ctx.right_of s
@@ -137,7 +124,8 @@ let join_limits: manager -> limit * limit -> srcloc = fun ctx (s, e) ->
137124
| None -> loc'
138125
| Some loc -> Cobol_common.Srcloc.concat loc loc'
139126
in
140-
if e == e' (* physical comparison *)
127+
if e.pos_cnum = e'.pos_cnum && (* compare only the fields that matter *)
128+
e.pos_fname = e'.pos_fname
141129
then (Links.replace ctx.cache s (loc, e); loc)
142130
else try_cache_from ~loc @@ Links.find ctx.over_right_gap e'
143131

@@ -163,19 +151,14 @@ let join_limits: manager -> limit * limit -> srcloc = fun ctx (s, e) ->
163151
(* Printexc.(print_raw_backtrace Stdlib.stderr @@ get_callstack 10); *)
164152
loc
165153
in
166-
(* first attempt assumes proper token limits: `s` is a left and `e` is a
167-
right of tokens *)
168-
try try_limits (s, e) with Not_found ->
169-
(* otherwise try assuming `s` is an end of token *)
170-
try try_limits (Links.find ctx.over_right_gap s, e) with Not_found ->
171-
try if s.pos_cnum = 0 (* potential special case with left-position forged by
172-
the parser: retry with leftmost limit if it differs
173-
from s *)
174-
then match leftmost_limit_in ~filename:s.pos_fname ctx with
175-
| Some l when l != s -> try_limits (l, e) (* physical equality is enough *)
176-
| Some _ | None -> raise Not_found
177-
else raise Not_found
178-
with Not_found -> join_failure (s, e)
154+
try (* first attempt assumes proper token limits: `s` is a left and `e` is a
155+
right of tokens *)
156+
try_limits (s, e)
157+
with Not_found ->
158+
try (* otherwise try assuming `s` is an end of token *)
159+
try_limits (Links.find ctx.over_right_gap s, e)
160+
with Not_found ->
161+
join_failure (s, e)
179162

180163
module New_manager (Id: sig val name: string end) : MANAGER = struct
181164
let ctx = new_manager Id.name

0 commit comments

Comments
 (0)