From 113beb15bf2769db5d5f03c7ba8f6f61ce24f984 Mon Sep 17 00:00:00 2001
From: Nicolas Berthier <nicolas.berthier@ocamlpro.com>
Date: Tue, 12 Sep 2023 15:02:12 +0200
Subject: [PATCH 01/17] Extract preprocessor logs into a dedicated module

This also comes with various refactorings here and there.
---
 src/lsp/cobol_common/srcloc.ml            | 26 +++--------
 src/lsp/cobol_common/srcloc.mli           | 19 +++-----
 src/lsp/cobol_lsp/lsp_document.ml         |  8 ++--
 src/lsp/cobol_lsp/lsp_request.ml          | 48 +++++++++----------
 src/lsp/cobol_parser/parser_engine.ml     |  4 +-
 src/lsp/cobol_parser/parser_engine.mli    |  2 +-
 src/lsp/cobol_parser/parser_options.ml    |  2 +-
 src/lsp/cobol_preproc/cobol_preproc.ml    |  2 +
 src/lsp/cobol_preproc/preproc.ml          | 25 ++++------
 src/lsp/cobol_preproc/preproc.mli         | 18 +++-----
 src/lsp/cobol_preproc/preproc_engine.ml   | 55 ++++++++++------------
 src/lsp/cobol_preproc/preproc_engine.mli  | 11 +----
 src/lsp/cobol_preproc/preproc_grammar.mly |  6 +--
 src/lsp/cobol_preproc/preproc_trace.ml    | 51 +++++++++++++++++++++
 src/lsp/cobol_preproc/preproc_trace.mli   | 56 +++++++++++++++++++++++
 src/lsp/cobol_preproc/preproc_utils.mli   |  2 +-
 16 files changed, 201 insertions(+), 134 deletions(-)
 create mode 100644 src/lsp/cobol_preproc/preproc_trace.ml
 create mode 100644 src/lsp/cobol_preproc/preproc_trace.mli

diff --git a/src/lsp/cobol_common/srcloc.ml b/src/lsp/cobol_common/srcloc.ml
index 9cf9dd487..807a249e8 100644
--- a/src/lsp/cobol_common/srcloc.ml
+++ b/src/lsp/cobol_common/srcloc.ml
@@ -57,6 +57,9 @@ module TYPES = struct
   (* ... but forbids other cats directly on its right. *)
   and right_ = [raw_|cpy_|rpl_]
 
+  (** Sets of copied libraries *)
+  type copylocs = copyloc list
+
   (** Values attached with a source location. *)
   type 'a with_loc = { payload: 'a; loc: srcloc [@compare fun _ _ -> 0] }
   [@@ deriving ord]
@@ -644,23 +647,6 @@ let copy_from ~filename ~copyloc { payload; loc } =
 
 (* --- *)
 
-module COPYLOCS = struct
-  (** Helper to record and format chains of copied libraries. *)
-
-  type t = copyloc list                                           (* reversed *)
-
-  let none: t = []
-  let append ~copyloc filename : t -> t = List.cons { filename; copyloc }
-  let mem: string -> t -> bool = fun f ->
-    List.exists (fun { filename; _ } -> filename = f)
-
-end
-
-(* TODO: move me to a better place. This type declaration has to be
-   shared by Common_ast and Common_preproc *)
-(* NB: not necessarily.  One refers to pre-processing concept, the other to the
-   semantics of some COBOL statements like INSPECT or EXAMINE. *)
-type leading_or_trailing =
-  | Leading
-  | Trailing
-[@@deriving show, ord]
+let no_copy: copylocs = []
+let new_copy ~copyloc filename = List.cons { filename; copyloc }
+let mem_copy f  = List.exists (fun { filename; _ } -> filename = f)
diff --git a/src/lsp/cobol_common/srcloc.mli b/src/lsp/cobol_common/srcloc.mli
index bb584946c..b371757d7 100644
--- a/src/lsp/cobol_common/srcloc.mli
+++ b/src/lsp/cobol_common/srcloc.mli
@@ -14,13 +14,14 @@
 module TYPES: sig
   type lexloc = Lexing.position * Lexing.position
   type srcloc
-  type 'a with_loc = { payload: 'a; loc: srcloc; }
-  [@@deriving ord]
+  type copylocs
+  type 'a with_loc = { payload: 'a; loc: srcloc; }                [@@deriving ord]
 end
 type lexloc = TYPES.lexloc
 type srcloc = TYPES.srcloc
+type copylocs = TYPES.copylocs
 type 'a with_loc = 'a TYPES.with_loc =
-  { payload: 'a; loc: srcloc; } [@@deriving ord]
+  { payload: 'a; loc: srcloc; }                                  [@@deriving ord]
 
 module INFIX: sig
   (* Meaning of letters:
@@ -107,12 +108,6 @@ val concat_locs: _ with_loc list -> srcloc option
 val concat_strings_with_loc: string with_loc -> string with_loc -> string with_loc
 val copy_from: filename:string -> copyloc:srcloc -> 'a with_loc -> 'a with_loc
 
-module COPYLOCS: sig
-  type t
-  val none: t
-  val append: copyloc:srcloc -> string -> t -> t
-  val mem: string -> t -> bool
-end
-
-type leading_or_trailing = Leading | Trailing
-[@@deriving show, ord]
+val no_copy: copylocs
+val new_copy: copyloc:srcloc -> string -> copylocs -> copylocs
+val mem_copy: string -> copylocs -> bool
diff --git a/src/lsp/cobol_lsp/lsp_document.ml b/src/lsp/cobol_lsp/lsp_document.ml
index c849b38a4..a8127962b 100644
--- a/src/lsp/cobol_lsp/lsp_document.ml
+++ b/src/lsp/cobol_lsp/lsp_document.ml
@@ -25,7 +25,7 @@ module TYPES = struct
       project: Lsp_project.t;
       textdoc: Lsp.Text_document.t;
       copybook: bool;
-      pplog: Cobol_preproc.rev_log;
+      pplog: Cobol_preproc.log;
       tokens: Cobol_parser.tokens_with_locs Lazy.t;
       parsed: parsed_data option;
       (* Used for caching, when loading a cache file as the file is not reparsed,
@@ -52,7 +52,7 @@ module TYPES = struct
       doc_cache_checksum: Digest.t; (* checked against file on disk on reload *)
       doc_cache_langid: string;
       doc_cache_version: int;
-      doc_cache_pplog: Cobol_preproc.rev_log;
+      doc_cache_pplog: Cobol_preproc.log;
       doc_cache_tokens: Cobol_parser.tokens_with_locs;
       doc_cache_parsed: (PTREE.compilation_group * CUs.t) option;
       doc_cache_diags: DIAGS.Set.serializable;
@@ -103,7 +103,7 @@ let lazy_references ast cus defs =
 let analyze ({ project; textdoc; copybook; _ } as doc) =
   let pplog, tokens, (parsed, diags) =
     if copybook then
-      [], lazy [], (None, DIAGS.Set.none)
+      Cobol_preproc.Trace.empty, lazy [], (None, DIAGS.Set.none)
     else
       let ptree = parse ~project textdoc in
       Cobol_parser.preproc_rev_log ptree,
@@ -129,7 +129,7 @@ let blank ~project ?copybook textdoc =
   {
     project;
     textdoc;
-    pplog = [];
+    pplog = Cobol_preproc.Trace.empty;
     tokens = lazy [];
     diags = DIAGS.Set.none;
     parsed = None;
diff --git a/src/lsp/cobol_lsp/lsp_request.ml b/src/lsp/cobol_lsp/lsp_request.ml
index 9de767d0e..4cedd22ba 100644
--- a/src/lsp/cobol_lsp/lsp_request.ml
+++ b/src/lsp/cobol_lsp/lsp_request.ml
@@ -233,36 +233,36 @@ let handle_semantic_tokens_full registry (params: SemanticTokensParams.t) =
 
 let handle_hover registry (params: HoverParams.t) =
   let filename = Lsp.Uri.to_path params.textDocument.uri in
-  let find_hovered_replacement pplog =
-    List.find_opt begin fun Cobol_preproc.{ matched_loc; _ } ->
-      Lsp_position.is_in_lexloc params.position
-        (Cobol_common.Srcloc.lexloc_in ~filename matched_loc)
-    end pplog
+  let find_hovered_pplog_event pplog =
+    List.find_opt begin function
+      | Cobol_preproc.Replacement { matched_loc = loc; _ }
+      | Cobol_preproc.FileCopy { copyloc = loc; _ } ->
+          Lsp_position.is_in_lexloc params.position
+            (Cobol_common.Srcloc.lexloc_in ~filename loc)
+    end (Cobol_preproc.Trace.events pplog)
   in
   let hover_markdown ~loc value =
     let content = MarkupContent.create ~kind:MarkupKind.Markdown ~value in
     let range = Lsp_position.range_of_srcloc_in ~filename loc in
     Some (Hover.create () ~contents:(`MarkupContent content) ~range)
   in
-  try_with_document_data registry params.textDocument
-    ~f:begin fun ~project ~textdoc:_ ~pplog ~tokens:_ { ast; _ } ->
-      match Lsp_lookup.copy_at_pos ~filename params.position ast with
-      | Some { payload = lib; loc } ->
-          let text = EzFile.read_file lib in
-          (* TODO: grab source-format from preprocessor state? *)
-          let module Config = (val project.cobol_config) in
-          let mdlang = match Config.format#value with
-            | SF (SFFree | SFVariable | SFCOBOLX) -> "cobolfree"
-            | SF _ | Auto -> "cobol"
-          in
-          Pretty.string_to (hover_markdown ~loc) "```%s\n%s\n```" mdlang text
-      | None ->
-          match find_hovered_replacement pplog with
-          | None -> None
-          | Some Cobol_preproc.{ matched_loc = loc; replacement_text; _ } ->
-              Pretty.string_to (hover_markdown ~loc) "``@[<h>%a@]``"
-                Cobol_preproc.Text.pp_text replacement_text
-    end
+  let Lsp_document.{ project; pplog; _ } =
+    Lsp_server.find_document params.textDocument registry in
+  match find_hovered_pplog_event pplog with
+  | Some Replacement { matched_loc = loc; replacement_text; _ } ->
+      Pretty.string_to (hover_markdown ~loc) "``@[<h>%a@]``"
+        Cobol_preproc.Text.pp_text replacement_text
+  | Some FileCopy { copyloc = loc; status = CopyDone lib | CyclicCopy lib } ->
+      let text = EzFile.read_file lib in
+      (* TODO: grab source-format from preprocessor state? *)
+      let module Config = (val project.cobol_config) in
+      let mdlang = match Config.format#value with
+        | SF (SFFree | SFVariable | SFCOBOLX) -> "cobolfree"
+        | SF _ | Auto -> "cobol"
+      in
+      Pretty.string_to (hover_markdown ~loc) "```%s\n%s\n```" mdlang text
+  | Some FileCopy { status = MissingCopy _; _ } | None ->
+      None
 
 let handle_completion registry (params:CompletionParams.t) =
   let open Lsp_completion in
diff --git a/src/lsp/cobol_parser/parser_engine.ml b/src/lsp/cobol_parser/parser_engine.ml
index 9a3a5b9ac..528ee1907 100644
--- a/src/lsp/cobol_parser/parser_engine.ml
+++ b/src/lsp/cobol_parser/parser_engine.ml
@@ -446,8 +446,8 @@ module Make (Config: Cobol_config.T) = struct
         Only res, all_diags ps
     | Eidetic ->
         let tokens = Tokzr.parsed_tokens ps.preproc.tokzr
-        and rev_log = Cobol_preproc.rev_log ps.preproc.pp in
-        WithTokens (res, tokens, rev_log), all_diags ps
+        and log = Cobol_preproc.log ps.preproc.pp in
+        WithTokens (res, tokens, log), all_diags ps
 
 end
 
diff --git a/src/lsp/cobol_parser/parser_engine.mli b/src/lsp/cobol_parser/parser_engine.mli
index a3c913f7f..20d82f080 100644
--- a/src/lsp/cobol_parser/parser_engine.mli
+++ b/src/lsp/cobol_parser/parser_engine.mli
@@ -30,4 +30,4 @@ val parse_with_tokens: Cobol_common.Behaviors.eidetic parsing_function
 val parsed_tokens
   : (_, Cobol_common.Behaviors.eidetic) parsed_result -> tokens_with_locs Lazy.t
 val preproc_rev_log
-  : (_, Cobol_common.Behaviors.eidetic) parsed_result -> Cobol_preproc.rev_log
+  : (_, Cobol_common.Behaviors.eidetic) parsed_result -> Cobol_preproc.log
diff --git a/src/lsp/cobol_parser/parser_options.ml b/src/lsp/cobol_parser/parser_options.ml
index f15be8e58..b113cf5be 100644
--- a/src/lsp/cobol_parser/parser_options.ml
+++ b/src/lsp/cobol_parser/parser_options.ml
@@ -34,7 +34,7 @@ type tokens_with_locs = Grammar_tokens.token with_loc list
 type ('a, 'm) output =
   | Only: 'a ->
       ('a, Cobol_common.Behaviors.amnesic) output
-  | WithTokens: 'a * tokens_with_locs Lazy.t * Cobol_preproc.rev_log ->
+  | WithTokens: 'a * tokens_with_locs Lazy.t * Cobol_preproc.log ->
       ('a, Cobol_common.Behaviors.eidetic) output
 
 type ('a, 'm) parsed_result =
diff --git a/src/lsp/cobol_preproc/cobol_preproc.ml b/src/lsp/cobol_preproc/cobol_preproc.ml
index 0badb5222..a425eaf96 100644
--- a/src/lsp/cobol_preproc/cobol_preproc.ml
+++ b/src/lsp/cobol_preproc/cobol_preproc.ml
@@ -18,5 +18,7 @@ module Text = Text
 module Text_printer = Text_printer
 
 module Copybook = Copybook
+module Trace = Preproc_trace
 
+include Trace.TYPES
 include Preproc_engine
diff --git a/src/lsp/cobol_preproc/preproc.ml b/src/lsp/cobol_preproc/preproc.ml
index 276df5aa4..fef209aa2 100644
--- a/src/lsp/cobol_preproc/preproc.ml
+++ b/src/lsp/cobol_preproc/preproc.ml
@@ -22,6 +22,7 @@ module DIAGS = Cobol_common.Diagnostics
 (* --- *)
 
 include Preproc_tokens                         (* include token type directly *)
+include Preproc_trace                          (* include log events *)
 
 (* --- *)
 
@@ -153,17 +154,11 @@ and replacing =
       }
 and partial_subst =
   {
-    partial_subst_dir: Cobol_common.Srcloc.leading_or_trailing;
+    partial_subst_dir: replacing_direction;
     partial_subst_len: int;
     partial_subst_regexp: Str.regexp;
   }
-
-type log_entry =
-  {
-    matched_loc: srcloc;
-    replacement_text: text;
-  }
-type log = log_entry list
+and replacing_direction = Leading | Trailing
 
 (* --- Implementation of replacing operations ------------------------------- *)
 
@@ -202,7 +197,7 @@ let partial_word (type k) (req: k partial_word_request) words : (k, _) result =
 
 type partial_replacing =
   {
-    repl_dir: Cobol_common.Srcloc.leading_or_trailing;
+    repl_dir: replacing_direction;
     repl_strict: bool;
   }
 
@@ -486,7 +481,7 @@ let try_replacing_clause: replacing with_loc -> text -> _ result = fun replacing
         match pseudotext_exact_match ~&repl_from text with
         | Ok (l, r, matched_loc, suffix) ->
             let replacement_text = to_text ~replloc repl_to ~old:matched_loc in
-            let log_entry = { matched_loc; replacement_text } in
+            let log_entry = Replacement { matched_loc; replacement_text } in
             Ok (delim l replacement_text r, log_entry, suffix)
         | Error _ as e ->
             e
@@ -495,10 +490,10 @@ let try_replacing_clause: replacing with_loc -> text -> _ result = fun replacing
       begin fun text ->
         match textword_partial_replace ~replloc repl_subst repl_to text with
         | Ok ((t, matched_loc), suffix) when ~&t = "" ->
-            Ok ([], { matched_loc; replacement_text = [] }, suffix)
+            Ok ([], Replacement { matched_loc; replacement_text = [] }, suffix)
         | Ok ((t, matched_loc), suffix) ->
             let replacement_text = [lift_textword t] in
-            let log_entry = { matched_loc; replacement_text } in
+            let log_entry = Replacement { matched_loc; replacement_text } in
             Ok (replacement_text, log_entry, suffix)
         | Error _ as e ->
             e
@@ -531,11 +526,11 @@ let apply_replacing k repl log =
     fun k done_text log text ->
       match k, try_replacing_phrase k repl text, text with
       | OnPartText, Ok (done_text', le, []), _ ->
-          Ok (done_text @ done_text', le :: log)
+          Ok (done_text @ done_text', Preproc_trace.append le log)
       | OnFullText, Ok (done_text', le, []), _ ->
-          done_text @ done_text', le :: log
+          done_text @ done_text', Preproc_trace.append le log
       | _, Ok (done_text', le, text), _ ->
-          aux k (done_text @ done_text') (le :: log) text
+          aux k (done_text @ done_text') (Preproc_trace.append le log) text
       | OnPartText, Error `MissingText, _ ->
           Error (`MissingText (done_text, log, text))
       | OnPartText, Error `NoReplacement, [] ->
diff --git a/src/lsp/cobol_preproc/preproc.mli b/src/lsp/cobol_preproc/preproc.mli
index 44bfcbc0b..43f7b8cf7 100644
--- a/src/lsp/cobol_preproc/preproc.mli
+++ b/src/lsp/cobol_preproc/preproc.mli
@@ -54,20 +54,14 @@ and library =
 and fileloc = [`Word | `Alphanum] * string
 and replacing
 
-type log_entry =
-  {
-    matched_loc: srcloc;
-    replacement_text: text;
-  }
-type log = log_entry list
-
 type (_, _) repl_attempt =
   | OnPartText: ([`NoReplacement | `MissingText],
                  partial_text_repl_result) repl_attempt
   | OnFullText: ([`NoReplacement],
-                 text * log) repl_attempt
+                 text * Preproc_trace.log) repl_attempt
 and partial_text_repl_result =
-  (text * log, [`MissingText of text * log * text]) result
+  (text * Preproc_trace.log,
+   [`MissingText of text * Preproc_trace.log * text]) result
 
 module type ENTRY_POINTS = sig
   type 'x entry
@@ -90,9 +84,11 @@ end
 
 type partial_replacing =
   {
-    repl_dir: Cobol_common.Srcloc.leading_or_trailing;
+    repl_dir: replacing_direction;
     repl_strict: bool;
   }
+and replacing_direction = Leading | Trailing
+
 val replacing
   : ?partial:partial_replacing
   -> pseudotext with_loc
@@ -101,7 +97,7 @@ val replacing
 val apply_replacing
   : (_, 'a) repl_attempt
   -> replacing with_loc list
-  -> log
+  -> Preproc_trace.log
   -> text
   -> 'a
 
diff --git a/src/lsp/cobol_preproc/preproc_engine.ml b/src/lsp/cobol_preproc/preproc_engine.ml
index 0306db49b..c9d780933 100644
--- a/src/lsp/cobol_preproc/preproc_engine.ml
+++ b/src/lsp/cobol_preproc/preproc_engine.ml
@@ -11,7 +11,7 @@
 (*                                                                        *)
 (**************************************************************************)
 
-open Cobol_common.Srcloc
+open Cobol_common.Srcloc.TYPES
 open Cobol_common.Srcloc.INFIX
 open Cobol_common.Diagnostics.TYPES
 
@@ -36,22 +36,12 @@ let decide_source_format _input
 
 (* --- *)
 
-type log = log_entry list
-and rev_log = log
-and log_entry = Preproc.log_entry =
-  {
-    matched_loc: Cobol_common.Srcloc.srcloc;
-    replacement_text: Text.text;
-  }
-
-(* --- *)
-
 type preprocessor =
   {
     buff: Text.text;
     srclex: Preproc.any_srclexer;
     ppstate: Preproc.state;
-    pplog: Preproc.log;
+    pplog: Preproc_trace.log;
     diags: DIAGS.diagnostics;
     persist: preprocessor_persist;
   }
@@ -62,7 +52,7 @@ and preprocessor_persist =
     overlay_manager: (module Src_overlay.MANAGER);
     config: Cobol_config.t;
     replacing: Preproc.replacing with_loc list list;
-    copybooks: COPYLOCS.t;                                (* opened copybooks *)
+    copybooks: Cobol_common.Srcloc.copylocs;              (* opened copybooks *)
     libpath: string list;
     verbose: bool;
     show_if_verbose: [`Txt | `Src] list;
@@ -72,19 +62,21 @@ let diags { diags; srclex; _ } =
   DIAGS.Set.union diags @@ Preproc.srclex_diags srclex
 let add_diag lp d = { lp with diags = DIAGS.Set.cons d lp.diags }
 let add_diags lp d = { lp with diags = DIAGS.Set.union d lp.diags }
-let log { pplog; _ } = List.rev pplog
-let rev_log { pplog; _ } = pplog
+let log { pplog; _ } = (* List.rev *) pplog
+(* let rev_log { pplog; _ } = pplog *)
 let srclexer { srclex; _ } = srclex
 let position { srclex; _ } = Preproc.srclex_pos srclex
 
 let with_srclex lp srclex =
   if lp.srclex == srclex then lp else { lp with srclex }
-let with_diags lp diags =
-  if lp.diags == diags then lp else { lp with diags }
+(* let with_diags lp diags = *)
+(*   if lp.diags == diags then lp else { lp with diags } *)
 let with_buff lp buff =
   if lp.buff == buff then lp else { lp with buff }
 let with_pplog lp pplog =
   if lp.pplog == pplog then lp else { lp with pplog }
+let with_diags_n_pplog lp diags pplog =
+  if lp.diags == diags && lp.pplog == pplog then lp else { lp with diags; pplog }
 let with_buff_n_pplog lp buff pplog =
   if lp.buff == buff && lp.pplog == pplog then lp else { lp with buff; pplog }
 let with_replacing lp replacing =
@@ -121,15 +113,15 @@ let preprocessor ?(on_period_only = true) ?(verbose = false) input = function
         buff = [];
         srclex = make_srclex ~on_period_only ~source_format input;
         ppstate = Preproc.initial_state;
-        pplog = [];
-        diags = diags;
+        pplog = Preproc_trace.empty;
+        diags;
         persist =
           {
             pparser = (module Pp);
             overlay_manager = (module Om);
             config = (module Config);
             replacing = [];
-            copybooks = COPYLOCS.none;
+            copybooks = Cobol_common.Srcloc.no_copy;
             libpath;
             verbose;
             show_if_verbose = [`Src];
@@ -144,7 +136,8 @@ let preprocessor ?(on_period_only = true) ?(verbose = false) input = function
         persist =
           {
             persist with
-            copybooks = COPYLOCS.append ~copyloc copybook persist.copybooks;
+            copybooks =
+              Cobol_common.Srcloc.new_copy ~copyloc copybook persist.copybooks;
             verbose = persist.verbose || verbose;
           };
       }
@@ -306,28 +299,30 @@ and do_replace lp rev_prefix repl suffix =
   `ReplaceDone (lp, prefix, suffix)
 
 
-and read_lib ({ diags; persist = { libpath; copybooks; verbose; _ }; _ } as lp)
+and read_lib ({ persist = { libpath; copybooks; verbose; _ }; _ } as lp)
     loc { libname; cbkname } =
   let libpath = match ~&?cbkname with None -> libpath | Some (_, d) -> [d] in
-  let text, diags = match Copybook.find_lib ~libpath ~&libname with
-    | Ok filename when COPYLOCS.mem filename copybooks ->
+  let text, diags, pplog = match Copybook.find_lib ~libpath ~&libname with
+    | Ok filename when Cobol_common.Srcloc.mem_copy filename copybooks ->
         (* TODO: `note addendum *)
         [],
-        DIAGS.Acc.error diags ~loc "@[Cyclic@ COPY@ of@ `%s'@]" filename
+        DIAGS.Acc.error lp.diags ~loc "@[Cyclic@ COPY@ of@ `%s'@]" filename,
+        Preproc_trace.cyclic_copy ~loc ~filename lp.pplog
     | Ok filename ->
         if verbose then
           Pretty.error "Reading library `%s'@." filename;
-        let text, pp' =
-          full_text
+        let text, lp =             (* note: [lp] holds all prev and new diags *)
+          full_text                (* likewise for pplog *)
             (preprocessor (Filename filename) (`Fork (lp, loc, filename)))
             ~postproc:(Cobol_common.Srcloc.copy_from ~filename ~copyloc:loc)
         in
-        text, pp'.diags
+        text, lp.diags, Preproc_trace.copy_done ~loc ~filename lp.pplog
     | Error lnf ->
         [],
-        Copybook.lib_not_found_error (DIAGS.Acc.error diags ~loc "%t") lnf
+        Copybook.lib_not_found_error (DIAGS.Acc.error lp.diags ~loc "%t") lnf,
+        Preproc_trace.missing_copy ~loc ~info:lnf lp.pplog
   in
-  text, with_diags lp diags
+  text, with_diags_n_pplog lp diags pplog
 
 and full_text ?(item = "library") ?postproc lp : Text.text * preprocessor =
   let eofp p = ~&p = Text.Eof in
diff --git a/src/lsp/cobol_preproc/preproc_engine.mli b/src/lsp/cobol_preproc/preproc_engine.mli
index 7b59810f4..071bb2736 100644
--- a/src/lsp/cobol_preproc/preproc_engine.mli
+++ b/src/lsp/cobol_preproc/preproc_engine.mli
@@ -25,21 +25,12 @@ type init =
     init_source_format: Cobol_config.source_format_spec;
   }
 
-type log = log_entry list
-and rev_log = log
-and log_entry = Preproc.log_entry =
-  {
-    matched_loc: Cobol_common.Srcloc.srcloc;
-    replacement_text: Text.text;
-  }
-
 (* --- *)
 
 val diags: preprocessor -> Cobol_common.Diagnostics.Set.t
 val add_diag: preprocessor -> Cobol_common.Diagnostics.t -> preprocessor
 val add_diags: preprocessor -> Cobol_common.Diagnostics.Set.t -> preprocessor
-val log: preprocessor -> log
-val rev_log: preprocessor -> rev_log
+val log: preprocessor -> Preproc_trace.log
 val srclexer: preprocessor -> Preproc.any_srclexer
 val position: preprocessor -> Lexing.position
 val next_sentence: preprocessor -> Text.text * preprocessor
diff --git a/src/lsp/cobol_preproc/preproc_grammar.mly b/src/lsp/cobol_preproc/preproc_grammar.mly
index c28c1735a..f297825fa 100644
--- a/src/lsp/cobol_preproc/preproc_grammar.mly
+++ b/src/lsp/cobol_preproc/preproc_grammar.mly
@@ -133,9 +133,9 @@ let copy_replacing_text_identifier :=
       and rpar = Text.pseudoword_of_string (")" &@<- _rpar) in
       c @ [lpar] @ cl @ [rpar] }
 
-let leading_or_trailing :=
-  | LEADING;  { Cobol_common.Srcloc.Leading }
-  | TRAILING; { Cobol_common.Srcloc.Trailing }
+let leading_or_trailing ==
+  | LEADING;  { Preproc.Leading }
+  | TRAILING; { Preproc.Trailing }
 
 (* --- REPLACE -------------------------------------------------------------- *)
 
diff --git a/src/lsp/cobol_preproc/preproc_trace.ml b/src/lsp/cobol_preproc/preproc_trace.ml
new file mode 100644
index 000000000..2d00b4433
--- /dev/null
+++ b/src/lsp/cobol_preproc/preproc_trace.ml
@@ -0,0 +1,51 @@
+(**************************************************************************)
+(*                                                                        *)
+(*  Copyright (c) 2021-2023 OCamlPro SAS                                  *)
+(*                                                                        *)
+(*  All rights reserved.                                                  *)
+(*  This file is distributed under the terms of the                       *)
+(*  OCAMLPRO-NON-COMMERCIAL license.                                      *)
+(*                                                                        *)
+(**************************************************************************)
+
+(** Some utilities to log preprocessing events. *)
+
+open Cobol_common.Srcloc.TYPES
+
+module TYPES = struct
+  type log_entry =
+    | FileCopy of
+        {
+          copyloc: srcloc;
+          status: copy_event_status;
+        }
+    | Replacement of
+        {
+          matched_loc: srcloc;
+          replacement_text: Text.text;
+        }
+
+  and copy_event_status =
+    | CopyDone of string
+    | CyclicCopy of string
+    | MissingCopy of Copybook.lib_not_found_info
+
+  type log = log_entry list
+end
+include TYPES
+
+(* --- *)
+
+let empty = []
+let append =
+  List.cons
+let copy_done ~loc ~filename : log -> log =
+  List.cons @@ FileCopy { copyloc = loc; status = CopyDone filename }
+let cyclic_copy ~loc ~filename : log -> log =
+  List.cons @@ FileCopy { copyloc = loc; status = CyclicCopy filename }
+let missing_copy ~loc ~info : log -> log =
+  List.cons @@ FileCopy { copyloc = loc; status = MissingCopy info }
+
+(* --- *)
+
+let events: log -> log_entry list = List.rev
diff --git a/src/lsp/cobol_preproc/preproc_trace.mli b/src/lsp/cobol_preproc/preproc_trace.mli
new file mode 100644
index 000000000..3e99a6a17
--- /dev/null
+++ b/src/lsp/cobol_preproc/preproc_trace.mli
@@ -0,0 +1,56 @@
+(**************************************************************************)
+(*                                                                        *)
+(*  Copyright (c) 2021-2023 OCamlPro SAS                                  *)
+(*                                                                        *)
+(*  All rights reserved.                                                  *)
+(*  This file is distributed under the terms of the                       *)
+(*  OCAMLPRO-NON-COMMERCIAL license.                                      *)
+(*                                                                        *)
+(**************************************************************************)
+
+module TYPES: sig
+  type log_entry =
+    | FileCopy of
+        {
+          copyloc: Cobol_common.Srcloc.srcloc;
+          status: copy_event_status;
+        }
+    | Replacement of
+        {
+          matched_loc: Cobol_common.Srcloc.srcloc;
+          replacement_text: Text.text;
+        }
+
+  and copy_event_status =
+    | CopyDone of string
+    | CyclicCopy of string
+    | MissingCopy of Copybook.lib_not_found_info
+
+  type log
+end
+
+include module type of TYPES
+  with type copy_event_status = TYPES.copy_event_status
+   and type log_entry = TYPES.log_entry
+   and type log = TYPES.log
+
+val empty: log
+val append
+  : log_entry
+  -> log -> log
+val copy_done
+  : loc: Cobol_common.srcloc
+  -> filename: string
+  -> log -> log
+val cyclic_copy
+  : loc: Cobol_common.srcloc
+  -> filename: string
+  -> log -> log
+val missing_copy
+  : loc: Cobol_common.srcloc
+  -> info: Copybook.lib_not_found_info
+  -> log -> log
+
+(* --- *)
+
+val events: log -> log_entry list
diff --git a/src/lsp/cobol_preproc/preproc_utils.mli b/src/lsp/cobol_preproc/preproc_utils.mli
index 6277dbb27..53a2e1c08 100644
--- a/src/lsp/cobol_preproc/preproc_utils.mli
+++ b/src/lsp/cobol_preproc/preproc_utils.mli
@@ -17,7 +17,7 @@ open Cobol_common.Diagnostics.TYPES
 module Make (Config: Cobol_config.T) : sig
 
   val replacing'
-    : ?repl_dir:Cobol_common.Srcloc.leading_or_trailing
+    : ?repl_dir:Preproc.replacing_direction
     -> [< `Alphanum of Text.pseudotext
        | `PseudoText of Text.pseudotext ] Cobol_common.Srcloc.with_loc
     -> Text.pseudotext Cobol_common.Srcloc.with_loc

From 839d85822bfe03f156f41a834026fad78f05b25f Mon Sep 17 00:00:00 2001
From: Nicolas Berthier <nicolas.berthier@ocamlpro.com>
Date: Fri, 15 Sep 2023 16:20:48 +0200
Subject: [PATCH 02/17] Make `Cobol_preproc` record comments

---
 src/lsp/cobol_indent/indenter.ml            |  15 +-
 src/lsp/cobol_preproc/preproc.ml            |   9 +-
 src/lsp/cobol_preproc/preproc.mli           |   9 +-
 src/lsp/cobol_preproc/preproc_engine.ml     |  38 +-
 src/lsp/cobol_preproc/preproc_engine.mli    |  16 +-
 src/lsp/cobol_preproc/src_lexer.mll         |  26 +-
 src/lsp/cobol_preproc/src_lexing.ml         |  37 +-
 src/lsp/cobol_preproc/src_lexing.mli        |  11 +-
 src/lsp/cobol_preproc/text.mli              |   7 +
 src/lsp/cobol_preproc/text_types.ml         |   7 +
 test/cobol_parsing/decimal_point.ml         |   3 +-
 test/output-tests/listings.expected         | 712 +++++++++-----------
 test/output-tests/run_accept.expected       |   2 +-
 test/output-tests/run_extensions.expected   | 246 +++----
 test/output-tests/run_file.expected         | 148 ++--
 test/output-tests/run_functions.expected    |  96 +--
 test/output-tests/run_fundamental.expected  | 222 +-----
 test/output-tests/run_misc.expected         | 360 +++-------
 test/output-tests/run_reportwriter.expected | 700 +++++++++++++++++++
 test/output-tests/syn_misc.expected         |  26 +-
 20 files changed, 1460 insertions(+), 1230 deletions(-)

diff --git a/src/lsp/cobol_indent/indenter.ml b/src/lsp/cobol_indent/indenter.ml
index 8669ba597..78b13e943 100644
--- a/src/lsp/cobol_indent/indenter.ml
+++ b/src/lsp/cobol_indent/indenter.ml
@@ -77,18 +77,19 @@ let indent_range' ~source_format ~range ~file =
     this function has an argument which is the name of file,
     so when using lsp, every time using the formatting,
     we must save the file before, it is not convenient.
+     (* NB: not anymore. *)
   *)
   let state =
-    Cobol_preproc.fold_text_lines ~on_period_only:false ~source_format check_indent file state
+    Cobol_preproc.fold_text_lines ~source_format check_indent
+      (Filename file) state
   in
   let ind_recds = state.acc in
   indenter ~source_format file_content ind_recds state.range
 
 (*indent a range of file, with the user-defined indent_config*)
 let indent_range' ~source_format ~indent_config ~range ~file =
-  match indent_config with
-  | Some indent_config ->
-      Indent_config.set_config ~indent_config;
-      indent_range' ~source_format ~range ~file
-  | None ->
-      indent_range' ~source_format ~range ~file
+  begin match indent_config with
+    | Some indent_config -> Indent_config.set_config ~indent_config
+    | None -> ()
+  end;
+  indent_range' ~source_format ~range ~file
diff --git a/src/lsp/cobol_preproc/preproc.ml b/src/lsp/cobol_preproc/preproc.ml
index fef209aa2..09e39d8bf 100644
--- a/src/lsp/cobol_preproc/preproc.ml
+++ b/src/lsp/cobol_preproc/preproc.ml
@@ -85,18 +85,17 @@ let with_source_format
       | Ok s -> Plx (s, lexbuf)
       | Error s -> Plx (s, lexbuf)
 
-let make_srclex make_lexing on_period_only ?filename ~source_format input =
+let make_srclex make_lexing ?filename ~source_format input =
   let SF source_format = Src_lexing.select_source_format source_format in
   (* Be sure to provide position informations *)
   let lexbuf = make_lexing ?with_positions:(Some true) input in
   Option.iter (Lexing.set_filename lexbuf) filename;
-  Plx (Src_lexing.init_state on_period_only source_format, lexbuf)
+  Plx (Src_lexing.init_state source_format, lexbuf)
 
 let srclex_from_string = make_srclex Lexing.from_string
 let srclex_from_channel = make_srclex Lexing.from_channel
-let srclex_from_file on_period_only ~source_format filename : any_srclexer =
-  srclex_from_string on_period_only ~source_format ~filename
-    (EzFile.read_file filename)
+let srclex_from_file ~source_format filename : any_srclexer =
+  srclex_from_string ~source_format ~filename (EzFile.read_file filename)
 
 (* --- Compiler Directives -------------------------------------------------- *)
 
diff --git a/src/lsp/cobol_preproc/preproc.mli b/src/lsp/cobol_preproc/preproc.mli
index 43f7b8cf7..b22d09741 100644
--- a/src/lsp/cobol_preproc/preproc.mli
+++ b/src/lsp/cobol_preproc/preproc.mli
@@ -121,19 +121,16 @@ val srclex_pos
   : any_srclexer
   -> Lexing.position
 val srclex_from_file
-  : bool
-  -> source_format:Cobol_config.source_format
+  : source_format:Cobol_config.source_format
   -> string
   -> any_srclexer
 val srclex_from_string
-  : bool
-  -> ?filename: string
+  : ?filename: string
   -> source_format:Cobol_config.source_format
   -> string
   -> any_srclexer
 val srclex_from_channel
-  : bool
-  -> ?filename: string
+  : ?filename: string
   -> source_format:Cobol_config.source_format
   -> in_channel
   -> any_srclexer
diff --git a/src/lsp/cobol_preproc/preproc_engine.ml b/src/lsp/cobol_preproc/preproc_engine.ml
index c9d780933..1c97fd951 100644
--- a/src/lsp/cobol_preproc/preproc_engine.ml
+++ b/src/lsp/cobol_preproc/preproc_engine.ml
@@ -85,13 +85,13 @@ let with_replacing lp replacing =
 let show tag { persist = { verbose; show_if_verbose; _ }; _ } =
   verbose && List.mem tag show_if_verbose
 
-let make_srclex ?(on_period_only = true) ~source_format = function
+let make_srclex ~source_format = function
   | Filename filename ->
-      Preproc.srclex_from_file on_period_only ~source_format filename
+      Preproc.srclex_from_file ~source_format filename
   | String { contents; filename } ->
-      Preproc.srclex_from_string on_period_only ~filename ~source_format contents
+      Preproc.srclex_from_string ~filename ~source_format contents
   | Channel { contents; filename } ->
-      Preproc.srclex_from_channel on_period_only ~filename ~source_format contents
+      Preproc.srclex_from_channel ~filename ~source_format contents
 
 type init =
   {
@@ -100,7 +100,7 @@ type init =
     init_source_format: Cobol_config.source_format_spec;
   }
 
-let preprocessor ?(on_period_only = true) ?(verbose = false) input = function
+let preprocessor ?(verbose = false) input = function
   | `WithLibpath { init_libpath = libpath;
                    init_config = (module Config);
                    init_source_format = source_format; } ->
@@ -111,7 +111,7 @@ let preprocessor ?(on_period_only = true) ?(verbose = false) input = function
         = decide_source_format input source_format in
       {
         buff = [];
-        srclex = make_srclex ~on_period_only ~source_format input;
+        srclex = make_srclex ~source_format input;
         ppstate = Preproc.initial_state;
         pplog = Preproc_trace.empty;
         diags;
@@ -389,33 +389,33 @@ let pp_pptokens: pptokens Pretty.printer =
     {!preprocess_file}. *)
 let default_oppf = Fmt.stdout
 
-let lex_file ?(on_period_only = true) ~source_format ?(ppf = default_oppf) =
-  Cobol_common.do_unit begin fun (module DIAGS) filename ->
+let lex_file ~source_format ?(ppf = default_oppf) =
+  Cobol_common.do_unit begin fun (module DIAGS) input ->
     let source_format =
-      DIAGS.grab_diags @@ decide_source_format filename source_format in
-    let pl = Preproc.srclex_from_file on_period_only ~source_format filename in
+      DIAGS.grab_diags @@ decide_source_format input source_format in
+    let pl = make_srclex ~source_format input in
     Preproc.print_source_lines ppf pl
   end
 
-let lex_lib ?(on_period_only = true)~source_format ~libpath ?(ppf = default_oppf) =
+let lex_lib ~source_format ~libpath ?(ppf = default_oppf) =
   Cobol_common.do_unit begin fun (module DIAGS) libname ->
     match Copybook.find_lib ~libpath libname with
     | Ok filename ->
         let source_format =
-          DIAGS.grab_diags @@ decide_source_format filename source_format in
-        let pl = Preproc.srclex_from_file on_period_only ~source_format filename in
+          DIAGS.grab_diags @@
+          decide_source_format (Filename filename) source_format in
+        let pl = Preproc.srclex_from_file ~source_format filename in
         Preproc.print_source_lines ppf pl
     | Error lnf ->
         Copybook.lib_not_found_error (DIAGS.error "%t") lnf
   end
 
-(* TODO: get rid of `on_period_only` *)
-let fold_text_lines ?(on_period_only = true) ~source_format ?epf f =
-  Cobol_common.do_any ?epf begin fun (module DIAGS) filename ->
+let fold_text_lines ~source_format ?epf f =
+  Cobol_common.do_any ?epf begin fun (module DIAGS) input ->
     let source_format =
-      DIAGS.grab_diags @@ decide_source_format filename source_format in
-    let lex = Preproc.srclex_from_file on_period_only ~source_format filename in
-    Preproc.(fold_source_lines lex) f
+      DIAGS.grab_diags @@ decide_source_format input source_format in
+    let pl = make_srclex ~source_format input in
+    Preproc.fold_source_lines pl f
   end
 
 let pp_preprocessed ppf lp =
diff --git a/src/lsp/cobol_preproc/preproc_engine.mli b/src/lsp/cobol_preproc/preproc_engine.mli
index 071bb2736..44b4d7f0f 100644
--- a/src/lsp/cobol_preproc/preproc_engine.mli
+++ b/src/lsp/cobol_preproc/preproc_engine.mli
@@ -43,32 +43,28 @@ val decide_source_format
   -> Cobol_config.source_format Cobol_common.Diagnostics.with_diags
 
 val preprocessor
-  : ?on_period_only:bool
-  -> ?verbose:bool
+  : ?verbose:bool
   -> input
   -> [< `WithLibpath of init ]
   -> preprocessor
 
 val lex_file
-  : ?on_period_only:bool
-  -> source_format: Cobol_config.source_format_spec
+  : source_format: Cobol_config.source_format_spec
   -> ?ppf:Format.formatter
   -> ?epf:Format.formatter
-  -> string
+  -> input
   -> unit
 
 val fold_text_lines
-  : ?on_period_only:bool
-  -> source_format: Cobol_config.source_format_spec
+  : source_format: Cobol_config.source_format_spec
   -> ?epf:Format.formatter
   -> (Text.text -> 'a -> 'a)
-  -> string
+  -> input
   -> 'a
   -> 'a
 
 val lex_lib
-  : ?on_period_only:bool
-  -> source_format: Cobol_config.source_format_spec
+  : source_format: Cobol_config.source_format_spec
   -> libpath:string list
   -> ?ppf:Format.formatter
   -> ?epf:Format.formatter
diff --git a/src/lsp/cobol_preproc/src_lexer.mll b/src/lsp/cobol_preproc/src_lexer.mll
index 745896dd2..16d5578ad 100644
--- a/src/lsp/cobol_preproc/src_lexer.mll
+++ b/src/lsp/cobol_preproc/src_lexer.mll
@@ -124,9 +124,9 @@ rule fixed_line state
       {
         fixed_cdir_line (Src_lexing.flush_continued state) lexbuf
       }
-  | sna ['*' '/']                                             (* comment line *)
+  | sna (['*' '/'] as marker)                                 (* comment line *)
       {
-        gobble_line state lexbuf
+        comment_line marker state lexbuf
       }
   | sna ['d' 'D']
       {
@@ -189,9 +189,9 @@ and xopen_or_crt_or_acutrm_followup state
       {
         fixed_cdir_line (Src_lexing.flush_continued state) lexbuf
       }
-  | ['*' '/']                                                 (* comment line *)
+  | (['*' '/'] as marker)                                     (* comment line *)
       {
-        gobble_line state lexbuf
+        comment_line marker state lexbuf
       }
   | epsilon
       {
@@ -211,9 +211,9 @@ and cobolx_line state                                 (* COBOLX format (GCOS) *)
       {
         fixed_cdir_line (Src_lexing.flush_continued state) lexbuf
       }
-  | ['*' '/']                                                 (* comment line *)
+  | (['*' '/'] as marker)                                     (* comment line *)
       {
-        gobble_line state lexbuf
+        comment_line marker state lexbuf
       }
   | ['D' 'd']
       {
@@ -257,9 +257,9 @@ and fixed_nominal state
       {
         fixed_nominal state lexbuf
       }
-  | "*>" nnl*                                             (* floating comment *)
+  | "*>" nnl* (newline | eof)                             (* floating comment *)
       {
-        gobble_line state lexbuf
+        Src_lexing.comment ~floating:true state lexbuf
       }
   | "=="
       {
@@ -422,9 +422,9 @@ and free_nominal state
       {
         free_nominal state lexbuf
       }
-  | "*>" nnl*                                      (* floating/inline comment *)
+  | "*>" nnl* (newline | eof)                             (* floating comment *)
       {
-        free_gobble_line state lexbuf
+        Src_lexing.comment ~floating:true state lexbuf
       }
   | "=="
       {
@@ -455,6 +455,12 @@ and gobble_line state
       {
         Src_lexing.(flush @@ eof state lexbuf)
       }
+and comment_line marker state
+  = parse
+  | (nnl* (newline | eof))
+      {
+        Src_lexing.comment ~marker:(String.make 1 marker) state lexbuf
+      }
 and free_gobble_line state
   = parse
   | (nnl* newline)
diff --git a/src/lsp/cobol_preproc/src_lexing.ml b/src/lsp/cobol_preproc/src_lexing.ml
index a0b3af2f4..d0d16fb2d 100644
--- a/src/lsp/cobol_preproc/src_lexing.ml
+++ b/src/lsp/cobol_preproc/src_lexing.ml
@@ -143,9 +143,9 @@ type 'k state =
     lex_prods: text;
     continued: continued;
     pseudotext: (srcloc * text) option;
+    comments: comment list;
     cdir_seen: bool;
     newline: bool;
-    on_period_only: bool; (*newline on TextWord "." only if true, on any TextWord when false *)
     diags: DIAGS.Set.t;
     config: 'k config;
   }
@@ -169,16 +169,15 @@ and 'k config =
     source_format: 'k source_format;
   }
 
-(* TODO: get rid of `on_period_only` *)
-let init_state on_period_only: 'k source_format -> 'k state = fun source_format ->
+let init_state : 'k source_format -> 'k state = fun source_format ->
   {
     lex_prods = [];
     continued = CNone;
     pseudotext = None;
+    comments = [];
     cdir_seen = false;
     newline = true;
     diags = DIAGS.Set.none;
-    on_period_only;
     config =
       {
         debug = false;
@@ -187,6 +186,7 @@ let init_state on_period_only: 'k source_format -> 'k state = fun source_format
   }
 
 let diagnostics { diags; _ } = diags
+let comments { comments; _ } = comments
 
 let source_format { config = { source_format; _ }; _ } =
   source_format
@@ -257,13 +257,8 @@ let append t state =
 let new_line state lexbuf =
   Lexing.new_line lexbuf;
   match state.lex_prods, state.cdir_seen with
-  | { payload = (Pseudo _ | Eof); _ } :: _, _ | _, true ->
-      flush { state with newline = true }
-  | { payload = (TextWord "." ); _ } :: _, _
-    when state.on_period_only ->
-      flush { state with newline = true }
-  | { payload = (TextWord _ | Alphanum _); _ } :: _, _
-    when not @@ state.on_period_only ->
+  | { payload = TextWord _ | Alphanum _ | Pseudo _ | Eof; _ } :: _, _
+  | _, true ->
       flush { state with newline = true }
   | _ ->
       { state with newline = true }, []
@@ -561,6 +556,26 @@ type lexeme_info = string * Lexing.position * Lexing.position
 let lexeme_info lexbuf : lexeme_info =
   Lexing.(lexeme lexbuf, lexeme_start_p lexbuf, lexeme_end_p lexbuf)
 
+let comment ?(marker = "") ?(floating = false) state lexbuf =
+  let (s, start_pos, end_pos) = lexeme_info lexbuf in
+  let start_pos =                       (* include location of comment marker *)
+    Lexing.{ start_pos with
+             pos_cnum = start_pos.pos_cnum - String.length marker } in
+  let comment_contents, end_pos =
+    if EzString.ends_with ~suffix:"\n" s          (* remove potential newline *)
+    then marker ^ String.(sub s 0 (String.length s - 1)),
+         Lexing.{ end_pos with pos_cnum = end_pos.pos_cnum - 1 }
+    else marker ^ s, end_pos
+  in
+  let comment =
+    {
+      comment_loc = start_pos, end_pos;
+      comment_kind = if floating then `Floating else `Line;
+      comment_contents;
+    }
+  in
+  new_line { state with comments = comment :: state.comments } lexbuf
+
 let trunc_to_col n ((s, sp, ep) as info: lexeme_info) =
   let sc = pos_column sp and ec = pos_column ep in
   assert (sc <= n);        (* starts on last column (CHECKME: always avoided?) *)
diff --git a/src/lsp/cobol_preproc/src_lexing.mli b/src/lsp/cobol_preproc/src_lexing.mli
index 4b42651d0..ec9566c60 100644
--- a/src/lsp/cobol_preproc/src_lexing.mli
+++ b/src/lsp/cobol_preproc/src_lexing.mli
@@ -52,8 +52,10 @@ val decypher_source_format
   -> (Cobol_config.source_format, [> `SFUnknown of string ]) result
 
 type 'k state
-val init_state: bool -> 'k source_format -> 'k state
+
+val init_state: 'k source_format -> 'k state
 val diagnostics: _ state -> Cobol_common.Diagnostics.Set.t
+val comments: _ state -> Text.comment list
 val source_format: 'k state -> 'k source_format
 val change_source_format: 'k state -> 'c source_format Cobol_common.Srcloc.with_loc
   -> ('c state, 'k state) result
@@ -63,6 +65,13 @@ val flush_continued: ?force:bool -> 'a state -> 'a state
 val eof: 'a state -> Lexing.lexbuf -> 'a state
 val new_line: 'a state -> Lexing.lexbuf -> 'a state * Text.text
 
+val comment
+  : ?marker:string
+  -> ?floating:bool
+  -> 'a state
+  -> Lexing.lexbuf
+  -> 'a state * Text.text
+
 type alphanumeric_continuation =
   | Nominal
   | Closed of Text.quotation
diff --git a/src/lsp/cobol_preproc/text.mli b/src/lsp/cobol_preproc/text.mli
index 7358f7fcb..e48c1490c 100644
--- a/src/lsp/cobol_preproc/text.mli
+++ b/src/lsp/cobol_preproc/text.mli
@@ -15,6 +15,13 @@ open Cobol_common.Srcloc
 
 module TYPES = Text_types
 include module type of Text_types
+  with type text = Text_types.text
+   and type t = Text_types.t
+   and type text_word = Text_types.text_word
+   and type alphanum = Text_types.alphanum
+   and type quotation = Text_types.quotation
+   and type pseudotext = Text_types.pseudotext
+   and type comment = Text_types.comment
 
 val textwordp : text_word with_loc -> bool
 val textword_eqp : eq:string -> text_word with_loc -> bool
diff --git a/src/lsp/cobol_preproc/text_types.ml b/src/lsp/cobol_preproc/text_types.ml
index 2753e619f..df1764b81 100644
--- a/src/lsp/cobol_preproc/text_types.ml
+++ b/src/lsp/cobol_preproc/text_types.ml
@@ -51,3 +51,10 @@ and pseudoword_item =
   | PwText of string
   | PwDelim of pseudotext_delimiter
 and pseudotext_delimiter = string * Str.regexp       (* with pre-built regexp *)
+
+type comment =
+  {
+    comment_loc: lexloc;
+    comment_kind: [`Line | `Floating];
+    comment_contents: string;
+  }
diff --git a/test/cobol_parsing/decimal_point.ml b/test/cobol_parsing/decimal_point.ml
index 22e1a91cd..bd25e86d2 100644
--- a/test/cobol_parsing/decimal_point.ml
+++ b/test/cobol_parsing/decimal_point.ml
@@ -69,6 +69,5 @@ let%expect_test "decimal-point-is-comma-with-missing-period" =
     IDENTIFICATION, DIVISION, ., PROGRAM-ID, ., WORD[PROG], ., ENVIRONMENT,
     DIVISION, ., CONFIGURATION, SECTION, ., SPECIAL-NAMES, ., DECIMAL-POINT, IS,
     COMMA, PROCEDURE, DIVISION, DISPLAY, DIGITS[1], DIGITS[1], DISPLAY,
-    DIGITS[1], DIGITS[1], DISPLAY, SINT[-1], DIGITS[1], DISPLAY, FIXED[-1,1], .,
-    EOF
+    FIXED[1,1], DISPLAY, SINT[-1], DIGITS[1], DISPLAY, FIXED[-1,1], ., EOF
 |}];;
diff --git a/test/output-tests/listings.expected b/test/output-tests/listings.expected
index dc3f9c79e..121caef61 100644
--- a/test/output-tests/listings.expected
+++ b/test/output-tests/listings.expected
@@ -1120,156 +1120,6 @@ listings.at-2030-expected.lst:22.6-22.7:
   24   SIZE  TYPE           LVL  NAME                           PICTURE
 >> Error: Unexpected indicator: `B'
 
-listings.at-2030-expected.lst:24.6-24.7:
-  21   000016         EX. STOP RUN.
-  22   GnuCOBOL V.R.P          prog-1.cob                                      Page 0002
-  23   
-  24 > SIZE  TYPE           LVL  NAME                           PICTURE
-----         ^
-  25   
-  26         WORKING-STORAGE SECTION
->> Error: Unexpected indicator: `T'
-
-listings.at-2030-expected.lst:26.6-26.7:
-  23   
-  24   SIZE  TYPE           LVL  NAME                           PICTURE
-  25   
-  26 >       WORKING-STORAGE SECTION
-----         ^
-  27   
-  28   00001 ALPHANUMERIC   01   blah                           X
->> Error: Unexpected indicator: `W'
-
-listings.at-2030-expected.lst:28.6-28.7:
-  25   
-  26         WORKING-STORAGE SECTION
-  27   
-  28 > 00001 ALPHANUMERIC   01   blah                           X
-----         ^
-  29   
-  30   GnuCOBOL V.R.P          prog-1.cob                                      Page 0003
->> Error: Unexpected indicator: `A'
-
-listings.at-2030-expected.lst:30.6-30.7:
-  27   
-  28   00001 ALPHANUMERIC   01   blah                           X
-  29   
-  30 > GnuCOBOL V.R.P          prog-1.cob                                      Page 0003
-----         ^
-  31   
-  32   NAME                           DEFINED                REFERENCES
->> Error: Unexpected indicator: `B'
-
-listings.at-2030-expected.lst:36.6-36.7:
-  33   
-  34   blah                           7       *10      11      14             x3
-  35   
-  36 > GnuCOBOL V.R.P          prog-1.cob                                      Page 0004
-----         ^
-  37   
-  38   LABEL                          DEFINED                REFERENCES
->> Error: Unexpected indicator: `B'
-
-listings.at-2030-expected.lst:40.6-40.7:
-  37   
-  38   LABEL                          DEFINED                REFERENCES
-  39   
-  40 > E prog__1                      10
-----         ^
-  41   P EX                           16       12                             x1
-  42   GnuCOBOL V.R.P          prog-1.cob                                      Page 0005
->> Error: Unexpected indicator: `_'
-
-listings.at-2030-expected.lst:42.6-42.7:
-  39   
-  40   E prog__1                      10
-  41   P EX                           16       12                             x1
-  42 > GnuCOBOL V.R.P          prog-1.cob                                      Page 0005
-----         ^
-  43   
-  44   FUNCTION                       TYPE                   REFERENCES
->> Error: Unexpected indicator: `B'
-
-listings.at-2030-expected.lst:44.6-44.7:
-  41   P EX                           16       12                             x1
-  42   GnuCOBOL V.R.P          prog-1.cob                                      Page 0005
-  43   
-  44 > FUNCTION                       TYPE                   REFERENCES
-----         ^
-  45   
-  46   L prog-2                       EXTERN   11                             x1
->> Error: Unexpected indicator: `O'
-
-listings.at-2030-expected.lst:46.7-46.11:
-  43   
-  44   FUNCTION                       TYPE                   REFERENCES
-  45   
-  46 > L prog-2                       EXTERN   11                             x1
-----          ^^^^
-  47   
-  48   GnuCOBOL V.R.P          prog-1.cob                                      Page 0006
->> Warning: Unexpected non-blank area A on continuation line
-
-listings.at-2030-expected.lst:48.6-48.7:
-  45   
-  46   L prog-2                       EXTERN   11                             x1
-  47   
-  48 > GnuCOBOL V.R.P          prog-1.cob                                      Page 0006
-----         ^
-  49   
-  50   Error/Warning summary:
->> Error: Unexpected indicator: `B'
-
-listings.at-2030-expected.lst:50.6-50.7:
-  47   
-  48   GnuCOBOL V.R.P          prog-1.cob                                      Page 0006
-  49   
-  50 > Error/Warning summary:
-----         ^
-  51   
-  52   prog-1.cob:14: warning: unreachable statement 'DISPLAY'
->> Error: Unexpected indicator: `W'
-
-listings.at-2030-expected.lst:52.6-52.7:
-  49   
-  50   Error/Warning summary:
-  51   
-  52 > prog-1.cob:14: warning: unreachable statement 'DISPLAY'
-----         ^
-  53   
-  54   1 warning in compilation group
->> Error: Unexpected indicator: `.'
-
-listings.at-2030-expected.lst:54.6-54.7:
-  51   
-  52   prog-1.cob:14: warning: unreachable statement 'DISPLAY'
-  53   
-  54 > 1 warning in compilation group
-----         ^
-  55   0 errors in compilation group
-  56   GnuCOBOL V.R.P          prog-2.cob                                      Page 0001
->> Error: Unexpected indicator: `i'
-
-listings.at-2030-expected.lst:55.6-55.7:
-  52   prog-1.cob:14: warning: unreachable statement 'DISPLAY'
-  53   
-  54   1 warning in compilation group
-  55 > 0 errors in compilation group
-----         ^
-  56   GnuCOBOL V.R.P          prog-2.cob                                      Page 0001
-  57   
->> Error: Unexpected indicator: `r'
-
-listings.at-2030-expected.lst:56.6-56.7:
-  53   
-  54   1 warning in compilation group
-  55   0 errors in compilation group
-  56 > GnuCOBOL V.R.P          prog-2.cob                                      Page 0001
-----         ^
-  57   
-  58   LINE    PG/LN  A...B............................................................
->> Error: Unexpected indicator: `B'
-
 listings.at-2030-expected.lst:22.9:
   19   warning: unreachable statement 'DISPLAY'
   20   000015
@@ -1310,6 +1160,16 @@ listings.at-2030-expected.lst:22.25-22.35:
   24   SIZE  TYPE           LVL  NAME                           PICTURE
 >> Warning: Invalid syntax
 
+listings.at-2030-expected.lst:24.6-24.7:
+  21   000016         EX. STOP RUN.
+  22   GnuCOBOL V.R.P          prog-1.cob                                      Page 0002
+  23   
+  24 > SIZE  TYPE           LVL  NAME                           PICTURE
+----         ^
+  25   
+  26         WORKING-STORAGE SECTION
+>> Error: Unexpected indicator: `T'
+
 listings.at-2030-expected.lst:22.35:
   19   warning: unreachable statement 'DISPLAY'
   20   000015
@@ -1370,6 +1230,16 @@ listings.at-2030-expected.lst:24.26-24.30:
   26         WORKING-STORAGE SECTION
 >> Warning: Invalid syntax
 
+listings.at-2030-expected.lst:26.6-26.7:
+  23   
+  24   SIZE  TYPE           LVL  NAME                           PICTURE
+  25   
+  26 >       WORKING-STORAGE SECTION
+----         ^
+  27   
+  28   00001 ALPHANUMERIC   01   blah                           X
+>> Error: Unexpected indicator: `W'
+
 listings.at-2030-expected.lst:24.57-24.64:
   21   000016         EX. STOP RUN.
   22   GnuCOBOL V.R.P          prog-1.cob                                      Page 0002
@@ -1380,6 +1250,16 @@ listings.at-2030-expected.lst:24.57-24.64:
   26         WORKING-STORAGE SECTION
 >> Error: Invalid syntax
 
+listings.at-2030-expected.lst:28.6-28.7:
+  25   
+  26         WORKING-STORAGE SECTION
+  27   
+  28 > 00001 ALPHANUMERIC   01   blah                           X
+----         ^
+  29   
+  30   GnuCOBOL V.R.P          prog-1.cob                                      Page 0003
+>> Error: Unexpected indicator: `A'
+
 listings.at-2030-expected.lst:26.29:
   23   
   24   SIZE  TYPE           LVL  NAME                           PICTURE
@@ -1460,6 +1340,16 @@ listings.at-2030-expected.lst:28.57-28.58:
   30   GnuCOBOL V.R.P          prog-1.cob                                      Page 0003
 >> Warning: Invalid syntax
 
+listings.at-2030-expected.lst:30.6-30.7:
+  27   
+  28   00001 ALPHANUMERIC   01   blah                           X
+  29   
+  30 > GnuCOBOL V.R.P          prog-1.cob                                      Page 0003
+----         ^
+  31   
+  32   NAME                           DEFINED                REFERENCES
+>> Error: Unexpected indicator: `B'
+
 listings.at-2030-expected.lst:28.58:
   25   
   26         WORKING-STORAGE SECTION
@@ -1640,6 +1530,16 @@ listings.at-2030-expected.lst:34.71-34.72:
   36   GnuCOBOL V.R.P          prog-1.cob                                      Page 0004
 >> Warning: Invalid syntax
 
+listings.at-2030-expected.lst:36.6-36.7:
+  33   
+  34   blah                           7       *10      11      14             x3
+  35   
+  36 > GnuCOBOL V.R.P          prog-1.cob                                      Page 0004
+----         ^
+  37   
+  38   LABEL                          DEFINED                REFERENCES
+>> Error: Unexpected indicator: `B'
+
 listings.at-2030-expected.lst:34.72:
   31   
   32   NAME                           DEFINED                REFERENCES
@@ -1720,6 +1620,16 @@ listings.at-2030-expected.lst:38.31-38.38:
   40   E prog__1                      10
 >> Warning: Invalid syntax
 
+listings.at-2030-expected.lst:40.6-40.7:
+  37   
+  38   LABEL                          DEFINED                REFERENCES
+  39   
+  40 > E prog__1                      10
+----         ^
+  41   P EX                           16       12                             x1
+  42   GnuCOBOL V.R.P          prog-1.cob                                      Page 0005
+>> Error: Unexpected indicator: `_'
+
 listings.at-2030-expected.lst:38.38:
   35   
   36   GnuCOBOL V.R.P          prog-1.cob                                      Page 0004
@@ -1820,6 +1730,16 @@ listings.at-2030-expected.lst:41.71-41.72:
   43   
 >> Warning: Invalid syntax
 
+listings.at-2030-expected.lst:42.6-42.7:
+  39   
+  40   E prog__1                      10
+  41   P EX                           16       12                             x1
+  42 > GnuCOBOL V.R.P          prog-1.cob                                      Page 0005
+----         ^
+  43   
+  44   FUNCTION                       TYPE                   REFERENCES
+>> Error: Unexpected indicator: `B'
+
 listings.at-2030-expected.lst:41.72:
   38   LABEL                          DEFINED                REFERENCES
   39   
@@ -1880,6 +1800,16 @@ listings.at-2030-expected.lst:42.25-42.35:
   44   FUNCTION                       TYPE                   REFERENCES
 >> Warning: Invalid syntax
 
+listings.at-2030-expected.lst:44.6-44.7:
+  41   P EX                           16       12                             x1
+  42   GnuCOBOL V.R.P          prog-1.cob                                      Page 0005
+  43   
+  44 > FUNCTION                       TYPE                   REFERENCES
+----         ^
+  45   
+  46   L prog-2                       EXTERN   11                             x1
+>> Error: Unexpected indicator: `O'
+
 listings.at-2030-expected.lst:42.35:
   39   
   40   E prog__1                      10
@@ -1900,6 +1830,16 @@ listings.at-2030-expected.lst:44.7-44.8:
   46   L prog-2                       EXTERN   11                             x1
 >> Warning: Invalid syntax
 
+listings.at-2030-expected.lst:46.7-46.11:
+  43   
+  44   FUNCTION                       TYPE                   REFERENCES
+  45   
+  46 > L prog-2                       EXTERN   11                             x1
+----          ^^^^
+  47   
+  48   GnuCOBOL V.R.P          prog-1.cob                                      Page 0006
+>> Warning: Unexpected non-blank area A on continuation line
+
 listings.at-2030-expected.lst:44.8:
   41   P EX                           16       12                             x1
   42   GnuCOBOL V.R.P          prog-1.cob                                      Page 0005
@@ -1960,6 +1900,16 @@ listings.at-2030-expected.lst:46.71-46.72:
   48   GnuCOBOL V.R.P          prog-1.cob                                      Page 0006
 >> Warning: Invalid syntax
 
+listings.at-2030-expected.lst:48.6-48.7:
+  45   
+  46   L prog-2                       EXTERN   11                             x1
+  47   
+  48 > GnuCOBOL V.R.P          prog-1.cob                                      Page 0006
+----         ^
+  49   
+  50   Error/Warning summary:
+>> Error: Unexpected indicator: `B'
+
 listings.at-2030-expected.lst:46.72:
   43   
   44   FUNCTION                       TYPE                   REFERENCES
@@ -2020,6 +1970,16 @@ listings.at-2030-expected.lst:48.25-48.35:
   50   Error/Warning summary:
 >> Warning: Invalid syntax
 
+listings.at-2030-expected.lst:50.6-50.7:
+  47   
+  48   GnuCOBOL V.R.P          prog-1.cob                                      Page 0006
+  49   
+  50 > Error/Warning summary:
+----         ^
+  51   
+  52   prog-1.cob:14: warning: unreachable statement 'DISPLAY'
+>> Error: Unexpected indicator: `W'
+
 listings.at-2030-expected.lst:48.35:
   45   
   46   L prog-2                       EXTERN   11                             x1
@@ -2060,6 +2020,16 @@ listings.at-2030-expected.lst:50.14-50.22:
   52   prog-1.cob:14: warning: unreachable statement 'DISPLAY'
 >> Warning: Invalid syntax
 
+listings.at-2030-expected.lst:52.6-52.7:
+  49   
+  50   Error/Warning summary:
+  51   
+  52 > prog-1.cob:14: warning: unreachable statement 'DISPLAY'
+----         ^
+  53   
+  54   1 warning in compilation group
+>> Error: Unexpected indicator: `.'
+
 listings.at-2030-expected.lst:50.22:
   47   
   48   GnuCOBOL V.R.P          prog-1.cob                                      Page 0006
@@ -2160,6 +2130,16 @@ listings.at-2030-expected.lst:52.36-52.45:
   54   1 warning in compilation group
 >> Warning: Invalid syntax
 
+listings.at-2030-expected.lst:54.6-54.7:
+  51   
+  52   prog-1.cob:14: warning: unreachable statement 'DISPLAY'
+  53   
+  54 > 1 warning in compilation group
+----         ^
+  55   0 errors in compilation group
+  56   GnuCOBOL V.R.P          prog-2.cob                                      Page 0001
+>> Error: Unexpected indicator: `i'
+
 listings.at-2030-expected.lst:52.45:
   49   
   50   Error/Warning summary:
@@ -2200,6 +2180,16 @@ listings.at-2030-expected.lst:54.10-54.12:
   56   GnuCOBOL V.R.P          prog-2.cob                                      Page 0001
 >> Warning: Invalid syntax
 
+listings.at-2030-expected.lst:55.6-55.7:
+  52   prog-1.cob:14: warning: unreachable statement 'DISPLAY'
+  53   
+  54   1 warning in compilation group
+  55 > 0 errors in compilation group
+----         ^
+  56   GnuCOBOL V.R.P          prog-2.cob                                      Page 0001
+  57   
+>> Error: Unexpected indicator: `r'
+
 listings.at-2030-expected.lst:54.24:
   51   
   52   prog-1.cob:14: warning: unreachable statement 'DISPLAY'
@@ -2240,6 +2230,16 @@ listings.at-2030-expected.lst:55.9-55.11:
   57   
 >> Warning: Invalid syntax
 
+listings.at-2030-expected.lst:56.6-56.7:
+  53   
+  54   1 warning in compilation group
+  55   0 errors in compilation group
+  56 > GnuCOBOL V.R.P          prog-2.cob                                      Page 0001
+----         ^
+  57   
+  58   LINE    PG/LN  A...B............................................................
+>> Error: Unexpected indicator: `B'
+
 listings.at-2030-expected.lst:55.23:
   52   prog-1.cob:14: warning: unreachable statement 'DISPLAY'
   53   
@@ -2375,187 +2375,60 @@ listings.at-2030-expected.lst:76.7-76.8:
   74   000015
   75   000016             ACCEPT stuff.
   76 > warning: unreachable statement 'ACCEPT'
-----          ^
-  77   000017
-  78   000018         EX. STOP RUN.
->> Error: Invalid syntax
-
-listings.at-2030-expected.lst:76.20:
-  73   000014             GO TO EX
-  74   000015
-  75   000016             ACCEPT stuff.
-  76 > warning: unreachable statement 'ACCEPT'
-----                       ^
-  77   000017
-  78   000018         EX. STOP RUN.
->> Hint: Missing .
-
-listings.at-2030-expected.lst:76.21-76.30:
-  73   000014             GO TO EX
-  74   000015
-  75   000016             ACCEPT stuff.
-  76 > warning: unreachable statement 'ACCEPT'
-----                        ^^^^^^^^^
-  77   000017
-  78   000018         EX. STOP RUN.
->> Warning: Invalid syntax
-
-listings.at-2030-expected.lst:76.30:
-  73   000014             GO TO EX
-  74   000015
-  75   000016             ACCEPT stuff.
-  76 > warning: unreachable statement 'ACCEPT'
-----                                 ^
-  77   000017
-  78   000018         EX. STOP RUN.
->> Hint: Missing .
-
-listings.at-2030-expected.lst:76.31-76.39:
-  73   000014             GO TO EX
-  74   000015
-  75   000016             ACCEPT stuff.
-  76 > warning: unreachable statement 'ACCEPT'
-----                                  ^^^^^^^^
-  77   000017
-  78   000018         EX. STOP RUN.
->> Warning: Invalid syntax
-
-listings.at-2030-expected.lst:80.6-80.7:
-  77   000017
-  78   000018         EX. STOP RUN.
-  79   000019
-  80 > GnuCOBOL V.R.P          prog-2.cob                                      Page 0002
-----         ^
-  81   
-  82   SIZE  TYPE           LVL  NAME                           PICTURE
->> Error: Unexpected indicator: `B'
-
-listings.at-2030-expected.lst:82.6-82.7:
-  79   000019
-  80   GnuCOBOL V.R.P          prog-2.cob                                      Page 0002
-  81   
-  82 > SIZE  TYPE           LVL  NAME                           PICTURE
-----         ^
-  83   
-  84         WORKING-STORAGE SECTION
->> Error: Unexpected indicator: `T'
-
-listings.at-2030-expected.lst:84.6-84.7:
-  81   
-  82   SIZE  TYPE           LVL  NAME                           PICTURE
-  83   
-  84 >       WORKING-STORAGE SECTION
-----         ^
-  85   
-  86   00001 NUMERIC        01   data-b                         9
->> Error: Unexpected indicator: `W'
-
-listings.at-2030-expected.lst:86.6-86.7:
-  83   
-  84         WORKING-STORAGE SECTION
-  85   
-  86 > 00001 NUMERIC        01   data-b                         9
-----         ^
-  87   
-  88         LINKAGE SECTION
->> Error: Unexpected indicator: `N'
-
-listings.at-2030-expected.lst:88.6-88.7:
-  85   
-  86   00001 NUMERIC        01   data-b                         9
-  87   
-  88 >       LINKAGE SECTION
-----         ^
-  89   
-  90   00001 ALPHANUMERIC   01   stuff                          X
->> Error: Unexpected indicator: `L'
-
-listings.at-2030-expected.lst:90.6-90.7:
-  87   
-  88         LINKAGE SECTION
-  89   
-  90 > 00001 ALPHANUMERIC   01   stuff                          X
-----         ^
-  91   
-  92   GnuCOBOL V.R.P          prog-2.cob                                      Page 0003
->> Error: Unexpected indicator: `A'
-
-listings.at-2030-expected.lst:92.6-92.7:
-  89   
-  90   00001 ALPHANUMERIC   01   stuff                          X
-  91   
-  92 > GnuCOBOL V.R.P          prog-2.cob                                      Page 0003
-----         ^
-  93   
-  94   NAME                           DEFINED                REFERENCES
->> Error: Unexpected indicator: `B'
-
-listings.at-2030-expected.lst:100.6-100.7:
-  97   
-  98   stuff                          9       *10      12     *16             x3
-  99   
- 100 > GnuCOBOL V.R.P          prog-2.cob                                      Page 0004
-----         ^
- 101   
- 102   LABEL                          DEFINED                REFERENCES
->> Error: Unexpected indicator: `B'
-
-listings.at-2030-expected.lst:104.6-104.7:
- 101   
- 102   LABEL                          DEFINED                REFERENCES
- 103   
- 104 > E prog__2                      11
-----         ^
- 105   P MAIN                         11     not referenced
- 106   P EX                           18       14                             x1
->> Error: Unexpected indicator: `_'
-
-listings.at-2030-expected.lst:108.6-108.7:
- 105   P MAIN                         11     not referenced
- 106   P EX                           18       14                             x1
- 107   
- 108 > GnuCOBOL V.R.P          prog-2.cob                                      Page 0005
-----         ^
- 109   
- 110   Error/Warning summary:
->> Error: Unexpected indicator: `B'
+----          ^
+  77   000017
+  78   000018         EX. STOP RUN.
+>> Error: Invalid syntax
 
-listings.at-2030-expected.lst:110.6-110.7:
- 107   
- 108   GnuCOBOL V.R.P          prog-2.cob                                      Page 0005
- 109   
- 110 > Error/Warning summary:
-----         ^
- 111   
- 112   prog-2.cob:16: warning: unreachable statement 'ACCEPT'
->> Error: Unexpected indicator: `W'
+listings.at-2030-expected.lst:76.20:
+  73   000014             GO TO EX
+  74   000015
+  75   000016             ACCEPT stuff.
+  76 > warning: unreachable statement 'ACCEPT'
+----                       ^
+  77   000017
+  78   000018         EX. STOP RUN.
+>> Hint: Missing .
 
-listings.at-2030-expected.lst:112.6-112.7:
- 109   
- 110   Error/Warning summary:
- 111   
- 112 > prog-2.cob:16: warning: unreachable statement 'ACCEPT'
-----         ^
- 113   
- 114   2 warnings in compilation group
->> Error: Unexpected indicator: `.'
+listings.at-2030-expected.lst:76.21-76.30:
+  73   000014             GO TO EX
+  74   000015
+  75   000016             ACCEPT stuff.
+  76 > warning: unreachable statement 'ACCEPT'
+----                        ^^^^^^^^^
+  77   000017
+  78   000018         EX. STOP RUN.
+>> Warning: Invalid syntax
 
-listings.at-2030-expected.lst:114.6-114.7:
- 111   
- 112   prog-2.cob:16: warning: unreachable statement 'ACCEPT'
- 113   
- 114 > 2 warnings in compilation group
-----         ^
- 115   0 errors in compilation group
->> Error: Unexpected indicator: `i'
+listings.at-2030-expected.lst:76.30:
+  73   000014             GO TO EX
+  74   000015
+  75   000016             ACCEPT stuff.
+  76 > warning: unreachable statement 'ACCEPT'
+----                                 ^
+  77   000017
+  78   000018         EX. STOP RUN.
+>> Hint: Missing .
 
-listings.at-2030-expected.lst:115.6-115.7:
- 112   prog-2.cob:16: warning: unreachable statement 'ACCEPT'
- 113   
- 114   2 warnings in compilation group
- 115 > 0 errors in compilation group
+listings.at-2030-expected.lst:76.31-76.39:
+  73   000014             GO TO EX
+  74   000015
+  75   000016             ACCEPT stuff.
+  76 > warning: unreachable statement 'ACCEPT'
+----                                  ^^^^^^^^
+  77   000017
+  78   000018         EX. STOP RUN.
+>> Warning: Invalid syntax
+
+listings.at-2030-expected.lst:80.6-80.7:
+  77   000017
+  78   000018         EX. STOP RUN.
+  79   000019
+  80 > GnuCOBOL V.R.P          prog-2.cob                                      Page 0002
 ----         ^
->> Error: Unexpected indicator: `r'
+  81   
+  82   SIZE  TYPE           LVL  NAME                           PICTURE
+>> Error: Unexpected indicator: `B'
 
 listings.at-2030-expected.lst:80.9:
   77   000017
@@ -2597,6 +2470,16 @@ listings.at-2030-expected.lst:80.25-80.35:
   82   SIZE  TYPE           LVL  NAME                           PICTURE
 >> Warning: Invalid syntax
 
+listings.at-2030-expected.lst:82.6-82.7:
+  79   000019
+  80   GnuCOBOL V.R.P          prog-2.cob                                      Page 0002
+  81   
+  82 > SIZE  TYPE           LVL  NAME                           PICTURE
+----         ^
+  83   
+  84         WORKING-STORAGE SECTION
+>> Error: Unexpected indicator: `T'
+
 listings.at-2030-expected.lst:80.35:
   77   000017
   78   000018         EX. STOP RUN.
@@ -2657,6 +2540,16 @@ listings.at-2030-expected.lst:82.26-82.30:
   84         WORKING-STORAGE SECTION
 >> Warning: Invalid syntax
 
+listings.at-2030-expected.lst:84.6-84.7:
+  81   
+  82   SIZE  TYPE           LVL  NAME                           PICTURE
+  83   
+  84 >       WORKING-STORAGE SECTION
+----         ^
+  85   
+  86   00001 NUMERIC        01   data-b                         9
+>> Error: Unexpected indicator: `W'
+
 listings.at-2030-expected.lst:82.57-82.64:
   79   000019
   80   GnuCOBOL V.R.P          prog-2.cob                                      Page 0002
@@ -2667,6 +2560,16 @@ listings.at-2030-expected.lst:82.57-82.64:
   84         WORKING-STORAGE SECTION
 >> Error: Invalid syntax
 
+listings.at-2030-expected.lst:86.6-86.7:
+  83   
+  84         WORKING-STORAGE SECTION
+  85   
+  86 > 00001 NUMERIC        01   data-b                         9
+----         ^
+  87   
+  88         LINKAGE SECTION
+>> Error: Unexpected indicator: `N'
+
 listings.at-2030-expected.lst:84.29:
   81   
   82   SIZE  TYPE           LVL  NAME                           PICTURE
@@ -2747,6 +2650,16 @@ listings.at-2030-expected.lst:86.57-86.58:
   88         LINKAGE SECTION
 >> Warning: Invalid syntax
 
+listings.at-2030-expected.lst:88.6-88.7:
+  85   
+  86   00001 NUMERIC        01   data-b                         9
+  87   
+  88 >       LINKAGE SECTION
+----         ^
+  89   
+  90   00001 ALPHANUMERIC   01   stuff                          X
+>> Error: Unexpected indicator: `L'
+
 listings.at-2030-expected.lst:86.58:
   83   
   84         WORKING-STORAGE SECTION
@@ -2767,6 +2680,16 @@ listings.at-2030-expected.lst:88.7-88.13:
   90   00001 ALPHANUMERIC   01   stuff                          X
 >> Warning: Invalid syntax
 
+listings.at-2030-expected.lst:90.6-90.7:
+  87   
+  88         LINKAGE SECTION
+  89   
+  90 > 00001 ALPHANUMERIC   01   stuff                          X
+----         ^
+  91   
+  92   GnuCOBOL V.R.P          prog-2.cob                                      Page 0003
+>> Error: Unexpected indicator: `A'
+
 listings.at-2030-expected.lst:88.21:
   85   
   86   00001 NUMERIC        01   data-b                         9
@@ -2847,6 +2770,16 @@ listings.at-2030-expected.lst:90.57-90.58:
   92   GnuCOBOL V.R.P          prog-2.cob                                      Page 0003
 >> Warning: Invalid syntax
 
+listings.at-2030-expected.lst:92.6-92.7:
+  89   
+  90   00001 ALPHANUMERIC   01   stuff                          X
+  91   
+  92 > GnuCOBOL V.R.P          prog-2.cob                                      Page 0003
+----         ^
+  93   
+  94   NAME                           DEFINED                REFERENCES
+>> Error: Unexpected indicator: `B'
+
 listings.at-2030-expected.lst:90.58:
   87   
   88         LINKAGE SECTION
@@ -3107,6 +3040,16 @@ listings.at-2030-expected.lst:98.71-98.72:
  100   GnuCOBOL V.R.P          prog-2.cob                                      Page 0004
 >> Warning: Invalid syntax
 
+listings.at-2030-expected.lst:100.6-100.7:
+  97   
+  98   stuff                          9       *10      12     *16             x3
+  99   
+ 100 > GnuCOBOL V.R.P          prog-2.cob                                      Page 0004
+----         ^
+ 101   
+ 102   LABEL                          DEFINED                REFERENCES
+>> Error: Unexpected indicator: `B'
+
 listings.at-2030-expected.lst:98.72:
   95   
   96   data-b                         7       *12      13                     x2
@@ -3187,6 +3130,16 @@ listings.at-2030-expected.lst:102.31-102.38:
  104   E prog__2                      11
 >> Warning: Invalid syntax
 
+listings.at-2030-expected.lst:104.6-104.7:
+ 101   
+ 102   LABEL                          DEFINED                REFERENCES
+ 103   
+ 104 > E prog__2                      11
+----         ^
+ 105   P MAIN                         11     not referenced
+ 106   P EX                           18       14                             x1
+>> Error: Unexpected indicator: `_'
+
 listings.at-2030-expected.lst:102.38:
   99   
  100   GnuCOBOL V.R.P          prog-2.cob                                      Page 0004
@@ -3327,6 +3280,16 @@ listings.at-2030-expected.lst:106.71-106.72:
  108   GnuCOBOL V.R.P          prog-2.cob                                      Page 0005
 >> Warning: Invalid syntax
 
+listings.at-2030-expected.lst:108.6-108.7:
+ 105   P MAIN                         11     not referenced
+ 106   P EX                           18       14                             x1
+ 107   
+ 108 > GnuCOBOL V.R.P          prog-2.cob                                      Page 0005
+----         ^
+ 109   
+ 110   Error/Warning summary:
+>> Error: Unexpected indicator: `B'
+
 listings.at-2030-expected.lst:106.72:
  103   
  104   E prog__2                      11
@@ -3387,6 +3350,16 @@ listings.at-2030-expected.lst:108.25-108.35:
  110   Error/Warning summary:
 >> Warning: Invalid syntax
 
+listings.at-2030-expected.lst:110.6-110.7:
+ 107   
+ 108   GnuCOBOL V.R.P          prog-2.cob                                      Page 0005
+ 109   
+ 110 > Error/Warning summary:
+----         ^
+ 111   
+ 112   prog-2.cob:16: warning: unreachable statement 'ACCEPT'
+>> Error: Unexpected indicator: `W'
+
 listings.at-2030-expected.lst:108.35:
  105   P MAIN                         11     not referenced
  106   P EX                           18       14                             x1
@@ -3427,6 +3400,16 @@ listings.at-2030-expected.lst:110.14-110.22:
  112   prog-2.cob:16: warning: unreachable statement 'ACCEPT'
 >> Warning: Invalid syntax
 
+listings.at-2030-expected.lst:112.6-112.7:
+ 109   
+ 110   Error/Warning summary:
+ 111   
+ 112 > prog-2.cob:16: warning: unreachable statement 'ACCEPT'
+----         ^
+ 113   
+ 114   2 warnings in compilation group
+>> Error: Unexpected indicator: `.'
+
 listings.at-2030-expected.lst:110.22:
  107   
  108   GnuCOBOL V.R.P          prog-2.cob                                      Page 0005
@@ -3527,6 +3510,15 @@ listings.at-2030-expected.lst:112.36-112.45:
  114   2 warnings in compilation group
 >> Warning: Invalid syntax
 
+listings.at-2030-expected.lst:114.6-114.7:
+ 111   
+ 112   prog-2.cob:16: warning: unreachable statement 'ACCEPT'
+ 113   
+ 114 > 2 warnings in compilation group
+----         ^
+ 115   0 errors in compilation group
+>> Error: Unexpected indicator: `i'
+
 listings.at-2030-expected.lst:112.45:
  109   
  110   Error/Warning summary:
@@ -3565,6 +3557,14 @@ listings.at-2030-expected.lst:114.11-114.13:
  115   0 errors in compilation group
 >> Warning: Invalid syntax
 
+listings.at-2030-expected.lst:115.6-115.7:
+ 112   prog-2.cob:16: warning: unreachable statement 'ACCEPT'
+ 113   
+ 114   2 warnings in compilation group
+ 115 > 0 errors in compilation group
+----         ^
+>> Error: Unexpected indicator: `r'
+
 listings.at-2030-expected.lst:114.25:
  111   
  112   prog-2.cob:16: warning: unreachable statement 'ACCEPT'
@@ -4001,65 +4001,15 @@ listings.at-2848-prog.cob:7.7-7.28:
    9              END-DISPLAY
 >> Error: Malformed or unknown compiler directive
 
-listings.at-2848-prog.cob:9.22:
-   6          PROCEDURE        DIVISION.
-   7          >>IF ACTIVATE DEFINED
-   8              DISPLAY "NOTOK" NO ADVANCING
-   9 >            END-DISPLAY
-----                         ^
-  10          >>ELIF ACTIVATE2 DEFINED
-  11              DISPLAY "OK" NO ADVANCING
->> Hint: Missing .
-
-listings.at-2848-prog.cob:10.7-10.13:
-   7          >>IF ACTIVATE DEFINED
-   8              DISPLAY "NOTOK" NO ADVANCING
-   9              END-DISPLAY
-  10 >        >>ELIF ACTIVATE2 DEFINED
-----          ^^^^^^
-  11              DISPLAY "OK" NO ADVANCING
-  12              END-DISPLAY
->> Warning: Invalid syntax
-
-listings.at-2848-prog.cob:10.23:
-   7          >>IF ACTIVATE DEFINED
-   8              DISPLAY "NOTOK" NO ADVANCING
-   9              END-DISPLAY
-  10 >        >>ELIF ACTIVATE2 DEFINED
-----                          ^
-  11              DISPLAY "OK" NO ADVANCING
-  12              END-DISPLAY
->> Hint: Missing .
-
-listings.at-2848-prog.cob:10.24-10.31:
-   7          >>IF ACTIVATE DEFINED
-   8              DISPLAY "NOTOK" NO ADVANCING
-   9              END-DISPLAY
-  10 >        >>ELIF ACTIVATE2 DEFINED
-----                           ^^^^^^^
-  11              DISPLAY "OK" NO ADVANCING
-  12              END-DISPLAY
->> Warning: Invalid syntax
-
-listings.at-2848-prog.cob:10.31:
+listings.at-2848-prog.cob:10.7-10.31:
    7          >>IF ACTIVATE DEFINED
    8              DISPLAY "NOTOK" NO ADVANCING
    9              END-DISPLAY
   10 >        >>ELIF ACTIVATE2 DEFINED
-----                                  ^
+----          ^^^^^^^^^^^^^^^^^^^^^^^^
   11              DISPLAY "OK" NO ADVANCING
   12              END-DISPLAY
->> Hint: Missing .
-
-listings.at-2848-prog.cob:11.11-11.18:
-   8              DISPLAY "NOTOK" NO ADVANCING
-   9              END-DISPLAY
-  10          >>ELIF ACTIVATE2 DEFINED
-  11 >            DISPLAY "OK" NO ADVANCING
-----              ^^^^^^^
-  12              END-DISPLAY
-  13          >>ELSE
->> Warning: Invalid syntax
+>> Error: Malformed or unknown compiler directive
 
 listings.at-2848-prog.cob:13.7-13.13:
   10          >>ELIF ACTIVATE2 DEFINED
@@ -4069,7 +4019,7 @@ listings.at-2848-prog.cob:13.7-13.13:
 ----          ^^^^^^
   14              DISPLAY "NOTOK" NO ADVANCING
   15              END-DISPLAY
->> Error: Invalid syntax
+>> Error: Malformed or unknown compiler directive
 
 listings.at-2848-prog.cob:16.7-16.15:
   13          >>ELSE
@@ -4078,7 +4028,7 @@ listings.at-2848-prog.cob:16.7-16.15:
   16 >        >>END-IF
 ----          ^^^^^^^^
   17              STOP RUN.
->> Error: Invalid syntax
+>> Error: Malformed or unknown compiler directive
 
 Considering: import/gnucobol/tests/testsuite.src/listings.at:2876:0
 listings.at-2876-prog2.cob:7.7-7.26:
diff --git a/test/output-tests/run_accept.expected b/test/output-tests/run_accept.expected
index d07533f3d..2854fa9bf 100644
--- a/test/output-tests/run_accept.expected
+++ b/test/output-tests/run_accept.expected
@@ -36,7 +36,7 @@ run_accept.at-260-prog.cob:46.7-46.16:
 ----          ^^^^^^^^^
   47              GOBACK.
   48   
->> Error: Invalid syntax
+>> Error: Malformed or unknown compiler directive
 
 run_accept.at-260-prog.cob:63.36:
   60              MOVE WS-NOW-MM    TO WS-TIME-MM
diff --git a/test/output-tests/run_extensions.expected b/test/output-tests/run_extensions.expected
index 7926b389c..743b5b55a 100644
--- a/test/output-tests/run_extensions.expected
+++ b/test/output-tests/run_extensions.expected
@@ -1696,56 +1696,6 @@ run_extensions.at-2060-caller.cob:14.6-14.7:
   16         >> ELSE
 >> Error: Unexpected indicator: `>'
 
-run_extensions.at-2060-caller.cob:16.6-16.7:
-  13   
-  14         >> IF P64 DEFINED
-  15              MOVE "callee64" TO CALL-NAME
-  16 >       >> ELSE
-----         ^
-  17              MOVE "callee32" TO CALL-NAME
-  18         >> END-IF
->> Error: Unexpected indicator: `>'
-
-run_extensions.at-2060-caller.cob:18.6-18.7:
-  15              MOVE "callee64" TO CALL-NAME
-  16         >> ELSE
-  17              MOVE "callee32" TO CALL-NAME
-  18 >       >> END-IF
-----         ^
-  19   
-  20              MOVE 12345678 TO ADR-BUFFER
->> Error: Unexpected indicator: `>'
-
-run_extensions.at-2060-caller.cob:28.6-28.7:
-  25              CALL CALL-NAME USING BY VALUE LENGTH OF SOME-FILL
-  26   
-  27              MOVE -42 TO ADR-BUFFER
-  28 >       >> IF P64 DEFINED
-----         ^
-  29              CALL "callee32" USING BY VALUE SIZE 4 ADR-BUFFER
-  30              CALL "callee64" USING BY VALUE BIG-BUFF
->> Error: Unexpected indicator: `>'
-
-run_extensions.at-2060-caller.cob:31.6-31.7:
-  28         >> IF P64 DEFINED
-  29              CALL "callee32" USING BY VALUE SIZE 4 ADR-BUFFER
-  30              CALL "callee64" USING BY VALUE BIG-BUFF
-  31 >       >> ELSE
-----         ^
-  32              CALL "callee32" USING BY VALUE ADR-BUFFER
-  33              CALL "callee64" USING BY VALUE SIZE 8 BIG-BUFF
->> Error: Unexpected indicator: `>'
-
-run_extensions.at-2060-caller.cob:34.6-34.7:
-  31         >> ELSE
-  32              CALL "callee32" USING BY VALUE ADR-BUFFER
-  33              CALL "callee64" USING BY VALUE SIZE 8 BIG-BUFF
-  34 >       >> END-IF
-----         ^
-  35   
-  36              GOBACK.
->> Error: Unexpected indicator: `>'
-
 run_extensions.at-2060-caller.cob:14.7-14.8:
   11          77 BIG-BUFF      USAGE COMP-5 PIC S9(18) VALUE 99999999999999.
   12          PROCEDURE        DIVISION  CHAINING CALL-NAME.
@@ -1756,6 +1706,16 @@ run_extensions.at-2060-caller.cob:14.7-14.8:
   16         >> ELSE
 >> Error: Invalid syntax
 
+run_extensions.at-2060-caller.cob:16.6-16.7:
+  13   
+  14         >> IF P64 DEFINED
+  15              MOVE "callee64" TO CALL-NAME
+  16 >       >> ELSE
+----         ^
+  17              MOVE "callee32" TO CALL-NAME
+  18         >> END-IF
+>> Error: Unexpected indicator: `>'
+
 run_extensions.at-2060-caller.cob:16.7-16.8:
   13   
   14         >> IF P64 DEFINED
@@ -1766,6 +1726,16 @@ run_extensions.at-2060-caller.cob:16.7-16.8:
   18         >> END-IF
 >> Error: Invalid syntax
 
+run_extensions.at-2060-caller.cob:18.6-18.7:
+  15              MOVE "callee64" TO CALL-NAME
+  16         >> ELSE
+  17              MOVE "callee32" TO CALL-NAME
+  18 >       >> END-IF
+----         ^
+  19   
+  20              MOVE 12345678 TO ADR-BUFFER
+>> Error: Unexpected indicator: `>'
+
 run_extensions.at-2060-caller.cob:18.7-18.8:
   15              MOVE "callee64" TO CALL-NAME
   16         >> ELSE
@@ -1786,6 +1756,16 @@ run_extensions.at-2060-caller.cob:25.41-25.47:
   27              MOVE -42 TO ADR-BUFFER
 >> Error: Invalid syntax
 
+run_extensions.at-2060-caller.cob:28.6-28.7:
+  25              CALL CALL-NAME USING BY VALUE LENGTH OF SOME-FILL
+  26   
+  27              MOVE -42 TO ADR-BUFFER
+  28 >       >> IF P64 DEFINED
+----         ^
+  29              CALL "callee32" USING BY VALUE SIZE 4 ADR-BUFFER
+  30              CALL "callee64" USING BY VALUE BIG-BUFF
+>> Error: Unexpected indicator: `>'
+
 run_extensions.at-2060-caller.cob:28.7-28.8:
   25              CALL CALL-NAME USING BY VALUE LENGTH OF SOME-FILL
   26   
@@ -1806,6 +1786,16 @@ run_extensions.at-2060-caller.cob:29.42-29.46:
   31         >> ELSE
 >> Error: Invalid syntax
 
+run_extensions.at-2060-caller.cob:31.6-31.7:
+  28         >> IF P64 DEFINED
+  29              CALL "callee32" USING BY VALUE SIZE 4 ADR-BUFFER
+  30              CALL "callee64" USING BY VALUE BIG-BUFF
+  31 >       >> ELSE
+----         ^
+  32              CALL "callee32" USING BY VALUE ADR-BUFFER
+  33              CALL "callee64" USING BY VALUE SIZE 8 BIG-BUFF
+>> Error: Unexpected indicator: `>'
+
 run_extensions.at-2060-caller.cob:31.7-31.8:
   28         >> IF P64 DEFINED
   29              CALL "callee32" USING BY VALUE SIZE 4 ADR-BUFFER
@@ -1826,6 +1816,16 @@ run_extensions.at-2060-caller.cob:33.42-33.46:
   35   
 >> Error: Invalid syntax
 
+run_extensions.at-2060-caller.cob:34.6-34.7:
+  31         >> ELSE
+  32              CALL "callee32" USING BY VALUE ADR-BUFFER
+  33              CALL "callee64" USING BY VALUE SIZE 8 BIG-BUFF
+  34 >       >> END-IF
+----         ^
+  35   
+  36              GOBACK.
+>> Error: Unexpected indicator: `>'
+
 run_extensions.at-2060-caller.cob:34.7-34.8:
   31         >> ELSE
   32              CALL "callee32" USING BY VALUE ADR-BUFFER
@@ -3349,7 +3349,7 @@ run_extensions.at-4921-prog.cob:10.7-10.13:
 ----          ^^^^^^
   11              DISPLAY "NOTOK" NO ADVANCING
   12              END-DISPLAY
->> Error: Invalid syntax
+>> Error: Malformed or unknown compiler directive
 
 run_extensions.at-4921-prog.cob:13.7-13.15:
   10          >>ELSE
@@ -3358,7 +3358,7 @@ run_extensions.at-4921-prog.cob:13.7-13.15:
   13 >        >>END-IF
 ----          ^^^^^^^^
   14              STOP RUN.
->> Error: Invalid syntax
+>> Error: Malformed or unknown compiler directive
 
 Considering: import/gnucobol/tests/testsuite.src/run_extensions.at:4946:0
 run_extensions.at-4946-prog.cob:7.7-7.28:
@@ -3379,7 +3379,7 @@ run_extensions.at-4946-prog.cob:10.7-10.13:
 ----          ^^^^^^
   11              DISPLAY "NOTOK" NO ADVANCING
   12              END-DISPLAY
->> Error: Invalid syntax
+>> Error: Malformed or unknown compiler directive
 
 run_extensions.at-4946-prog.cob:13.7-13.15:
   10          >>ELSE
@@ -3388,7 +3388,7 @@ run_extensions.at-4946-prog.cob:13.7-13.15:
   13 >        >>END-IF
 ----          ^^^^^^^^
   14              STOP RUN.
->> Error: Invalid syntax
+>> Error: Malformed or unknown compiler directive
 
 Considering: import/gnucobol/tests/testsuite.src/run_extensions.at:4974:0
 run_extensions.at-4974-prog.cob:7.7-7.28:
@@ -3401,65 +3401,15 @@ run_extensions.at-4974-prog.cob:7.7-7.28:
    9              END-DISPLAY
 >> Error: Malformed or unknown compiler directive
 
-run_extensions.at-4974-prog.cob:9.22:
-   6          PROCEDURE        DIVISION.
-   7          >>IF ACTIVATE DEFINED
-   8              DISPLAY "NOTOK" NO ADVANCING
-   9 >            END-DISPLAY
-----                         ^
-  10          >>ELIF ACTIVATE2 DEFINED
-  11              DISPLAY "OK" NO ADVANCING
->> Hint: Missing .
-
-run_extensions.at-4974-prog.cob:10.7-10.13:
-   7          >>IF ACTIVATE DEFINED
-   8              DISPLAY "NOTOK" NO ADVANCING
-   9              END-DISPLAY
-  10 >        >>ELIF ACTIVATE2 DEFINED
-----          ^^^^^^
-  11              DISPLAY "OK" NO ADVANCING
-  12              END-DISPLAY
->> Warning: Invalid syntax
-
-run_extensions.at-4974-prog.cob:10.23:
-   7          >>IF ACTIVATE DEFINED
-   8              DISPLAY "NOTOK" NO ADVANCING
-   9              END-DISPLAY
-  10 >        >>ELIF ACTIVATE2 DEFINED
-----                          ^
-  11              DISPLAY "OK" NO ADVANCING
-  12              END-DISPLAY
->> Hint: Missing .
-
-run_extensions.at-4974-prog.cob:10.24-10.31:
-   7          >>IF ACTIVATE DEFINED
-   8              DISPLAY "NOTOK" NO ADVANCING
-   9              END-DISPLAY
-  10 >        >>ELIF ACTIVATE2 DEFINED
-----                           ^^^^^^^
-  11              DISPLAY "OK" NO ADVANCING
-  12              END-DISPLAY
->> Warning: Invalid syntax
-
-run_extensions.at-4974-prog.cob:10.31:
+run_extensions.at-4974-prog.cob:10.7-10.31:
    7          >>IF ACTIVATE DEFINED
    8              DISPLAY "NOTOK" NO ADVANCING
    9              END-DISPLAY
   10 >        >>ELIF ACTIVATE2 DEFINED
-----                                  ^
+----          ^^^^^^^^^^^^^^^^^^^^^^^^
   11              DISPLAY "OK" NO ADVANCING
   12              END-DISPLAY
->> Hint: Missing .
-
-run_extensions.at-4974-prog.cob:11.11-11.18:
-   8              DISPLAY "NOTOK" NO ADVANCING
-   9              END-DISPLAY
-  10          >>ELIF ACTIVATE2 DEFINED
-  11 >            DISPLAY "OK" NO ADVANCING
-----              ^^^^^^^
-  12              END-DISPLAY
-  13          >>ELSE
->> Warning: Invalid syntax
+>> Error: Malformed or unknown compiler directive
 
 run_extensions.at-4974-prog.cob:13.7-13.13:
   10          >>ELIF ACTIVATE2 DEFINED
@@ -3469,7 +3419,7 @@ run_extensions.at-4974-prog.cob:13.7-13.13:
 ----          ^^^^^^
   14              DISPLAY "NOTOK" NO ADVANCING
   15              END-DISPLAY
->> Error: Invalid syntax
+>> Error: Malformed or unknown compiler directive
 
 run_extensions.at-4974-prog.cob:16.7-16.15:
   13          >>ELSE
@@ -3478,7 +3428,7 @@ run_extensions.at-4974-prog.cob:16.7-16.15:
   16 >        >>END-IF
 ----          ^^^^^^^^
   17              STOP RUN.
->> Error: Invalid syntax
+>> Error: Malformed or unknown compiler directive
 
 Considering: import/gnucobol/tests/testsuite.src/run_extensions.at:5000:0
 run_extensions.at-5000-prog.cob:7.7-7.28:
@@ -3491,45 +3441,15 @@ run_extensions.at-5000-prog.cob:7.7-7.28:
    9              END-DISPLAY
 >> Error: Malformed or unknown compiler directive
 
-run_extensions.at-5000-prog.cob:9.22:
-   6          PROCEDURE        DIVISION.
-   7          >>IF ACTIVATE DEFINED
-   8              DISPLAY "NOTOK" NO ADVANCING
-   9 >            END-DISPLAY
-----                         ^
-  10          >>ELIF ACTIVATE2 DEFINED
-  11          >>ELSE
->> Hint: Missing .
-
-run_extensions.at-5000-prog.cob:10.7-10.13:
-   7          >>IF ACTIVATE DEFINED
-   8              DISPLAY "NOTOK" NO ADVANCING
-   9              END-DISPLAY
-  10 >        >>ELIF ACTIVATE2 DEFINED
-----          ^^^^^^
-  11          >>ELSE
-  12              DISPLAY "NOTOK" NO ADVANCING
->> Warning: Invalid syntax
-
-run_extensions.at-5000-prog.cob:10.23:
+run_extensions.at-5000-prog.cob:10.7-10.31:
    7          >>IF ACTIVATE DEFINED
    8              DISPLAY "NOTOK" NO ADVANCING
    9              END-DISPLAY
   10 >        >>ELIF ACTIVATE2 DEFINED
-----                          ^
+----          ^^^^^^^^^^^^^^^^^^^^^^^^
   11          >>ELSE
   12              DISPLAY "NOTOK" NO ADVANCING
->> Hint: Missing .
-
-run_extensions.at-5000-prog.cob:10.24-10.31:
-   7          >>IF ACTIVATE DEFINED
-   8              DISPLAY "NOTOK" NO ADVANCING
-   9              END-DISPLAY
-  10 >        >>ELIF ACTIVATE2 DEFINED
-----                           ^^^^^^^
-  11          >>ELSE
-  12              DISPLAY "NOTOK" NO ADVANCING
->> Warning: Invalid syntax
+>> Error: Malformed or unknown compiler directive
 
 run_extensions.at-5000-prog.cob:11.7-11.13:
    8              DISPLAY "NOTOK" NO ADVANCING
@@ -3541,26 +3461,6 @@ run_extensions.at-5000-prog.cob:11.7-11.13:
   13              END-DISPLAY
 >> Error: Malformed or unknown compiler directive
 
-run_extensions.at-5000-prog.cob:10.31:
-   7          >>IF ACTIVATE DEFINED
-   8              DISPLAY "NOTOK" NO ADVANCING
-   9              END-DISPLAY
-  10 >        >>ELIF ACTIVATE2 DEFINED
-----                                  ^
-  11          >>ELSE
-  12              DISPLAY "NOTOK" NO ADVANCING
->> Hint: Missing .
-
-run_extensions.at-5000-prog.cob:12.11-12.18:
-   9              END-DISPLAY
-  10          >>ELIF ACTIVATE2 DEFINED
-  11          >>ELSE
-  12 >            DISPLAY "NOTOK" NO ADVANCING
-----              ^^^^^^^
-  13              END-DISPLAY
-  14          >>END-IF
->> Warning: Invalid syntax
-
 run_extensions.at-5000-prog.cob:14.7-14.15:
   11          >>ELSE
   12              DISPLAY "NOTOK" NO ADVANCING
@@ -3568,7 +3468,7 @@ run_extensions.at-5000-prog.cob:14.7-14.15:
   14 >        >>END-IF
 ----          ^^^^^^^^
   15              STOP RUN.
->> Error: Invalid syntax
+>> Error: Malformed or unknown compiler directive
 
 Considering: import/gnucobol/tests/testsuite.src/run_extensions.at:5065:0
 Considering: import/gnucobol/tests/testsuite.src/run_extensions.at:5049:0
@@ -4115,6 +4015,26 @@ run_extensions.at-5351-prog.cob:2.7-2.36:
    4          >>ELSE
 >> Error: Malformed or unknown compiler directive
 
+run_extensions.at-5351-prog.cob:4.7-4.13:
+   1   
+   2          >>IF BINARY-COMP-1 IS DEFINED
+   3              $SET COMP-1(BINARY)
+   4 >        >>ELSE
+----          ^^^^^^
+   5              $SET COMP1 "float"
+   6          >>END-IF
+>> Error: Malformed or unknown compiler directive
+
+run_extensions.at-5351-prog.cob:6.7-6.15:
+   3              $SET COMP-1(BINARY)
+   4          >>ELSE
+   5              $SET COMP1 "float"
+   6 >        >>END-IF
+----          ^^^^^^^^
+   7          IDENTIFICATION  DIVISION.
+   8          PROGRAM-ID.     prog.
+>> Error: Malformed or unknown compiler directive
+
 run_extensions.at-5351-prog.cob:3.11-3.15:
    1   
    2          >>IF BINARY-COMP-1 IS DEFINED
diff --git a/test/output-tests/run_file.expected b/test/output-tests/run_file.expected
index e9f33b3ff..e25b647c1 100644
--- a/test/output-tests/run_file.expected
+++ b/test/output-tests/run_file.expected
@@ -7624,85 +7624,25 @@ run_file.at-12281-reference:1.8-1.14:
 >> Error: Invalid syntax
 
 Considering: import/gnucobol/tests/testsuite.src/run_file.at:12369:0
-run_file.at-12369-prog.cob:31.36:
-  28              WRITE f-rec FROM "a"
-  29              CLOSE f
-  30   
-  31 >            SET LAST EXCEPTION TO OFF
-----                                       ^
-  32              >>TURN EC-I-O CHECKING ON
-  33              *> Read f too many times without libcob error
->> Hint: Missing .
-
-run_file.at-12369-prog.cob:32.11-32.17:
-  29              CLOSE f
-  30   
-  31              SET LAST EXCEPTION TO OFF
-  32 >            >>TURN EC-I-O CHECKING ON
-----              ^^^^^^
-  33              *> Read f too many times without libcob error
-  34              OPEN INPUT f
->> Warning: Invalid syntax
-
-run_file.at-12369-prog.cob:32.24:
-  29              CLOSE f
-  30   
-  31              SET LAST EXCEPTION TO OFF
-  32 >            >>TURN EC-I-O CHECKING ON
-----                           ^
-  33              *> Read f too many times without libcob error
-  34              OPEN INPUT f
->> Hint: Missing .
-
-run_file.at-12369-prog.cob:32.25-32.33:
-  29              CLOSE f
-  30   
-  31              SET LAST EXCEPTION TO OFF
-  32 >            >>TURN EC-I-O CHECKING ON
-----                            ^^^^^^^^
-  33              *> Read f too many times without libcob error
-  34              OPEN INPUT f
->> Warning: Invalid syntax
-
-run_file.at-12369-prog.cob:32.33:
-  29              CLOSE f
-  30   
-  31              SET LAST EXCEPTION TO OFF
-  32 >            >>TURN EC-I-O CHECKING ON
-----                                    ^
-  33              *> Read f too many times without libcob error
-  34              OPEN INPUT f
->> Hint: Missing .
-
-run_file.at-12369-prog.cob:32.34-32.36:
+run_file.at-12369-prog.cob:32.11-32.36:
   29              CLOSE f
   30   
   31              SET LAST EXCEPTION TO OFF
   32 >            >>TURN EC-I-O CHECKING ON
-----                                     ^^
+----              ^^^^^^^^^^^^^^^^^^^^^^^^^
   33              *> Read f too many times without libcob error
   34              OPEN INPUT f
->> Warning: Invalid syntax
+>> Error: Malformed or unknown compiler directive
 
-run_file.at-12369-prog.cob:46.11-46.17:
+run_file.at-12369-prog.cob:46.11-46.38:
   43   
   44              CLOSE f
   45   
   46 >            >>TURN EC-I-O g CHECKING ON
-----              ^^^^^^
-  47   
-  48              *> Read f too many times without libcob error
->> Error: Invalid syntax
-
-run_file.at-12369-prog.cob:46.36-46.38:
-  43   
-  44              CLOSE f
-  45   
-  46 >            >>TURN EC-I-O g CHECKING ON
-----                                       ^^
+----              ^^^^^^^^^^^^^^^^^^^^^^^^^^^
   47   
   48              *> Read f too many times without libcob error
->> Error: Invalid syntax
+>> Error: Malformed or unknown compiler directive
 
 Considering: import/gnucobol/tests/testsuite.src/run_file.at:12582:0
 run_file.at-12582-prog.cob:10.34-10.42:
@@ -8066,6 +8006,14 @@ run_file.at-13896-expected.txt:2.7-2.11:
    4   READ FILE1
 >> Warning: Unexpected non-blank area A on continuation line
 
+run_file.at-13896-expected.txt:2.11-2.13:
+   1   ERROR ON FILE2
+   2 >   STAT-FILE1: 00
+----              ^^
+   3     STAT-FILE2: 35
+   4   READ FILE1
+>> Error: Unexpected `1:' in continuation
+
 run_file.at-13896-expected.txt:3.7-3.11:
    1   ERROR ON FILE2
    2     STAT-FILE1: 00
@@ -8075,6 +8023,15 @@ run_file.at-13896-expected.txt:3.7-3.11:
    5   ERROR ON FILE1
 >> Warning: Unexpected non-blank area A on continuation line
 
+run_file.at-13896-expected.txt:3.11-3.13:
+   1   ERROR ON FILE2
+   2     STAT-FILE1: 00
+   3 >   STAT-FILE2: 35
+----              ^^
+   4   READ FILE1
+   5   ERROR ON FILE1
+>> Error: Unexpected `2:' in continuation
+
 run_file.at-13896-expected.txt:4.6-4.7:
    1   ERROR ON FILE2
    2     STAT-FILE1: 00
@@ -8105,6 +8062,16 @@ run_file.at-13896-expected.txt:6.7-6.11:
    8   READ FILE2
 >> Warning: Unexpected non-blank area A on continuation line
 
+run_file.at-13896-expected.txt:6.11-6.13:
+   3     STAT-FILE2: 35
+   4   READ FILE1
+   5   ERROR ON FILE1
+   6 >   STAT-FILE1: 10
+----              ^^
+   7     STAT-FILE2: 35
+   8   READ FILE2
+>> Error: Unexpected `1:' in continuation
+
 run_file.at-13896-expected.txt:7.7-7.11:
    4   READ FILE1
    5   ERROR ON FILE1
@@ -8115,6 +8082,16 @@ run_file.at-13896-expected.txt:7.7-7.11:
    9   ERROR ON FILE2
 >> Warning: Unexpected non-blank area A on continuation line
 
+run_file.at-13896-expected.txt:7.11-7.13:
+   4   READ FILE1
+   5   ERROR ON FILE1
+   6     STAT-FILE1: 10
+   7 >   STAT-FILE2: 35
+----              ^^
+   8   READ FILE2
+   9   ERROR ON FILE2
+>> Error: Unexpected `2:' in continuation
+
 run_file.at-13896-expected.txt:8.6-8.7:
    5   ERROR ON FILE1
    6     STAT-FILE1: 10
@@ -8145,6 +8122,16 @@ run_file.at-13896-expected.txt:10.7-10.11:
   12   CLOSE FILES
 >> Warning: Unexpected non-blank area A on continuation line
 
+run_file.at-13896-expected.txt:10.11-10.13:
+   7     STAT-FILE2: 35
+   8   READ FILE2
+   9   ERROR ON FILE2
+  10 >   STAT-FILE1: 10
+----              ^^
+  11     STAT-FILE2: 47
+  12   CLOSE FILES
+>> Error: Unexpected `1:' in continuation
+
 run_file.at-13896-expected.txt:11.7-11.11:
    8   READ FILE2
    9   ERROR ON FILE2
@@ -8155,6 +8142,16 @@ run_file.at-13896-expected.txt:11.7-11.11:
   13   ERROR ON FILE2
 >> Warning: Unexpected non-blank area A on continuation line
 
+run_file.at-13896-expected.txt:11.11-11.13:
+   8   READ FILE2
+   9   ERROR ON FILE2
+  10     STAT-FILE1: 10
+  11 >   STAT-FILE2: 47
+----              ^^
+  12   CLOSE FILES
+  13   ERROR ON FILE2
+>> Error: Unexpected `2:' in continuation
+
 run_file.at-13896-expected.txt:12.6-12.7:
    9   ERROR ON FILE2
   10     STAT-FILE1: 10
@@ -8185,6 +8182,16 @@ run_file.at-13896-expected.txt:14.7-14.11:
   16   DELETE FILES
 >> Warning: Unexpected non-blank area A on continuation line
 
+run_file.at-13896-expected.txt:14.11-14.13:
+  11     STAT-FILE2: 47
+  12   CLOSE FILES
+  13   ERROR ON FILE2
+  14 >   STAT-FILE1: 00
+----              ^^
+  15     STAT-FILE2: 42
+  16   DELETE FILES
+>> Error: Unexpected `1:' in continuation
+
 run_file.at-13896-expected.txt:15.7-15.11:
   12   CLOSE FILES
   13   ERROR ON FILE2
@@ -8194,6 +8201,15 @@ run_file.at-13896-expected.txt:15.7-15.11:
   16   DELETE FILES
 >> Warning: Unexpected non-blank area A on continuation line
 
+run_file.at-13896-expected.txt:15.11-15.13:
+  12   CLOSE FILES
+  13   ERROR ON FILE2
+  14     STAT-FILE1: 00
+  15 >   STAT-FILE2: 42
+----              ^^
+  16   DELETE FILES
+>> Error: Unexpected `2:' in continuation
+
 run_file.at-13896-expected.txt:1.7-1.8:
    1 > ERROR ON FILE2
 ----          ^
diff --git a/test/output-tests/run_functions.expected b/test/output-tests/run_functions.expected
index b5f419aca..9cb2d6fb0 100644
--- a/test/output-tests/run_functions.expected
+++ b/test/output-tests/run_functions.expected
@@ -19,45 +19,15 @@ run_functions.at-410-prog.cob:19.7-19.31:
   21          >>ELIF CHARSET = 'EBCDIC'
 >> Error: Malformed or unknown compiler directive
 
-run_functions.at-410-prog.cob:20.61:
-  17              STRING FUNCTION BIT-OF (TXT) DELIMITED BY SIZE INTO BITX.
-  18         *> Discover if running ASCII or EBCDIC
-  19          >>IF   CHARSET = 'ASCII'
-  20 >            IF BITX NOT = "01001000010010010010111000100000--"
-----                                                                ^
-  21          >>ELIF CHARSET = 'EBCDIC'
-  22              IF BITX NOT = "11001000110010010100101101000000--"
->> Hint: Missing .
-
-run_functions.at-410-prog.cob:21.7-21.13:
-  18         *> Discover if running ASCII or EBCDIC
-  19          >>IF   CHARSET = 'ASCII'
-  20              IF BITX NOT = "01001000010010010010111000100000--"
-  21 >        >>ELIF CHARSET = 'EBCDIC'
-----          ^^^^^^
-  22              IF BITX NOT = "11001000110010010100101101000000--"
-  23          >>ELSE
->> Error: Invalid syntax
-
-run_functions.at-410-prog.cob:21.21:
+run_functions.at-410-prog.cob:21.7-21.32:
   18         *> Discover if running ASCII or EBCDIC
   19          >>IF   CHARSET = 'ASCII'
   20              IF BITX NOT = "01001000010010010010111000100000--"
   21 >        >>ELIF CHARSET = 'EBCDIC'
-----                        ^
+----          ^^^^^^^^^^^^^^^^^^^^^^^^^
   22              IF BITX NOT = "11001000110010010100101101000000--"
   23          >>ELSE
->> Hint: Missing .
-
-run_functions.at-410-prog.cob:21.22-21.23:
-  18         *> Discover if running ASCII or EBCDIC
-  19          >>IF   CHARSET = 'ASCII'
-  20              IF BITX NOT = "01001000010010010010111000100000--"
-  21 >        >>ELIF CHARSET = 'EBCDIC'
-----                         ^
-  22              IF BITX NOT = "11001000110010010100101101000000--"
-  23          >>ELSE
->> Warning: Invalid syntax
+>> Error: Malformed or unknown compiler directive
 
 run_functions.at-410-prog.cob:23.7-23.13:
   20              IF BITX NOT = "01001000010010010010111000100000--"
@@ -67,7 +37,7 @@ run_functions.at-410-prog.cob:23.7-23.13:
 ----          ^^^^^^
   24              IF 1 = 1 DISPLAY 'CHARSET UNKNOWN! PLEASE REPORT!'
   25          >>END-IF
->> Error: Invalid syntax
+>> Error: Malformed or unknown compiler directive
 
 run_functions.at-410-prog.cob:25.7-25.15:
   22              IF BITX NOT = "11001000110010010100101101000000--"
@@ -77,7 +47,7 @@ run_functions.at-410-prog.cob:25.7-25.15:
 ----          ^^^^^^^^
   26                 DISPLAY "UNEXPECTED BIT-VALUE OF 'HI. ': " BITX.
   27   
->> Error: Invalid syntax
+>> Error: Malformed or unknown compiler directive
 
 run_functions.at-410-prog.cob:30.7-30.31:
   27   
@@ -97,7 +67,7 @@ run_functions.at-410-prog.cob:32.7-32.13:
 ----          ^^^^^^
   33              IF BITX NOT = "111100001111000100000000----------"
   34          >>END-IF
->> Error: Invalid syntax
+>> Error: Malformed or unknown compiler directive
 
 run_functions.at-410-prog.cob:34.7-34.15:
   31              IF BITX NOT = "001100000011000100000000----------"
@@ -107,7 +77,7 @@ run_functions.at-410-prog.cob:34.7-34.15:
 ----          ^^^^^^^^
   35   
   36              IF FUNCTION BIT-TO-CHAR (BITX(1:24)) NOT = z"01"
->> Error: Invalid syntax
+>> Error: Malformed or unknown compiler directive
 
 run_functions.at-410-prog.cob:36.55-36.59:
   33              IF BITX NOT = "111100001111000100000000----------"
@@ -160,45 +130,15 @@ run_functions.at-541-prog.cob:36.7-36.31:
   38          >>ELIF CHARSET = 'EBCDIC'
 >> Error: Malformed or unknown compiler directive
 
-run_functions.at-541-prog.cob:37.37:
-  34              STRING FUNCTION HEX-OF (X) DELIMITED BY SIZE INTO HEXX.
-  35         *> Discover if running ASCII or EBCDIC
-  36          >>IF   CHARSET = 'ASCII'
-  37 >            IF HEXX NOT = "20303132--"
-----                                        ^
-  38          >>ELIF CHARSET = 'EBCDIC'
-  39              IF HEXX NOT = "40F0F1F2--"
->> Hint: Missing .
-
-run_functions.at-541-prog.cob:38.7-38.13:
-  35         *> Discover if running ASCII or EBCDIC
-  36          >>IF   CHARSET = 'ASCII'
-  37              IF HEXX NOT = "20303132--"
-  38 >        >>ELIF CHARSET = 'EBCDIC'
-----          ^^^^^^
-  39              IF HEXX NOT = "40F0F1F2--"
-  40          >>ELSE
->> Error: Invalid syntax
-
-run_functions.at-541-prog.cob:38.21:
+run_functions.at-541-prog.cob:38.7-38.32:
   35         *> Discover if running ASCII or EBCDIC
   36          >>IF   CHARSET = 'ASCII'
   37              IF HEXX NOT = "20303132--"
   38 >        >>ELIF CHARSET = 'EBCDIC'
-----                        ^
+----          ^^^^^^^^^^^^^^^^^^^^^^^^^
   39              IF HEXX NOT = "40F0F1F2--"
   40          >>ELSE
->> Hint: Missing .
-
-run_functions.at-541-prog.cob:38.22-38.23:
-  35         *> Discover if running ASCII or EBCDIC
-  36          >>IF   CHARSET = 'ASCII'
-  37              IF HEXX NOT = "20303132--"
-  38 >        >>ELIF CHARSET = 'EBCDIC'
-----                         ^
-  39              IF HEXX NOT = "40F0F1F2--"
-  40          >>ELSE
->> Warning: Invalid syntax
+>> Error: Malformed or unknown compiler directive
 
 run_functions.at-541-prog.cob:40.7-40.13:
   37              IF HEXX NOT = "20303132--"
@@ -208,7 +148,7 @@ run_functions.at-541-prog.cob:40.7-40.13:
 ----          ^^^^^^
   41              IF 1 = 1 DISPLAY 'CHARSET UNKNOWN! PLEASE REPORT!'
   42          >>END-IF
->> Error: Invalid syntax
+>> Error: Malformed or unknown compiler directive
 
 run_functions.at-541-prog.cob:42.7-42.15:
   39              IF HEXX NOT = "40F0F1F2--"
@@ -218,7 +158,7 @@ run_functions.at-541-prog.cob:42.7-42.15:
 ----          ^^^^^^^^
   43                 DISPLAY "UNEXPECTED HEX-VALUE OF '0012': " HEXX.
   44   
->> Error: Invalid syntax
+>> Error: Malformed or unknown compiler directive
 
 run_functions.at-541-prog.cob:47.7-47.31:
   44   
@@ -238,7 +178,7 @@ run_functions.at-541-prog.cob:49.7-49.14:
 ----          ^^^^^^^
   50              IF HEXX NOT = "C8C94B40--"
   51          >> END-IF
->> Error: Invalid syntax
+>> Error: Malformed or unknown compiler directive
 
 run_functions.at-541-prog.cob:51.7-51.16:
   48              IF HEXX NOT = "48492E20--"
@@ -248,7 +188,7 @@ run_functions.at-541-prog.cob:51.7-51.16:
 ----          ^^^^^^^^^
   52                 DISPLAY "UNEXPECTED HEX-VALUE OF 'HI! ': " HEXX.
   53   
->> Error: Invalid syntax
+>> Error: Malformed or unknown compiler directive
 
 run_functions.at-541-prog.cob:66.7-66.31:
   63   
@@ -268,7 +208,7 @@ run_functions.at-541-prog.cob:68.7-68.14:
 ----          ^^^^^^^
   69              IF HEXX NOT = "F0F100----"
   70          >> END-IF
->> Error: Invalid syntax
+>> Error: Malformed or unknown compiler directive
 
 run_functions.at-541-prog.cob:70.7-70.16:
   67              IF HEXX NOT = "303100----"
@@ -278,7 +218,7 @@ run_functions.at-541-prog.cob:70.7-70.16:
 ----          ^^^^^^^^^
   71                 DISPLAY "UNEXPECTED HEX-VALUE OF z'01': " HEXX.
   72   
->> Error: Invalid syntax
+>> Error: Malformed or unknown compiler directive
 
 run_functions.at-541-prog.cob:75.7-75.31:
   72   
@@ -298,7 +238,7 @@ run_functions.at-541-prog.cob:77.7-77.14:
 ----          ^^^^^^^
   78              IF HEXX NOT = "40--------"
   79          >> END-IF
->> Error: Invalid syntax
+>> Error: Malformed or unknown compiler directive
 
 run_functions.at-541-prog.cob:79.7-79.16:
   76              IF HEXX NOT = "20--------"
@@ -308,7 +248,7 @@ run_functions.at-541-prog.cob:79.7-79.16:
 ----          ^^^^^^^^^
   80                 DISPLAY "UNEXPECTED HEX-VALUE OF ' ': " HEXX.
   81   
->> Error: Invalid syntax
+>> Error: Malformed or unknown compiler directive
 
 run_functions.at-541-prog.cob:107.54-107.58:
  104              SET  HEXX-FILLER TO TRUE
diff --git a/test/output-tests/run_fundamental.expected b/test/output-tests/run_fundamental.expected
index a86314ed6..2ceb337c8 100644
--- a/test/output-tests/run_fundamental.expected
+++ b/test/output-tests/run_fundamental.expected
@@ -89,7 +89,7 @@ run_fundamental.at-138-prog.cob:7.7-7.13:
 ----          ^^^^^^
    8              DISPLAY X"313233"
    9          >>END-IF
->> Error: Invalid syntax
+>> Error: Malformed or unknown compiler directive
 
 run_fundamental.at-138-prog.cob:9.7-9.15:
    6              DISPLAY X"F1F2F3"
@@ -99,7 +99,7 @@ run_fundamental.at-138-prog.cob:9.7-9.15:
 ----          ^^^^^^^^
   10              END-DISPLAY.
   11              CALL "dump" USING X"000102"
->> Error: Invalid syntax
+>> Error: Malformed or unknown compiler directive
 
 Considering: import/gnucobol/tests/testsuite.src/run_fundamental.at:179:0
 Considering: import/gnucobol/tests/testsuite.src/run_fundamental.at:233:0
@@ -465,65 +465,15 @@ Considering: import/gnucobol/tests/testsuite.src/run_fundamental.at:1670:0
 Considering: import/gnucobol/tests/testsuite.src/run_fundamental.at:1723:0
 Considering: import/gnucobol/tests/testsuite.src/run_fundamental.at:1777:0
 Considering: import/gnucobol/tests/testsuite.src/run_fundamental.at:1856:0
-run_fundamental.at-1856-prog.cob:20.20:
-  17              DISPLAY "<"
-  18   
-  19              MOVE "dummy-call" TO prgm
-  20 >            CALL prgm
-----                       ^
-  21          >> IF CHECK-PERF IS DEFINED
-  22              PERFORM 500000 TIMES
->> Hint: Missing .
-
-run_fundamental.at-1856-prog.cob:21.7-21.12:
+run_fundamental.at-1856-prog.cob:21.7-21.34:
   18   
   19              MOVE "dummy-call" TO prgm
   20              CALL prgm
   21 >        >> IF CHECK-PERF IS DEFINED
-----          ^^^^^
-  22              PERFORM 500000 TIMES
-  23                 CALL prgm
->> Error: Invalid syntax
-
-run_fundamental.at-1856-prog.cob:21.23:
-  18   
-  19              MOVE "dummy-call" TO prgm
-  20              CALL prgm
-  21 >        >> IF CHECK-PERF IS DEFINED
-----                          ^
-  22              PERFORM 500000 TIMES
-  23                 CALL prgm
->> Hint: Missing .
-
-run_fundamental.at-1856-prog.cob:21.24-21.26:
-  18   
-  19              MOVE "dummy-call" TO prgm
-  20              CALL prgm
-  21 >        >> IF CHECK-PERF IS DEFINED
-----                           ^^
-  22              PERFORM 500000 TIMES
-  23                 CALL prgm
->> Warning: Invalid syntax
-
-run_fundamental.at-1856-prog.cob:21.34:
-  18   
-  19              MOVE "dummy-call" TO prgm
-  20              CALL prgm
-  21 >        >> IF CHECK-PERF IS DEFINED
-----                                     ^
+----          ^^^^^^^^^^^^^^^^^^^^^^^^^^^
   22              PERFORM 500000 TIMES
   23                 CALL prgm
->> Hint: Missing .
-
-run_fundamental.at-1856-prog.cob:22.11-22.18:
-  19              MOVE "dummy-call" TO prgm
-  20              CALL prgm
-  21          >> IF CHECK-PERF IS DEFINED
-  22 >            PERFORM 500000 TIMES
-----              ^^^^^^^
-  23                 CALL prgm
-  24              END-PERFORM
->> Warning: Invalid syntax
+>> Error: Malformed or unknown compiler directive
 
 run_fundamental.at-1856-prog.cob:25.7-25.16:
   22              PERFORM 500000 TIMES
@@ -533,68 +483,18 @@ run_fundamental.at-1856-prog.cob:25.7-25.16:
 ----          ^^^^^^^^^
   26              .
   27          END PROGRAM     prog.
->> Error: Invalid syntax
+>> Error: Malformed or unknown compiler directive
 
 Considering: import/gnucobol/tests/testsuite.src/run_fundamental.at:1956:0
-run_fundamental.at-1956-prog.cob:28.24:
-  25              DISPLAY "<"
-  26   
-  27              SET  prog-ptr TO ADDRESS OF PROGRAM "dummy-call"
-  28 >            CALL prog-ptr
-----                           ^
-  29          >> IF CHECK-PERF IS DEFINED
-  30              PERFORM 500000 TIMES
->> Hint: Missing .
-
-run_fundamental.at-1956-prog.cob:29.7-29.12:
-  26   
-  27              SET  prog-ptr TO ADDRESS OF PROGRAM "dummy-call"
-  28              CALL prog-ptr
-  29 >        >> IF CHECK-PERF IS DEFINED
-----          ^^^^^
-  30              PERFORM 500000 TIMES
-  31                 CALL prog-ptr
->> Error: Invalid syntax
-
-run_fundamental.at-1956-prog.cob:29.23:
-  26   
-  27              SET  prog-ptr TO ADDRESS OF PROGRAM "dummy-call"
-  28              CALL prog-ptr
-  29 >        >> IF CHECK-PERF IS DEFINED
-----                          ^
-  30              PERFORM 500000 TIMES
-  31                 CALL prog-ptr
->> Hint: Missing .
-
-run_fundamental.at-1956-prog.cob:29.24-29.26:
-  26   
-  27              SET  prog-ptr TO ADDRESS OF PROGRAM "dummy-call"
-  28              CALL prog-ptr
-  29 >        >> IF CHECK-PERF IS DEFINED
-----                           ^^
-  30              PERFORM 500000 TIMES
-  31                 CALL prog-ptr
->> Warning: Invalid syntax
-
-run_fundamental.at-1956-prog.cob:29.34:
+run_fundamental.at-1956-prog.cob:29.7-29.34:
   26   
   27              SET  prog-ptr TO ADDRESS OF PROGRAM "dummy-call"
   28              CALL prog-ptr
   29 >        >> IF CHECK-PERF IS DEFINED
-----                                     ^
+----          ^^^^^^^^^^^^^^^^^^^^^^^^^^^
   30              PERFORM 500000 TIMES
   31                 CALL prog-ptr
->> Hint: Missing .
-
-run_fundamental.at-1956-prog.cob:30.11-30.18:
-  27              SET  prog-ptr TO ADDRESS OF PROGRAM "dummy-call"
-  28              CALL prog-ptr
-  29          >> IF CHECK-PERF IS DEFINED
-  30 >            PERFORM 500000 TIMES
-----              ^^^^^^^
-  31                 CALL prog-ptr
-  32              END-PERFORM
->> Warning: Invalid syntax
+>> Error: Malformed or unknown compiler directive
 
 run_fundamental.at-1956-prog.cob:33.7-33.16:
   30              PERFORM 500000 TIMES
@@ -604,7 +504,7 @@ run_fundamental.at-1956-prog.cob:33.7-33.16:
 ----          ^^^^^^^^^
   34              .
   35          END PROGRAM     prog.
->> Error: Invalid syntax
+>> Error: Malformed or unknown compiler directive
 
 run_fundamental.at-1956-prog.cob:60.50:
   57   
@@ -832,15 +732,15 @@ Considering: import/gnucobol/tests/testsuite.src/run_fundamental.at:4508:0
 Considering: import/gnucobol/tests/testsuite.src/run_fundamental.at:4560:0
 Considering: import/gnucobol/tests/testsuite.src/run_fundamental.at:4608:0
 Considering: import/gnucobol/tests/testsuite.src/run_fundamental.at:4648:0
-run_fundamental.at-4648-prog.cob:12.7-12.11:
+run_fundamental.at-4648-prog.cob:12.7-12.19:
    9                  05  misalign-1           PIC X.
   10                  05  ptr                  POINTER, SYNC.
   11                  05  ptr-num              REDEFINES ptr,
   12 >        >>IF P64 SET
-----          ^^^^
+----          ^^^^^^^^^^^^
   13                                           USAGE BINARY-DOUBLE UNSIGNED.
   14          >>ELSE
->> Error: Invalid syntax
+>> Error: Malformed or unknown compiler directive
 
 run_fundamental.at-4648-prog.cob:14.7-14.13:
   11                  05  ptr-num              REDEFINES ptr,
@@ -1033,55 +933,15 @@ run_fundamental.at-5623-prog.cob:10.44-10.48:
 
 Considering: import/gnucobol/tests/testsuite.src/run_fundamental.at:5670:0
 Considering: import/gnucobol/tests/testsuite.src/run_fundamental.at:6013:0
-run_fundamental.at-6013-prog.cob:24.7-24.12:
-  21   
-  22         *>   Test with DISPLAY on error
-  23              PERFORM DO-CHECK
-  24 >        >> IF CHECK-PERF IS DEFINED
-----          ^^^^^
-  25              SET  NO-DISP    TO TRUE
-  26         *>   minimal side-test for performance comparisons
->> Error: Invalid syntax
-
-run_fundamental.at-6013-prog.cob:24.23:
-  21   
-  22         *>   Test with DISPLAY on error
-  23              PERFORM DO-CHECK
-  24 >        >> IF CHECK-PERF IS DEFINED
-----                          ^
-  25              SET  NO-DISP    TO TRUE
-  26         *>   minimal side-test for performance comparisons
->> Hint: Missing TIMES .
-
-run_fundamental.at-6013-prog.cob:24.24-24.26:
-  21   
-  22         *>   Test with DISPLAY on error
-  23              PERFORM DO-CHECK
-  24 >        >> IF CHECK-PERF IS DEFINED
-----                           ^^
-  25              SET  NO-DISP    TO TRUE
-  26         *>   minimal side-test for performance comparisons
->> Error: Invalid syntax
-
-run_fundamental.at-6013-prog.cob:24.34:
+run_fundamental.at-6013-prog.cob:24.7-24.34:
   21   
   22         *>   Test with DISPLAY on error
   23              PERFORM DO-CHECK
   24 >        >> IF CHECK-PERF IS DEFINED
-----                                     ^
+----          ^^^^^^^^^^^^^^^^^^^^^^^^^^^
   25              SET  NO-DISP    TO TRUE
   26         *>   minimal side-test for performance comparisons
->> Hint: Missing .
-
-run_fundamental.at-6013-prog.cob:25.11-25.14:
-  22         *>   Test with DISPLAY on error
-  23              PERFORM DO-CHECK
-  24          >> IF CHECK-PERF IS DEFINED
-  25 >            SET  NO-DISP    TO TRUE
-----              ^^^
-  26         *>   minimal side-test for performance comparisons
-  27              PERFORM DO-CHECK 20000 TIMES
->> Warning: Invalid syntax
+>> Error: Malformed or unknown compiler directive
 
 run_fundamental.at-6013-prog.cob:28.7-28.16:
   25              SET  NO-DISP    TO TRUE
@@ -1091,7 +951,7 @@ run_fundamental.at-6013-prog.cob:28.7-28.16:
 ----          ^^^^^^^^^
   29              GOBACK.
   30   
->> Error: Invalid syntax
+>> Error: Malformed or unknown compiler directive
 
 run_fundamental.at-6013-prog.cob:76.29-76.33:
   73              ELSE                        DISPLAY '! LOW-VALUE <= "X"'.
@@ -1414,55 +1274,15 @@ run_fundamental.at-6013-prog.cob:233.15-233.19:
 >> Error: Invalid syntax
 
 Considering: import/gnucobol/tests/testsuite.src/run_fundamental.at:6072:0
-run_fundamental.at-6072-prog.cob:22.7-22.12:
-  19   
-  20         *>   Test with DISPLAY on error
-  21              PERFORM DO-CHECK
-  22 >        >> IF CHECK-PERF IS DEFINED
-----          ^^^^^
-  23              SET  NO-DISP    TO TRUE
-  24         *>   minimal side-test for performance comparisons
->> Error: Invalid syntax
-
-run_fundamental.at-6072-prog.cob:22.23:
-  19   
-  20         *>   Test with DISPLAY on error
-  21              PERFORM DO-CHECK
-  22 >        >> IF CHECK-PERF IS DEFINED
-----                          ^
-  23              SET  NO-DISP    TO TRUE
-  24         *>   minimal side-test for performance comparisons
->> Hint: Missing TIMES .
-
-run_fundamental.at-6072-prog.cob:22.24-22.26:
+run_fundamental.at-6072-prog.cob:22.7-22.34:
   19   
   20         *>   Test with DISPLAY on error
   21              PERFORM DO-CHECK
   22 >        >> IF CHECK-PERF IS DEFINED
-----                           ^^
-  23              SET  NO-DISP    TO TRUE
-  24         *>   minimal side-test for performance comparisons
->> Error: Invalid syntax
-
-run_fundamental.at-6072-prog.cob:22.34:
-  19   
-  20         *>   Test with DISPLAY on error
-  21              PERFORM DO-CHECK
-  22 >        >> IF CHECK-PERF IS DEFINED
-----                                     ^
+----          ^^^^^^^^^^^^^^^^^^^^^^^^^^^
   23              SET  NO-DISP    TO TRUE
   24         *>   minimal side-test for performance comparisons
->> Hint: Missing .
-
-run_fundamental.at-6072-prog.cob:23.11-23.14:
-  20         *>   Test with DISPLAY on error
-  21              PERFORM DO-CHECK
-  22          >> IF CHECK-PERF IS DEFINED
-  23 >            SET  NO-DISP    TO TRUE
-----              ^^^
-  24         *>   minimal side-test for performance comparisons
-  25              PERFORM DO-CHECK 20000 TIMES
->> Warning: Invalid syntax
+>> Error: Malformed or unknown compiler directive
 
 run_fundamental.at-6072-prog.cob:26.7-26.16:
   23              SET  NO-DISP    TO TRUE
@@ -1472,7 +1292,7 @@ run_fundamental.at-6072-prog.cob:26.7-26.16:
 ----          ^^^^^^^^^
   27              GOBACK.
   28   
->> Error: Invalid syntax
+>> Error: Malformed or unknown compiler directive
 
 Considering: import/gnucobol/tests/testsuite.src/run_fundamental.at:6161:0
 Considering: import/gnucobol/tests/testsuite.src/run_fundamental.at:6229:0
diff --git a/test/output-tests/run_misc.expected b/test/output-tests/run_misc.expected
index fd1486f87..eba57730d 100644
--- a/test/output-tests/run_misc.expected
+++ b/test/output-tests/run_misc.expected
@@ -274,65 +274,15 @@ run_misc.at-942-prog.cob:14.7-14.45:
   16          >>TURN EC-BOUND-SUBSCRIPT CHECKING ON WITH LOCATION
 >> Error: Malformed or unknown compiler directive
 
-run_misc.at-942-prog.cob:15.44:
-  12   
-  13          PROCEDURE DIVISION.
-  14          >>TURN EC-BOUND-SUBSCRIPT CHECKING OFF
-  15 >            DISPLAY y (idx) WITH NO ADVANCING
-----                                               ^
-  16          >>TURN EC-BOUND-SUBSCRIPT CHECKING ON WITH LOCATION
-  17          >>TURN EC-BOUND, EC-PROGRAM CHECKING OFF
->> Hint: Missing .
-
-run_misc.at-942-prog.cob:16.7-16.13:
-  13          PROCEDURE DIVISION.
-  14          >>TURN EC-BOUND-SUBSCRIPT CHECKING OFF
-  15              DISPLAY y (idx) WITH NO ADVANCING
-  16 >        >>TURN EC-BOUND-SUBSCRIPT CHECKING ON WITH LOCATION
-----          ^^^^^^
-  17          >>TURN EC-BOUND, EC-PROGRAM CHECKING OFF
-  18              DISPLAY y (idx) WITH NO ADVANCING
->> Warning: Invalid syntax
-
-run_misc.at-942-prog.cob:16.32:
-  13          PROCEDURE DIVISION.
-  14          >>TURN EC-BOUND-SUBSCRIPT CHECKING OFF
-  15              DISPLAY y (idx) WITH NO ADVANCING
-  16 >        >>TURN EC-BOUND-SUBSCRIPT CHECKING ON WITH LOCATION
-----                                   ^
-  17          >>TURN EC-BOUND, EC-PROGRAM CHECKING OFF
-  18              DISPLAY y (idx) WITH NO ADVANCING
->> Hint: Missing .
-
-run_misc.at-942-prog.cob:16.33-16.41:
+run_misc.at-942-prog.cob:16.7-16.58:
   13          PROCEDURE DIVISION.
   14          >>TURN EC-BOUND-SUBSCRIPT CHECKING OFF
   15              DISPLAY y (idx) WITH NO ADVANCING
   16 >        >>TURN EC-BOUND-SUBSCRIPT CHECKING ON WITH LOCATION
-----                                    ^^^^^^^^
+----          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   17          >>TURN EC-BOUND, EC-PROGRAM CHECKING OFF
   18              DISPLAY y (idx) WITH NO ADVANCING
->> Warning: Invalid syntax
-
-run_misc.at-942-prog.cob:16.41:
-  13          PROCEDURE DIVISION.
-  14          >>TURN EC-BOUND-SUBSCRIPT CHECKING OFF
-  15              DISPLAY y (idx) WITH NO ADVANCING
-  16 >        >>TURN EC-BOUND-SUBSCRIPT CHECKING ON WITH LOCATION
-----                                            ^
-  17          >>TURN EC-BOUND, EC-PROGRAM CHECKING OFF
-  18              DISPLAY y (idx) WITH NO ADVANCING
->> Hint: Missing .
-
-run_misc.at-942-prog.cob:16.42-16.44:
-  13          PROCEDURE DIVISION.
-  14          >>TURN EC-BOUND-SUBSCRIPT CHECKING OFF
-  15              DISPLAY y (idx) WITH NO ADVANCING
-  16 >        >>TURN EC-BOUND-SUBSCRIPT CHECKING ON WITH LOCATION
-----                                             ^^
-  17          >>TURN EC-BOUND, EC-PROGRAM CHECKING OFF
-  18              DISPLAY y (idx) WITH NO ADVANCING
->> Warning: Invalid syntax
+>> Error: Malformed or unknown compiler directive
 
 run_misc.at-942-prog.cob:17.7-17.47:
   14          >>TURN EC-BOUND-SUBSCRIPT CHECKING OFF
@@ -344,85 +294,15 @@ run_misc.at-942-prog.cob:17.7-17.47:
   19          >>TURN EC-BOUND-SUBSCRIPT CHECKING ON
 >> Error: Malformed or unknown compiler directive
 
-run_misc.at-942-prog.cob:16.58:
-  13          PROCEDURE DIVISION.
-  14          >>TURN EC-BOUND-SUBSCRIPT CHECKING OFF
-  15              DISPLAY y (idx) WITH NO ADVANCING
-  16 >        >>TURN EC-BOUND-SUBSCRIPT CHECKING ON WITH LOCATION
-----                                                             ^
-  17          >>TURN EC-BOUND, EC-PROGRAM CHECKING OFF
-  18              DISPLAY y (idx) WITH NO ADVANCING
->> Hint: Missing .
-
-run_misc.at-942-prog.cob:18.11-18.18:
-  15              DISPLAY y (idx) WITH NO ADVANCING
-  16          >>TURN EC-BOUND-SUBSCRIPT CHECKING ON WITH LOCATION
-  17          >>TURN EC-BOUND, EC-PROGRAM CHECKING OFF
-  18 >            DISPLAY y (idx) WITH NO ADVANCING
-----              ^^^^^^^
-  19          >>TURN EC-BOUND-SUBSCRIPT CHECKING ON
-  20              DISPLAY y (idx) WITH NO ADVANCING
->> Warning: Invalid syntax
-
-run_misc.at-942-prog.cob:18.44:
-  15              DISPLAY y (idx) WITH NO ADVANCING
-  16          >>TURN EC-BOUND-SUBSCRIPT CHECKING ON WITH LOCATION
-  17          >>TURN EC-BOUND, EC-PROGRAM CHECKING OFF
-  18 >            DISPLAY y (idx) WITH NO ADVANCING
-----                                               ^
-  19          >>TURN EC-BOUND-SUBSCRIPT CHECKING ON
-  20              DISPLAY y (idx) WITH NO ADVANCING
->> Hint: Missing .
-
-run_misc.at-942-prog.cob:19.7-19.13:
-  16          >>TURN EC-BOUND-SUBSCRIPT CHECKING ON WITH LOCATION
-  17          >>TURN EC-BOUND, EC-PROGRAM CHECKING OFF
-  18              DISPLAY y (idx) WITH NO ADVANCING
-  19 >        >>TURN EC-BOUND-SUBSCRIPT CHECKING ON
-----          ^^^^^^
-  20              DISPLAY y (idx) WITH NO ADVANCING
-  21              .
->> Warning: Invalid syntax
-
-run_misc.at-942-prog.cob:19.32:
+run_misc.at-942-prog.cob:19.7-19.44:
   16          >>TURN EC-BOUND-SUBSCRIPT CHECKING ON WITH LOCATION
   17          >>TURN EC-BOUND, EC-PROGRAM CHECKING OFF
   18              DISPLAY y (idx) WITH NO ADVANCING
   19 >        >>TURN EC-BOUND-SUBSCRIPT CHECKING ON
-----                                   ^
-  20              DISPLAY y (idx) WITH NO ADVANCING
-  21              .
->> Hint: Missing .
-
-run_misc.at-942-prog.cob:19.33-19.41:
-  16          >>TURN EC-BOUND-SUBSCRIPT CHECKING ON WITH LOCATION
-  17          >>TURN EC-BOUND, EC-PROGRAM CHECKING OFF
-  18              DISPLAY y (idx) WITH NO ADVANCING
-  19 >        >>TURN EC-BOUND-SUBSCRIPT CHECKING ON
-----                                    ^^^^^^^^
-  20              DISPLAY y (idx) WITH NO ADVANCING
-  21              .
->> Warning: Invalid syntax
-
-run_misc.at-942-prog.cob:19.41:
-  16          >>TURN EC-BOUND-SUBSCRIPT CHECKING ON WITH LOCATION
-  17          >>TURN EC-BOUND, EC-PROGRAM CHECKING OFF
-  18              DISPLAY y (idx) WITH NO ADVANCING
-  19 >        >>TURN EC-BOUND-SUBSCRIPT CHECKING ON
-----                                            ^
-  20              DISPLAY y (idx) WITH NO ADVANCING
-  21              .
->> Hint: Missing .
-
-run_misc.at-942-prog.cob:19.42-19.44:
-  16          >>TURN EC-BOUND-SUBSCRIPT CHECKING ON WITH LOCATION
-  17          >>TURN EC-BOUND, EC-PROGRAM CHECKING OFF
-  18              DISPLAY y (idx) WITH NO ADVANCING
-  19 >        >>TURN EC-BOUND-SUBSCRIPT CHECKING ON
-----                                             ^^
+----          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   20              DISPLAY y (idx) WITH NO ADVANCING
   21              .
->> Warning: Invalid syntax
+>> Error: Malformed or unknown compiler directive
 
 Considering: import/gnucobol/tests/testsuite.src/run_misc.at:974:0
 Considering: import/gnucobol/tests/testsuite.src/run_misc.at:996:0
@@ -1079,26 +959,6 @@ run_misc.at-3626-prog.cob:5.6-5.7:
    7         >>ELIF EXPECT-ORDER  =  'EBCDIC'
 >> Error: Unexpected indicator: `>'
 
-run_misc.at-3626-prog.cob:7.6-7.7:
-   4          PROCEDURE        DIVISION.
-   5         >>IF   EXPECT-ORDER  =  'ASCII'
-   6              IF "1" NOT < "a"
-   7 >       >>ELIF EXPECT-ORDER  =  'EBCDIC'
-----         ^
-   8              IF "a" NOT < "1"
-   9         >>END-IF
->> Error: Unexpected indicator: `>'
-
-run_misc.at-3626-prog.cob:9.6-9.7:
-   6              IF "1" NOT < "a"
-   7         >>ELIF EXPECT-ORDER  =  'EBCDIC'
-   8              IF "a" NOT < "1"
-   9 >       >>END-IF
-----         ^
-  10                 DISPLAY "ERROR" END-DISPLAY
-  11              END-IF.
->> Error: Unexpected indicator: `>'
-
 run_misc.at-3626-prog.cob:5.7-5.8:
    2          IDENTIFICATION   DIVISION.
    3          PROGRAM-ID.      prog.
@@ -1109,6 +969,16 @@ run_misc.at-3626-prog.cob:5.7-5.8:
    7         >>ELIF EXPECT-ORDER  =  'EBCDIC'
 >> Error: Invalid syntax
 
+run_misc.at-3626-prog.cob:7.6-7.7:
+   4          PROCEDURE        DIVISION.
+   5         >>IF   EXPECT-ORDER  =  'ASCII'
+   6              IF "1" NOT < "a"
+   7 >       >>ELIF EXPECT-ORDER  =  'EBCDIC'
+----         ^
+   8              IF "a" NOT < "1"
+   9         >>END-IF
+>> Error: Unexpected indicator: `>'
+
 run_misc.at-3626-prog.cob:6.27:
    3          PROGRAM-ID.      prog.
    4          PROCEDURE        DIVISION.
@@ -1169,6 +1039,16 @@ run_misc.at-3626-prog.cob:7.27-7.28:
    9         >>END-IF
 >> Warning: Invalid syntax
 
+run_misc.at-3626-prog.cob:9.6-9.7:
+   6              IF "1" NOT < "a"
+   7         >>ELIF EXPECT-ORDER  =  'EBCDIC'
+   8              IF "a" NOT < "1"
+   9 >       >>END-IF
+----         ^
+  10                 DISPLAY "ERROR" END-DISPLAY
+  11              END-IF.
+>> Error: Unexpected indicator: `>'
+
 run_misc.at-3626-prog.cob:9.7-9.8:
    6              IF "1" NOT < "a"
    7         >>ELIF EXPECT-ORDER  =  'EBCDIC'
@@ -1199,36 +1079,6 @@ run_misc.at-3663-prog.cob:12.6-12.7:
   14         >>ELIF EXPECT-ORDER  =  'EBCDIC'
 >> Error: Unexpected indicator: `>'
 
-run_misc.at-3663-prog.cob:14.6-14.7:
-  11              SORT TBL ASCENDING KEY X.
-  12         >>IF   EXPECT-ORDER  =  'ASCII'
-  13              IF G NOT = "12345abcde"
-  14 >       >>ELIF EXPECT-ORDER  =  'EBCDIC'
-----         ^
-  15              IF G NOT = "abcde12345"
-  16         >>ELSE           *>  =  'NATIVE'
->> Error: Unexpected indicator: `>'
-
-run_misc.at-3663-prog.cob:16.6-16.7:
-  13              IF G NOT = "12345abcde"
-  14         >>ELIF EXPECT-ORDER  =  'EBCDIC'
-  15              IF G NOT = "abcde12345"
-  16 >       >>ELSE           *>  =  'NATIVE'
-----         ^
-  17              IF NOT G = "12345abcde" OR "abcde12345"
-  18         >>END-IF
->> Error: Unexpected indicator: `>'
-
-run_misc.at-3663-prog.cob:18.6-18.7:
-  15              IF G NOT = "abcde12345"
-  16         >>ELSE           *>  =  'NATIVE'
-  17              IF NOT G = "12345abcde" OR "abcde12345"
-  18 >       >>END-IF
-----         ^
-  19                 DISPLAY G END-DISPLAY
-  20              END-IF.
->> Error: Unexpected indicator: `>'
-
 run_misc.at-3663-prog.cob:12.7-12.8:
    9              03 X         PIC X.
   10          PROCEDURE        DIVISION.
@@ -1239,6 +1089,16 @@ run_misc.at-3663-prog.cob:12.7-12.8:
   14         >>ELIF EXPECT-ORDER  =  'EBCDIC'
 >> Error: Invalid syntax
 
+run_misc.at-3663-prog.cob:14.6-14.7:
+  11              SORT TBL ASCENDING KEY X.
+  12         >>IF   EXPECT-ORDER  =  'ASCII'
+  13              IF G NOT = "12345abcde"
+  14 >       >>ELIF EXPECT-ORDER  =  'EBCDIC'
+----         ^
+  15              IF G NOT = "abcde12345"
+  16         >>ELSE           *>  =  'NATIVE'
+>> Error: Unexpected indicator: `>'
+
 run_misc.at-3663-prog.cob:13.34:
   10          PROCEDURE        DIVISION.
   11              SORT TBL ASCENDING KEY X.
@@ -1299,6 +1159,16 @@ run_misc.at-3663-prog.cob:14.27-14.28:
   16         >>ELSE           *>  =  'NATIVE'
 >> Warning: Invalid syntax
 
+run_misc.at-3663-prog.cob:16.6-16.7:
+  13              IF G NOT = "12345abcde"
+  14         >>ELIF EXPECT-ORDER  =  'EBCDIC'
+  15              IF G NOT = "abcde12345"
+  16 >       >>ELSE           *>  =  'NATIVE'
+----         ^
+  17              IF NOT G = "12345abcde" OR "abcde12345"
+  18         >>END-IF
+>> Error: Unexpected indicator: `>'
+
 run_misc.at-3663-prog.cob:16.7-16.8:
   13              IF G NOT = "12345abcde"
   14         >>ELIF EXPECT-ORDER  =  'EBCDIC'
@@ -1309,6 +1179,16 @@ run_misc.at-3663-prog.cob:16.7-16.8:
   18         >>END-IF
 >> Error: Invalid syntax
 
+run_misc.at-3663-prog.cob:18.6-18.7:
+  15              IF G NOT = "abcde12345"
+  16         >>ELSE           *>  =  'NATIVE'
+  17              IF NOT G = "12345abcde" OR "abcde12345"
+  18 >       >>END-IF
+----         ^
+  19                 DISPLAY G END-DISPLAY
+  20              END-IF.
+>> Error: Unexpected indicator: `>'
+
 run_misc.at-3663-prog.cob:18.8:
   15              IF G NOT = "abcde12345"
   16         >>ELSE           *>  =  'NATIVE'
@@ -1371,26 +1251,6 @@ run_misc.at-3961-prog.cob:20.6-20.7:
   22         >>ELIF EXPECT-ORDER  =  'EBCDIC'
 >> Error: Unexpected indicator: `>'
 
-run_misc.at-3961-prog.cob:22.6-22.7:
-  19              END-SEARCH
-  20         >>IF   EXPECT-ORDER  =  'ASCII'
-  21              IF I NOT = 3
-  22 >       >>ELIF EXPECT-ORDER  =  'EBCDIC'
-----         ^
-  23              IF I NOT = 8
-  24         >>END-IF
->> Error: Unexpected indicator: `>'
-
-run_misc.at-3961-prog.cob:24.6-24.7:
-  21              IF I NOT = 3
-  22         >>ELIF EXPECT-ORDER  =  'EBCDIC'
-  23              IF I NOT = 8
-  24 >       >>END-IF
-----         ^
-  25                 DISPLAY "ERROR" END-DISPLAY
-  26              STOP RUN.
->> Error: Unexpected indicator: `>'
-
 run_misc.at-3961-prog.cob:20.7-20.8:
   17                 WHEN K (I) = KK
   18                    CONTINUE
@@ -1401,6 +1261,16 @@ run_misc.at-3961-prog.cob:20.7-20.8:
   22         >>ELIF EXPECT-ORDER  =  'EBCDIC'
 >> Error: Invalid syntax
 
+run_misc.at-3961-prog.cob:22.6-22.7:
+  19              END-SEARCH
+  20         >>IF   EXPECT-ORDER  =  'ASCII'
+  21              IF I NOT = 3
+  22 >       >>ELIF EXPECT-ORDER  =  'EBCDIC'
+----         ^
+  23              IF I NOT = 8
+  24         >>END-IF
+>> Error: Unexpected indicator: `>'
+
 run_misc.at-3961-prog.cob:21.23:
   18                    CONTINUE
   19              END-SEARCH
@@ -1461,6 +1331,16 @@ run_misc.at-3961-prog.cob:22.27-22.28:
   24         >>END-IF
 >> Warning: Invalid syntax
 
+run_misc.at-3961-prog.cob:24.6-24.7:
+  21              IF I NOT = 3
+  22         >>ELIF EXPECT-ORDER  =  'EBCDIC'
+  23              IF I NOT = 8
+  24 >       >>END-IF
+----         ^
+  25                 DISPLAY "ERROR" END-DISPLAY
+  26              STOP RUN.
+>> Error: Unexpected indicator: `>'
+
 run_misc.at-3961-prog.cob:24.7-24.8:
   21              IF I NOT = 3
   22         >>ELIF EXPECT-ORDER  =  'EBCDIC'
@@ -5303,26 +5183,6 @@ run_misc.at-10739-reference_tmpl:73.6-73.7:
   75   01        X                               000005441
 >> Error: Unexpected indicator: `E'
 
-run_misc.at-10739-reference_tmpl:81.6-81.7:
-  78   END OF DUMP - sub1
-  79   **********************
-  80   
-  81 > Dump Program-Id sub2 from sub2.cob compiled MMM DD YYYY HH:MM:SS
-----         ^
-  82   
-  83   WORKING-STORAGE
->> Error: Unexpected indicator: `r'
-
-run_misc.at-10739-reference_tmpl:83.6-83.7:
-  80   
-  81   Dump Program-Id sub2 from sub2.cob compiled MMM DD YYYY HH:MM:SS
-  82   
-  83 > WORKING-STORAGE
-----         ^
-  84   **********************
-  85   77        RETURN-CODE                     +000000000
->> Error: Unexpected indicator: `G'
-
 run_misc.at-10739-reference_tmpl:56.41-56.72:
   53     05      TSTTAIL1                        X  _
   54                                        1 x 5811
@@ -5343,6 +5203,26 @@ run_misc.at-10739-reference_tmpl:70.41-70.72:
   72   
 >> Error: Missing continuation of `Quick brown fox jumped over th'
 
+run_misc.at-10739-reference_tmpl:81.6-81.7:
+  78   END OF DUMP - sub1
+  79   **********************
+  80   
+  81 > Dump Program-Id sub2 from sub2.cob compiled MMM DD YYYY HH:MM:SS
+----         ^
+  82   
+  83   WORKING-STORAGE
+>> Error: Unexpected indicator: `r'
+
+run_misc.at-10739-reference_tmpl:83.6-83.7:
+  80   
+  81   Dump Program-Id sub2 from sub2.cob compiled MMM DD YYYY HH:MM:SS
+  82   
+  83 > WORKING-STORAGE
+----         ^
+  84   **********************
+  85   77        RETURN-CODE                     +000000000
+>> Error: Unexpected indicator: `G'
+
 run_misc.at-10739-reference_tmpl:116.41-116.72:
  113     05      TSTTAIL1                        X  _
  114                                        1 x 5811
@@ -5573,55 +5453,15 @@ run_misc.at-11129-prog.cob:106.43-106.49:
 >> Error: Invalid syntax
 
 Considering: import/gnucobol/tests/testsuite.src/run_misc.at:11365:0
-run_misc.at-11365-caller.cob:9.7-9.12:
+run_misc.at-11365-caller.cob:9.7-9.34:
    6          MAIN-LINE.
    7   
    8              PERFORM DO-CHECK
    9 >        >> IF CHECK-PERF IS DEFINED
-----          ^^^^^
-  10         *>   minimal side-test for performance comparisons
-  11              PERFORM DO-CHECK 10000 TIMES
->> Error: Invalid syntax
-
-run_misc.at-11365-caller.cob:9.23:
-   6          MAIN-LINE.
-   7   
-   8              PERFORM DO-CHECK
-   9 >        >> IF CHECK-PERF IS DEFINED
-----                          ^
-  10         *>   minimal side-test for performance comparisons
-  11              PERFORM DO-CHECK 10000 TIMES
->> Hint: Missing TIMES .
-
-run_misc.at-11365-caller.cob:9.24-9.26:
-   6          MAIN-LINE.
-   7   
-   8              PERFORM DO-CHECK
-   9 >        >> IF CHECK-PERF IS DEFINED
-----                           ^^
-  10         *>   minimal side-test for performance comparisons
-  11              PERFORM DO-CHECK 10000 TIMES
->> Error: Invalid syntax
-
-run_misc.at-11365-caller.cob:9.34:
-   6          MAIN-LINE.
-   7   
-   8              PERFORM DO-CHECK
-   9 >        >> IF CHECK-PERF IS DEFINED
-----                                     ^
+----          ^^^^^^^^^^^^^^^^^^^^^^^^^^^
   10         *>   minimal side-test for performance comparisons
   11              PERFORM DO-CHECK 10000 TIMES
->> Hint: Missing .
-
-run_misc.at-11365-caller.cob:11.11-11.18:
-   8              PERFORM DO-CHECK
-   9          >> IF CHECK-PERF IS DEFINED
-  10         *>   minimal side-test for performance comparisons
-  11 >            PERFORM DO-CHECK 10000 TIMES
-----              ^^^^^^^
-  12          >> END-IF
-  13              DISPLAY 'DONE' UPON SYSERR WITH NO ADVANCING
->> Warning: Invalid syntax
+>> Error: Malformed or unknown compiler directive
 
 run_misc.at-11365-caller.cob:12.7-12.16:
    9          >> IF CHECK-PERF IS DEFINED
@@ -5631,7 +5471,7 @@ run_misc.at-11365-caller.cob:12.7-12.16:
 ----          ^^^^^^^^^
   13              DISPLAY 'DONE' UPON SYSERR WITH NO ADVANCING
   14              GOBACK.
->> Error: Invalid syntax
+>> Error: Malformed or unknown compiler directive
 
 Considering: import/gnucobol/tests/testsuite.src/run_misc.at:11339:0
 Considering: import/gnucobol/tests/testsuite.src/run_misc.at:11409:0
diff --git a/test/output-tests/run_reportwriter.expected b/test/output-tests/run_reportwriter.expected
index 933207e27..0a16841f6 100644
--- a/test/output-tests/run_reportwriter.expected
+++ b/test/output-tests/run_reportwriter.expected
@@ -4767,6 +4767,16 @@ run_reportwriter.at-2890-reference:4.7-4.11:
    6   
 >> Warning: Unexpected non-blank area A on continuation line
 
+run_reportwriter.at-2890-reference:4.11-4.14:
+   1                                         C E N T U R Y   M E D I C A L   C E N T E R
+   2                                     Q U A R T E R L Y   P A Y R O L L   R E G I S T E R                         PAGE     1
+   3   
+   4 >      --------- EMPLOYEE ---------      GROSS         FICA        FED W/H       MISC.          NET
+----              ^^^
+   5         NO             NAME               PAY           TAX          TAX        DEDUCT.         PAY
+   6   
+>> Error: Unexpected `---' in continuation
+
 run_reportwriter.at-2890-reference:5.6-5.7:
    2                                     Q U A R T E R L Y   P A Y R O L L   R E G I S T E R                         PAGE     1
    3   
@@ -6737,6 +6747,16 @@ run_reportwriter.at-3787-reference:8.7-8.11:
   10     Dorken, Keith A        35       Waterloo          "
 >> Warning: Unexpected non-blank area A on continuation line
 
+run_reportwriter.at-3787-reference:8.11-8.71:
+   5                                       MAJOR  CS
+   6   
+   7      STUDENT NAME         PTS      CAMPUS                    ADVISOR
+   8 >    --------------------------------------------------------------------
+----              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   9     Norman, Ronald J       25       Waterloo        Hello    Malcolm, Mike
+  10     Dorken, Keith A        35       Waterloo          "
+>> Error: Unexpected `------------------------------------------------------------' in continuation
+
 run_reportwriter.at-3787-reference:9.6-9.7:
    6   
    7      STUDENT NAME         PTS      CAMPUS                    ADVISOR
@@ -6817,6 +6837,16 @@ run_reportwriter.at-3787-reference:33.7-33.11:
   35   
 >> Warning: Unexpected non-blank area A on continuation line
 
+run_reportwriter.at-3787-reference:33.11-33.71:
+  30                                       MAJOR  EC
+  31   
+  32      STUDENT NAME         PTS      CAMPUS                    ADVISOR
+  33 >    --------------------------------------------------------------------
+----              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  34     Allinson, A R          25       Whistler        Hello    Manning, Eric
+  35   
+>> Error: Unexpected `------------------------------------------------------------' in continuation
+
 run_reportwriter.at-3787-reference:34.6-34.7:
   31   
   32      STUDENT NAME         PTS      CAMPUS                    ADVISOR
@@ -8665,6 +8695,16 @@ run_reportwriter.at-9078-reference:5.7-5.11:
    7   
 >> Warning: Unexpected non-blank area A on continuation line
 
+run_reportwriter.at-9078-reference:5.11-5.72:
+   2   Region:    MW
+   3   Location:            1000051
+   4   Invoice#   Date                              Order#          Line#  Item#                            TX Qty      Cost
+   5 > --------------------------------------------------------------------------------------------------------------------------------
+----              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   6   
+   7   
+>> Error: Unexpected `-------------------------------------------------------------' in continuation
+
 run_reportwriter.at-9078-reference:8.6-8.7:
    5   --------------------------------------------------------------------------------------------------------------------------------
    6   
@@ -8725,6 +8765,16 @@ run_reportwriter.at-9078-reference:65.7-65.11:
   67   
 >> Warning: Unexpected non-blank area A on continuation line
 
+run_reportwriter.at-9078-reference:65.11-65.72:
+  62   Region:    MW
+  63   Location:            1000071
+  64   Invoice#   Date                              Order#          Line#  Item#                            TX Qty      Cost
+  65 > --------------------------------------------------------------------------------------------------------------------------------
+----              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  66   
+  67   
+>> Error: Unexpected `-------------------------------------------------------------' in continuation
+
 run_reportwriter.at-9078-reference:68.6-68.7:
   65   --------------------------------------------------------------------------------------------------------------------------------
   66   
@@ -8785,6 +8835,16 @@ run_reportwriter.at-9078-reference:125.7-125.11:
  127   
 >> Warning: Unexpected non-blank area A on continuation line
 
+run_reportwriter.at-9078-reference:125.11-125.72:
+ 122   Region:    MW
+ 123   Location:            1000201
+ 124   Invoice#   Date                              Order#          Line#  Item#                            TX Qty      Cost
+ 125 > --------------------------------------------------------------------------------------------------------------------------------
+----              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ 126   
+ 127   
+>> Error: Unexpected `-------------------------------------------------------------' in continuation
+
 run_reportwriter.at-9078-reference:128.6-128.7:
  125   --------------------------------------------------------------------------------------------------------------------------------
  126   
@@ -8845,6 +8905,16 @@ run_reportwriter.at-9078-reference:185.7-185.11:
  187   
 >> Warning: Unexpected non-blank area A on continuation line
 
+run_reportwriter.at-9078-reference:185.11-185.72:
+ 182   Region:    MW
+ 183   Location:            1000291
+ 184   Invoice#   Date                              Order#          Line#  Item#                            TX Qty      Cost
+ 185 > --------------------------------------------------------------------------------------------------------------------------------
+----              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ 186   
+ 187   
+>> Error: Unexpected `-------------------------------------------------------------' in continuation
+
 run_reportwriter.at-9078-reference:188.6-188.7:
  185   --------------------------------------------------------------------------------------------------------------------------------
  186   
@@ -8895,6 +8965,16 @@ run_reportwriter.at-9078-reference:245.7-245.11:
  247   
 >> Warning: Unexpected non-blank area A on continuation line
 
+run_reportwriter.at-9078-reference:245.11-245.72:
+ 242   Region:    MW
+ 243   Location:            1000411
+ 244   Invoice#   Date                              Order#          Line#  Item#                            TX Qty      Cost
+ 245 > --------------------------------------------------------------------------------------------------------------------------------
+----              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ 246   
+ 247   
+>> Error: Unexpected `-------------------------------------------------------------' in continuation
+
 run_reportwriter.at-9078-reference:248.6-248.7:
  245   --------------------------------------------------------------------------------------------------------------------------------
  246   
@@ -8945,6 +9025,16 @@ run_reportwriter.at-9078-reference:305.7-305.11:
  307   
 >> Warning: Unexpected non-blank area A on continuation line
 
+run_reportwriter.at-9078-reference:305.11-305.72:
+ 302   Region:    MW
+ 303   Location:            1000451
+ 304   Invoice#   Date                              Order#          Line#  Item#                            TX Qty      Cost
+ 305 > --------------------------------------------------------------------------------------------------------------------------------
+----              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ 306   
+ 307   
+>> Error: Unexpected `-------------------------------------------------------------' in continuation
+
 run_reportwriter.at-9078-reference:308.6-308.7:
  305   --------------------------------------------------------------------------------------------------------------------------------
  306   
@@ -8995,6 +9085,16 @@ run_reportwriter.at-9078-reference:365.7-365.11:
  367   
 >> Warning: Unexpected non-blank area A on continuation line
 
+run_reportwriter.at-9078-reference:365.11-365.72:
+ 362   Region:    MW
+ 363   Location:            1000471
+ 364   Invoice#   Date                              Order#          Line#  Item#                            TX Qty      Cost
+ 365 > --------------------------------------------------------------------------------------------------------------------------------
+----              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ 366   
+ 367   
+>> Error: Unexpected `-------------------------------------------------------------' in continuation
+
 run_reportwriter.at-9078-reference:368.6-368.7:
  365   --------------------------------------------------------------------------------------------------------------------------------
  366   
@@ -9045,6 +9145,16 @@ run_reportwriter.at-9078-reference:425.7-425.11:
  427   
 >> Warning: Unexpected non-blank area A on continuation line
 
+run_reportwriter.at-9078-reference:425.11-425.72:
+ 422   Region:    MW
+ 423   Location:            1000831
+ 424   Invoice#   Date                              Order#          Line#  Item#                            TX Qty      Cost
+ 425 > --------------------------------------------------------------------------------------------------------------------------------
+----              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ 426   
+ 427   
+>> Error: Unexpected `-------------------------------------------------------------' in continuation
+
 run_reportwriter.at-9078-reference:428.6-428.7:
  425   --------------------------------------------------------------------------------------------------------------------------------
  426   
@@ -9115,6 +9225,16 @@ run_reportwriter.at-9078-reference:485.7-485.11:
  487   
 >> Warning: Unexpected non-blank area A on continuation line
 
+run_reportwriter.at-9078-reference:485.11-485.72:
+ 482   Region:    MW
+ 483   Location:            1000891
+ 484   Invoice#   Date                              Order#          Line#  Item#                            TX Qty      Cost
+ 485 > --------------------------------------------------------------------------------------------------------------------------------
+----              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ 486   
+ 487   
+>> Error: Unexpected `-------------------------------------------------------------' in continuation
+
 run_reportwriter.at-9078-reference:488.6-488.7:
  485   --------------------------------------------------------------------------------------------------------------------------------
  486   
@@ -9175,6 +9295,16 @@ run_reportwriter.at-9078-reference:545.7-545.11:
  547   
 >> Warning: Unexpected non-blank area A on continuation line
 
+run_reportwriter.at-9078-reference:545.11-545.72:
+ 542   Region:    NE
+ 543   Location:            1000001
+ 544   Invoice#   Date                              Order#          Line#  Item#                            TX Qty      Cost
+ 545 > --------------------------------------------------------------------------------------------------------------------------------
+----              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ 546   
+ 547   
+>> Error: Unexpected `-------------------------------------------------------------' in continuation
+
 run_reportwriter.at-9078-reference:548.6-548.7:
  545   --------------------------------------------------------------------------------------------------------------------------------
  546   
@@ -9225,6 +9355,16 @@ run_reportwriter.at-9078-reference:605.7-605.11:
  607   
 >> Warning: Unexpected non-blank area A on continuation line
 
+run_reportwriter.at-9078-reference:605.11-605.72:
+ 602   Region:    NE
+ 603   Location:            1000201
+ 604   Invoice#   Date                              Order#          Line#  Item#                            TX Qty      Cost
+ 605 > --------------------------------------------------------------------------------------------------------------------------------
+----              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ 606   
+ 607   
+>> Error: Unexpected `-------------------------------------------------------------' in continuation
+
 run_reportwriter.at-9078-reference:608.6-608.7:
  605   --------------------------------------------------------------------------------------------------------------------------------
  606   
@@ -9275,6 +9415,16 @@ run_reportwriter.at-9078-reference:665.7-665.11:
  667   
 >> Warning: Unexpected non-blank area A on continuation line
 
+run_reportwriter.at-9078-reference:665.11-665.72:
+ 662   Region:    NE
+ 663   Location:            1000431
+ 664   Invoice#   Date                              Order#          Line#  Item#                            TX Qty      Cost
+ 665 > --------------------------------------------------------------------------------------------------------------------------------
+----              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ 666   
+ 667   
+>> Error: Unexpected `-------------------------------------------------------------' in continuation
+
 run_reportwriter.at-9078-reference:668.6-668.7:
  665   --------------------------------------------------------------------------------------------------------------------------------
  666   
@@ -9335,6 +9485,16 @@ run_reportwriter.at-9078-reference:725.7-725.11:
  727   
 >> Warning: Unexpected non-blank area A on continuation line
 
+run_reportwriter.at-9078-reference:725.11-725.72:
+ 722   Region:    NE
+ 723   Location:            1000451
+ 724   Invoice#   Date                              Order#          Line#  Item#                            TX Qty      Cost
+ 725 > --------------------------------------------------------------------------------------------------------------------------------
+----              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ 726   
+ 727   
+>> Error: Unexpected `-------------------------------------------------------------' in continuation
+
 run_reportwriter.at-9078-reference:728.6-728.7:
  725   --------------------------------------------------------------------------------------------------------------------------------
  726   
@@ -9385,6 +9545,16 @@ run_reportwriter.at-9078-reference:785.7-785.11:
  787   
 >> Warning: Unexpected non-blank area A on continuation line
 
+run_reportwriter.at-9078-reference:785.11-785.72:
+ 782   Region:    NE
+ 783   Location:            1000471
+ 784   Invoice#   Date                              Order#          Line#  Item#                            TX Qty      Cost
+ 785 > --------------------------------------------------------------------------------------------------------------------------------
+----              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ 786   
+ 787   
+>> Error: Unexpected `-------------------------------------------------------------' in continuation
+
 run_reportwriter.at-9078-reference:788.6-788.7:
  785   --------------------------------------------------------------------------------------------------------------------------------
  786   
@@ -9435,6 +9605,16 @@ run_reportwriter.at-9078-reference:845.7-845.11:
  847   
 >> Warning: Unexpected non-blank area A on continuation line
 
+run_reportwriter.at-9078-reference:845.11-845.72:
+ 842   Region:    NE
+ 843   Location:            1000491
+ 844   Invoice#   Date                              Order#          Line#  Item#                            TX Qty      Cost
+ 845 > --------------------------------------------------------------------------------------------------------------------------------
+----              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ 846   
+ 847   
+>> Error: Unexpected `-------------------------------------------------------------' in continuation
+
 run_reportwriter.at-9078-reference:848.6-848.7:
  845   --------------------------------------------------------------------------------------------------------------------------------
  846   
@@ -9485,6 +9665,16 @@ run_reportwriter.at-9078-reference:905.7-905.11:
  907   
 >> Warning: Unexpected non-blank area A on continuation line
 
+run_reportwriter.at-9078-reference:905.11-905.72:
+ 902   Region:    NE
+ 903   Location:            1000601
+ 904   Invoice#   Date                              Order#          Line#  Item#                            TX Qty      Cost
+ 905 > --------------------------------------------------------------------------------------------------------------------------------
+----              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ 906   
+ 907   
+>> Error: Unexpected `-------------------------------------------------------------' in continuation
+
 run_reportwriter.at-9078-reference:908.6-908.7:
  905   --------------------------------------------------------------------------------------------------------------------------------
  906   
@@ -9535,6 +9725,16 @@ run_reportwriter.at-9078-reference:965.7-965.11:
  967   
 >> Warning: Unexpected non-blank area A on continuation line
 
+run_reportwriter.at-9078-reference:965.11-965.72:
+ 962   Region:    NE
+ 963   Location:            1000631
+ 964   Invoice#   Date                              Order#          Line#  Item#                            TX Qty      Cost
+ 965 > --------------------------------------------------------------------------------------------------------------------------------
+----              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ 966   
+ 967   
+>> Error: Unexpected `-------------------------------------------------------------' in continuation
+
 run_reportwriter.at-9078-reference:968.6-968.7:
  965   --------------------------------------------------------------------------------------------------------------------------------
  966   
@@ -9585,6 +9785,16 @@ run_reportwriter.at-9078-reference:1025.7-1025.11:
 1027   
 >> Warning: Unexpected non-blank area A on continuation line
 
+run_reportwriter.at-9078-reference:1025.11-1025.72:
+1022   Region:    NE
+1023   Location:            1000671
+1024   Invoice#   Date                              Order#          Line#  Item#                            TX Qty      Cost
+1025 > --------------------------------------------------------------------------------------------------------------------------------
+----              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+1026   
+1027   
+>> Error: Unexpected `-------------------------------------------------------------' in continuation
+
 run_reportwriter.at-9078-reference:1028.6-1028.7:
 1025   --------------------------------------------------------------------------------------------------------------------------------
 1026   
@@ -9635,6 +9845,16 @@ run_reportwriter.at-9078-reference:1085.7-1085.11:
 1087   
 >> Warning: Unexpected non-blank area A on continuation line
 
+run_reportwriter.at-9078-reference:1085.11-1085.72:
+1082   Region:    NE
+1083   Location:            1000811
+1084   Invoice#   Date                              Order#          Line#  Item#                            TX Qty      Cost
+1085 > --------------------------------------------------------------------------------------------------------------------------------
+----              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+1086   
+1087   
+>> Error: Unexpected `-------------------------------------------------------------' in continuation
+
 run_reportwriter.at-9078-reference:1088.6-1088.7:
 1085   --------------------------------------------------------------------------------------------------------------------------------
 1086   
@@ -9695,6 +9915,16 @@ run_reportwriter.at-9078-reference:1145.7-1145.11:
 1147   
 >> Warning: Unexpected non-blank area A on continuation line
 
+run_reportwriter.at-9078-reference:1145.11-1145.72:
+1142   Region:    NE
+1143   Location:            1000831
+1144   Invoice#   Date                              Order#          Line#  Item#                            TX Qty      Cost
+1145 > --------------------------------------------------------------------------------------------------------------------------------
+----              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+1146   
+1147   
+>> Error: Unexpected `-------------------------------------------------------------' in continuation
+
 run_reportwriter.at-9078-reference:1148.6-1148.7:
 1145   --------------------------------------------------------------------------------------------------------------------------------
 1146   
@@ -9745,6 +9975,16 @@ run_reportwriter.at-9078-reference:1205.7-1205.11:
 1207   
 >> Warning: Unexpected non-blank area A on continuation line
 
+run_reportwriter.at-9078-reference:1205.11-1205.72:
+1202   Region:    NW
+1203   Location:            1000001
+1204   Invoice#   Date                              Order#          Line#  Item#                            TX Qty      Cost
+1205 > --------------------------------------------------------------------------------------------------------------------------------
+----              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+1206   
+1207   
+>> Error: Unexpected `-------------------------------------------------------------' in continuation
+
 run_reportwriter.at-9078-reference:1208.6-1208.7:
 1205   --------------------------------------------------------------------------------------------------------------------------------
 1206   
@@ -9795,6 +10035,16 @@ run_reportwriter.at-9078-reference:1265.7-1265.11:
 1267   
 >> Warning: Unexpected non-blank area A on continuation line
 
+run_reportwriter.at-9078-reference:1265.11-1265.72:
+1262   Region:    NW
+1263   Location:            1000011
+1264   Invoice#   Date                              Order#          Line#  Item#                            TX Qty      Cost
+1265 > --------------------------------------------------------------------------------------------------------------------------------
+----              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+1266   
+1267   
+>> Error: Unexpected `-------------------------------------------------------------' in continuation
+
 run_reportwriter.at-9078-reference:1268.6-1268.7:
 1265   --------------------------------------------------------------------------------------------------------------------------------
 1266   
@@ -9845,6 +10095,16 @@ run_reportwriter.at-9078-reference:1325.7-1325.11:
 1327   
 >> Warning: Unexpected non-blank area A on continuation line
 
+run_reportwriter.at-9078-reference:1325.11-1325.72:
+1322   Region:    NW
+1323   Location:            1000051
+1324   Invoice#   Date                              Order#          Line#  Item#                            TX Qty      Cost
+1325 > --------------------------------------------------------------------------------------------------------------------------------
+----              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+1326   
+1327   
+>> Error: Unexpected `-------------------------------------------------------------' in continuation
+
 run_reportwriter.at-9078-reference:1328.6-1328.7:
 1325   --------------------------------------------------------------------------------------------------------------------------------
 1326   
@@ -9915,6 +10175,16 @@ run_reportwriter.at-9078-reference:1385.7-1385.11:
 1387   
 >> Warning: Unexpected non-blank area A on continuation line
 
+run_reportwriter.at-9078-reference:1385.11-1385.72:
+1382   Region:    NW
+1383   Location:            1000071
+1384   Invoice#   Date                              Order#          Line#  Item#                            TX Qty      Cost
+1385 > --------------------------------------------------------------------------------------------------------------------------------
+----              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+1386   
+1387   
+>> Error: Unexpected `-------------------------------------------------------------' in continuation
+
 run_reportwriter.at-9078-reference:1388.6-1388.7:
 1385   --------------------------------------------------------------------------------------------------------------------------------
 1386   
@@ -9965,6 +10235,16 @@ run_reportwriter.at-9078-reference:1445.7-1445.11:
 1447   
 >> Warning: Unexpected non-blank area A on continuation line
 
+run_reportwriter.at-9078-reference:1445.11-1445.72:
+1442   Region:    NW
+1443   Location:            1000091
+1444   Invoice#   Date                              Order#          Line#  Item#                            TX Qty      Cost
+1445 > --------------------------------------------------------------------------------------------------------------------------------
+----              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+1446   
+1447   
+>> Error: Unexpected `-------------------------------------------------------------' in continuation
+
 run_reportwriter.at-9078-reference:1448.6-1448.7:
 1445   --------------------------------------------------------------------------------------------------------------------------------
 1446   
@@ -10045,6 +10325,16 @@ run_reportwriter.at-9078-reference:1505.7-1505.11:
 1507   
 >> Warning: Unexpected non-blank area A on continuation line
 
+run_reportwriter.at-9078-reference:1505.11-1505.72:
+1502   Region:    NW
+1503   Location:            1000201
+1504   Invoice#   Date                              Order#          Line#  Item#                            TX Qty      Cost
+1505 > --------------------------------------------------------------------------------------------------------------------------------
+----              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+1506   
+1507   
+>> Error: Unexpected `-------------------------------------------------------------' in continuation
+
 run_reportwriter.at-9078-reference:1508.6-1508.7:
 1505   --------------------------------------------------------------------------------------------------------------------------------
 1506   
@@ -10095,6 +10385,16 @@ run_reportwriter.at-9078-reference:1565.7-1565.11:
 1567   
 >> Warning: Unexpected non-blank area A on continuation line
 
+run_reportwriter.at-9078-reference:1565.11-1565.72:
+1562   Region:    NW
+1563   Location:            1000231
+1564   Invoice#   Date                              Order#          Line#  Item#                            TX Qty      Cost
+1565 > --------------------------------------------------------------------------------------------------------------------------------
+----              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+1566   
+1567   
+>> Error: Unexpected `-------------------------------------------------------------' in continuation
+
 run_reportwriter.at-9078-reference:1568.6-1568.7:
 1565   --------------------------------------------------------------------------------------------------------------------------------
 1566   
@@ -10145,6 +10445,16 @@ run_reportwriter.at-9078-reference:1625.7-1625.11:
 1627   
 >> Warning: Unexpected non-blank area A on continuation line
 
+run_reportwriter.at-9078-reference:1625.11-1625.72:
+1622   Region:    NW
+1623   Location:            1000251
+1624   Invoice#   Date                              Order#          Line#  Item#                            TX Qty      Cost
+1625 > --------------------------------------------------------------------------------------------------------------------------------
+----              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+1626   
+1627   
+>> Error: Unexpected `-------------------------------------------------------------' in continuation
+
 run_reportwriter.at-9078-reference:1628.6-1628.7:
 1625   --------------------------------------------------------------------------------------------------------------------------------
 1626   
@@ -10195,6 +10505,16 @@ run_reportwriter.at-9078-reference:1685.7-1685.11:
 1687   
 >> Warning: Unexpected non-blank area A on continuation line
 
+run_reportwriter.at-9078-reference:1685.11-1685.72:
+1682   Region:    NW
+1683   Location:            1000401
+1684   Invoice#   Date                              Order#          Line#  Item#                            TX Qty      Cost
+1685 > --------------------------------------------------------------------------------------------------------------------------------
+----              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+1686   
+1687   
+>> Error: Unexpected `-------------------------------------------------------------' in continuation
+
 run_reportwriter.at-9078-reference:1688.6-1688.7:
 1685   --------------------------------------------------------------------------------------------------------------------------------
 1686   
@@ -10255,6 +10575,16 @@ run_reportwriter.at-9078-reference:1745.7-1745.11:
 1747   
 >> Warning: Unexpected non-blank area A on continuation line
 
+run_reportwriter.at-9078-reference:1745.11-1745.72:
+1742   Region:    NW
+1743   Location:            1000411
+1744   Invoice#   Date                              Order#          Line#  Item#                            TX Qty      Cost
+1745 > --------------------------------------------------------------------------------------------------------------------------------
+----              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+1746   
+1747   
+>> Error: Unexpected `-------------------------------------------------------------' in continuation
+
 run_reportwriter.at-9078-reference:1748.6-1748.7:
 1745   --------------------------------------------------------------------------------------------------------------------------------
 1746   
@@ -10315,6 +10645,16 @@ run_reportwriter.at-9078-reference:1805.7-1805.11:
 1807   
 >> Warning: Unexpected non-blank area A on continuation line
 
+run_reportwriter.at-9078-reference:1805.11-1805.72:
+1802   Region:    NW
+1803   Location:            1000491
+1804   Invoice#   Date                              Order#          Line#  Item#                            TX Qty      Cost
+1805 > --------------------------------------------------------------------------------------------------------------------------------
+----              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+1806   
+1807   
+>> Error: Unexpected `-------------------------------------------------------------' in continuation
+
 run_reportwriter.at-9078-reference:1808.6-1808.7:
 1805   --------------------------------------------------------------------------------------------------------------------------------
 1806   
@@ -10365,6 +10705,16 @@ run_reportwriter.at-9078-reference:1865.7-1865.11:
 1867   
 >> Warning: Unexpected non-blank area A on continuation line
 
+run_reportwriter.at-9078-reference:1865.11-1865.72:
+1862   Region:    NW
+1863   Location:            1000611
+1864   Invoice#   Date                              Order#          Line#  Item#                            TX Qty      Cost
+1865 > --------------------------------------------------------------------------------------------------------------------------------
+----              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+1866   
+1867   
+>> Error: Unexpected `-------------------------------------------------------------' in continuation
+
 run_reportwriter.at-9078-reference:1868.6-1868.7:
 1865   --------------------------------------------------------------------------------------------------------------------------------
 1866   
@@ -10415,6 +10765,16 @@ run_reportwriter.at-9078-reference:1925.7-1925.11:
 1927   
 >> Warning: Unexpected non-blank area A on continuation line
 
+run_reportwriter.at-9078-reference:1925.11-1925.72:
+1922   Region:    NW
+1923   Location:            1000631
+1924   Invoice#   Date                              Order#          Line#  Item#                            TX Qty      Cost
+1925 > --------------------------------------------------------------------------------------------------------------------------------
+----              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+1926   
+1927   
+>> Error: Unexpected `-------------------------------------------------------------' in continuation
+
 run_reportwriter.at-9078-reference:1928.6-1928.7:
 1925   --------------------------------------------------------------------------------------------------------------------------------
 1926   
@@ -10485,6 +10845,16 @@ run_reportwriter.at-9078-reference:1985.7-1985.11:
 1987   
 >> Warning: Unexpected non-blank area A on continuation line
 
+run_reportwriter.at-9078-reference:1985.11-1985.72:
+1982   Region:    NW
+1983   Location:            1000651
+1984   Invoice#   Date                              Order#          Line#  Item#                            TX Qty      Cost
+1985 > --------------------------------------------------------------------------------------------------------------------------------
+----              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+1986   
+1987   
+>> Error: Unexpected `-------------------------------------------------------------' in continuation
+
 run_reportwriter.at-9078-reference:1988.6-1988.7:
 1985   --------------------------------------------------------------------------------------------------------------------------------
 1986   
@@ -10535,6 +10905,16 @@ run_reportwriter.at-9078-reference:2045.7-2045.11:
 2047   
 >> Warning: Unexpected non-blank area A on continuation line
 
+run_reportwriter.at-9078-reference:2045.11-2045.72:
+2042   Region:    NW
+2043   Location:            1000671
+2044   Invoice#   Date                              Order#          Line#  Item#                            TX Qty      Cost
+2045 > --------------------------------------------------------------------------------------------------------------------------------
+----              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+2046   
+2047   
+>> Error: Unexpected `-------------------------------------------------------------' in continuation
+
 run_reportwriter.at-9078-reference:2048.6-2048.7:
 2045   --------------------------------------------------------------------------------------------------------------------------------
 2046   
@@ -10585,6 +10965,16 @@ run_reportwriter.at-9078-reference:2105.7-2105.11:
 2107   
 >> Warning: Unexpected non-blank area A on continuation line
 
+run_reportwriter.at-9078-reference:2105.11-2105.72:
+2102   Region:    NW
+2103   Location:            1000691
+2104   Invoice#   Date                              Order#          Line#  Item#                            TX Qty      Cost
+2105 > --------------------------------------------------------------------------------------------------------------------------------
+----              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+2106   
+2107   
+>> Error: Unexpected `-------------------------------------------------------------' in continuation
+
 run_reportwriter.at-9078-reference:2108.6-2108.7:
 2105   --------------------------------------------------------------------------------------------------------------------------------
 2106   
@@ -10635,6 +11025,16 @@ run_reportwriter.at-9078-reference:2165.7-2165.11:
 2167   
 >> Warning: Unexpected non-blank area A on continuation line
 
+run_reportwriter.at-9078-reference:2165.11-2165.72:
+2162   Region:    NW
+2163   Location:            1000811
+2164   Invoice#   Date                              Order#          Line#  Item#                            TX Qty      Cost
+2165 > --------------------------------------------------------------------------------------------------------------------------------
+----              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+2166   
+2167   
+>> Error: Unexpected `-------------------------------------------------------------' in continuation
+
 run_reportwriter.at-9078-reference:2168.6-2168.7:
 2165   --------------------------------------------------------------------------------------------------------------------------------
 2166   
@@ -10685,6 +11085,16 @@ run_reportwriter.at-9078-reference:2225.7-2225.11:
 2227   
 >> Warning: Unexpected non-blank area A on continuation line
 
+run_reportwriter.at-9078-reference:2225.11-2225.72:
+2222   Region:    NW
+2223   Location:            1000851
+2224   Invoice#   Date                              Order#          Line#  Item#                            TX Qty      Cost
+2225 > --------------------------------------------------------------------------------------------------------------------------------
+----              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+2226   
+2227   
+>> Error: Unexpected `-------------------------------------------------------------' in continuation
+
 run_reportwriter.at-9078-reference:2228.6-2228.7:
 2225   --------------------------------------------------------------------------------------------------------------------------------
 2226   
@@ -10735,6 +11145,16 @@ run_reportwriter.at-9078-reference:2285.7-2285.11:
 2287   
 >> Warning: Unexpected non-blank area A on continuation line
 
+run_reportwriter.at-9078-reference:2285.11-2285.72:
+2282   Region:    NW
+2283   Location:            1000871
+2284   Invoice#   Date                              Order#          Line#  Item#                            TX Qty      Cost
+2285 > --------------------------------------------------------------------------------------------------------------------------------
+----              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+2286   
+2287   
+>> Error: Unexpected `-------------------------------------------------------------' in continuation
+
 run_reportwriter.at-9078-reference:2288.6-2288.7:
 2285   --------------------------------------------------------------------------------------------------------------------------------
 2286   
@@ -10795,6 +11215,16 @@ run_reportwriter.at-9078-reference:2345.7-2345.11:
 2347   
 >> Warning: Unexpected non-blank area A on continuation line
 
+run_reportwriter.at-9078-reference:2345.11-2345.72:
+2342   Region:    NW
+2343   Location:            1000891
+2344   Invoice#   Date                              Order#          Line#  Item#                            TX Qty      Cost
+2345 > --------------------------------------------------------------------------------------------------------------------------------
+----              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+2346   
+2347   
+>> Error: Unexpected `-------------------------------------------------------------' in continuation
+
 run_reportwriter.at-9078-reference:2348.6-2348.7:
 2345   --------------------------------------------------------------------------------------------------------------------------------
 2346   
@@ -10845,6 +11275,16 @@ run_reportwriter.at-9078-reference:2405.7-2405.11:
 2407   
 >> Warning: Unexpected non-blank area A on continuation line
 
+run_reportwriter.at-9078-reference:2405.11-2405.72:
+2402   Region:    SE
+2403   Location:            1000001
+2404   Invoice#   Date                              Order#          Line#  Item#                            TX Qty      Cost
+2405 > --------------------------------------------------------------------------------------------------------------------------------
+----              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+2406   
+2407   
+>> Error: Unexpected `-------------------------------------------------------------' in continuation
+
 run_reportwriter.at-9078-reference:2408.6-2408.7:
 2405   --------------------------------------------------------------------------------------------------------------------------------
 2406   
@@ -10895,6 +11335,16 @@ run_reportwriter.at-9078-reference:2465.7-2465.11:
 2467   
 >> Warning: Unexpected non-blank area A on continuation line
 
+run_reportwriter.at-9078-reference:2465.11-2465.72:
+2462   Region:    SE
+2463   Location:            1000011
+2464   Invoice#   Date                              Order#          Line#  Item#                            TX Qty      Cost
+2465 > --------------------------------------------------------------------------------------------------------------------------------
+----              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+2466   
+2467   
+>> Error: Unexpected `-------------------------------------------------------------' in continuation
+
 run_reportwriter.at-9078-reference:2468.6-2468.7:
 2465   --------------------------------------------------------------------------------------------------------------------------------
 2466   
@@ -10955,6 +11405,16 @@ run_reportwriter.at-9078-reference:2525.7-2525.11:
 2527   
 >> Warning: Unexpected non-blank area A on continuation line
 
+run_reportwriter.at-9078-reference:2525.11-2525.72:
+2522   Region:    SE
+2523   Location:            1000091
+2524   Invoice#   Date                              Order#          Line#  Item#                            TX Qty      Cost
+2525 > --------------------------------------------------------------------------------------------------------------------------------
+----              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+2526   
+2527   
+>> Error: Unexpected `-------------------------------------------------------------' in continuation
+
 run_reportwriter.at-9078-reference:2528.6-2528.7:
 2525   --------------------------------------------------------------------------------------------------------------------------------
 2526   
@@ -11025,6 +11485,16 @@ run_reportwriter.at-9078-reference:2585.7-2585.11:
 2587   
 >> Warning: Unexpected non-blank area A on continuation line
 
+run_reportwriter.at-9078-reference:2585.11-2585.72:
+2582   Region:    SE
+2583   Location:            1000211
+2584   Invoice#   Date                              Order#          Line#  Item#                            TX Qty      Cost
+2585 > --------------------------------------------------------------------------------------------------------------------------------
+----              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+2586   
+2587   
+>> Error: Unexpected `-------------------------------------------------------------' in continuation
+
 run_reportwriter.at-9078-reference:2588.6-2588.7:
 2585   --------------------------------------------------------------------------------------------------------------------------------
 2586   
@@ -11075,6 +11545,16 @@ run_reportwriter.at-9078-reference:2645.7-2645.11:
 2647   
 >> Warning: Unexpected non-blank area A on continuation line
 
+run_reportwriter.at-9078-reference:2645.11-2645.72:
+2642   Region:    SE
+2643   Location:            1000411
+2644   Invoice#   Date                              Order#          Line#  Item#                            TX Qty      Cost
+2645 > --------------------------------------------------------------------------------------------------------------------------------
+----              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+2646   
+2647   
+>> Error: Unexpected `-------------------------------------------------------------' in continuation
+
 run_reportwriter.at-9078-reference:2648.6-2648.7:
 2645   --------------------------------------------------------------------------------------------------------------------------------
 2646   
@@ -11125,6 +11605,16 @@ run_reportwriter.at-9078-reference:2705.7-2705.11:
 2707   
 >> Warning: Unexpected non-blank area A on continuation line
 
+run_reportwriter.at-9078-reference:2705.11-2705.72:
+2702   Region:    SE
+2703   Location:            1000431
+2704   Invoice#   Date                              Order#          Line#  Item#                            TX Qty      Cost
+2705 > --------------------------------------------------------------------------------------------------------------------------------
+----              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+2706   
+2707   
+>> Error: Unexpected `-------------------------------------------------------------' in continuation
+
 run_reportwriter.at-9078-reference:2708.6-2708.7:
 2705   --------------------------------------------------------------------------------------------------------------------------------
 2706   
@@ -11185,6 +11675,16 @@ run_reportwriter.at-9078-reference:2765.7-2765.11:
 2767   
 >> Warning: Unexpected non-blank area A on continuation line
 
+run_reportwriter.at-9078-reference:2765.11-2765.72:
+2762   Region:    SE
+2763   Location:            1000451
+2764   Invoice#   Date                              Order#          Line#  Item#                            TX Qty      Cost
+2765 > --------------------------------------------------------------------------------------------------------------------------------
+----              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+2766   
+2767   
+>> Error: Unexpected `-------------------------------------------------------------' in continuation
+
 run_reportwriter.at-9078-reference:2768.6-2768.7:
 2765   --------------------------------------------------------------------------------------------------------------------------------
 2766   
@@ -11235,6 +11735,16 @@ run_reportwriter.at-9078-reference:2825.7-2825.11:
 2827   
 >> Warning: Unexpected non-blank area A on continuation line
 
+run_reportwriter.at-9078-reference:2825.11-2825.72:
+2822   Region:    SE
+2823   Location:            1000471
+2824   Invoice#   Date                              Order#          Line#  Item#                            TX Qty      Cost
+2825 > --------------------------------------------------------------------------------------------------------------------------------
+----              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+2826   
+2827   
+>> Error: Unexpected `-------------------------------------------------------------' in continuation
+
 run_reportwriter.at-9078-reference:2828.6-2828.7:
 2825   --------------------------------------------------------------------------------------------------------------------------------
 2826   
@@ -11295,6 +11805,16 @@ run_reportwriter.at-9078-reference:2885.7-2885.11:
 2887   
 >> Warning: Unexpected non-blank area A on continuation line
 
+run_reportwriter.at-9078-reference:2885.11-2885.72:
+2882   Region:    SE
+2883   Location:            1000491
+2884   Invoice#   Date                              Order#          Line#  Item#                            TX Qty      Cost
+2885 > --------------------------------------------------------------------------------------------------------------------------------
+----              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+2886   
+2887   
+>> Error: Unexpected `-------------------------------------------------------------' in continuation
+
 run_reportwriter.at-9078-reference:2888.6-2888.7:
 2885   --------------------------------------------------------------------------------------------------------------------------------
 2886   
@@ -11345,6 +11865,16 @@ run_reportwriter.at-9078-reference:2945.7-2945.11:
 2947   
 >> Warning: Unexpected non-blank area A on continuation line
 
+run_reportwriter.at-9078-reference:2945.11-2945.72:
+2942   Region:    SE
+2943   Location:            1000601
+2944   Invoice#   Date                              Order#          Line#  Item#                            TX Qty      Cost
+2945 > --------------------------------------------------------------------------------------------------------------------------------
+----              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+2946   
+2947   
+>> Error: Unexpected `-------------------------------------------------------------' in continuation
+
 run_reportwriter.at-9078-reference:2948.6-2948.7:
 2945   --------------------------------------------------------------------------------------------------------------------------------
 2946   
@@ -11395,6 +11925,16 @@ run_reportwriter.at-9078-reference:3005.7-3005.11:
 3007   
 >> Warning: Unexpected non-blank area A on continuation line
 
+run_reportwriter.at-9078-reference:3005.11-3005.72:
+3002   Region:    SE
+3003   Location:            1000631
+3004   Invoice#   Date                              Order#          Line#  Item#                            TX Qty      Cost
+3005 > --------------------------------------------------------------------------------------------------------------------------------
+----              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+3006   
+3007   
+>> Error: Unexpected `-------------------------------------------------------------' in continuation
+
 run_reportwriter.at-9078-reference:3008.6-3008.7:
 3005   --------------------------------------------------------------------------------------------------------------------------------
 3006   
@@ -11445,6 +11985,16 @@ run_reportwriter.at-9078-reference:3065.7-3065.11:
 3067   
 >> Warning: Unexpected non-blank area A on continuation line
 
+run_reportwriter.at-9078-reference:3065.11-3065.72:
+3062   Region:    SE
+3063   Location:            1000671
+3064   Invoice#   Date                              Order#          Line#  Item#                            TX Qty      Cost
+3065 > --------------------------------------------------------------------------------------------------------------------------------
+----              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+3066   
+3067   
+>> Error: Unexpected `-------------------------------------------------------------' in continuation
+
 run_reportwriter.at-9078-reference:3068.6-3068.7:
 3065   --------------------------------------------------------------------------------------------------------------------------------
 3066   
@@ -11505,6 +12055,16 @@ run_reportwriter.at-9078-reference:3125.7-3125.11:
 3127   
 >> Warning: Unexpected non-blank area A on continuation line
 
+run_reportwriter.at-9078-reference:3125.11-3125.72:
+3122   Region:    SE
+3123   Location:            1000891
+3124   Invoice#   Date                              Order#          Line#  Item#                            TX Qty      Cost
+3125 > --------------------------------------------------------------------------------------------------------------------------------
+----              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+3126   
+3127   
+>> Error: Unexpected `-------------------------------------------------------------' in continuation
+
 run_reportwriter.at-9078-reference:3128.6-3128.7:
 3125   --------------------------------------------------------------------------------------------------------------------------------
 3126   
@@ -11555,6 +12115,16 @@ run_reportwriter.at-9078-reference:3185.7-3185.11:
 3187   
 >> Warning: Unexpected non-blank area A on continuation line
 
+run_reportwriter.at-9078-reference:3185.11-3185.72:
+3182   Region:    SW
+3183   Location:            1000011
+3184   Invoice#   Date                              Order#          Line#  Item#                            TX Qty      Cost
+3185 > --------------------------------------------------------------------------------------------------------------------------------
+----              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+3186   
+3187   
+>> Error: Unexpected `-------------------------------------------------------------' in continuation
+
 run_reportwriter.at-9078-reference:3188.6-3188.7:
 3185   --------------------------------------------------------------------------------------------------------------------------------
 3186   
@@ -11605,6 +12175,16 @@ run_reportwriter.at-9078-reference:3245.7-3245.11:
 3247   
 >> Warning: Unexpected non-blank area A on continuation line
 
+run_reportwriter.at-9078-reference:3245.11-3245.72:
+3242   Region:    SW
+3243   Location:            1000031
+3244   Invoice#   Date                              Order#          Line#  Item#                            TX Qty      Cost
+3245 > --------------------------------------------------------------------------------------------------------------------------------
+----              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+3246   
+3247   
+>> Error: Unexpected `-------------------------------------------------------------' in continuation
+
 run_reportwriter.at-9078-reference:3248.6-3248.7:
 3245   --------------------------------------------------------------------------------------------------------------------------------
 3246   
@@ -11665,6 +12245,16 @@ run_reportwriter.at-9078-reference:3305.7-3305.11:
 3307   
 >> Warning: Unexpected non-blank area A on continuation line
 
+run_reportwriter.at-9078-reference:3305.11-3305.72:
+3302   Region:    SW
+3303   Location:            1000091
+3304   Invoice#   Date                              Order#          Line#  Item#                            TX Qty      Cost
+3305 > --------------------------------------------------------------------------------------------------------------------------------
+----              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+3306   
+3307   
+>> Error: Unexpected `-------------------------------------------------------------' in continuation
+
 run_reportwriter.at-9078-reference:3308.6-3308.7:
 3305   --------------------------------------------------------------------------------------------------------------------------------
 3306   
@@ -11715,6 +12305,16 @@ run_reportwriter.at-9078-reference:3365.7-3365.11:
 3367   
 >> Warning: Unexpected non-blank area A on continuation line
 
+run_reportwriter.at-9078-reference:3365.11-3365.72:
+3362   Region:    SW
+3363   Location:            1000201
+3364   Invoice#   Date                              Order#          Line#  Item#                            TX Qty      Cost
+3365 > --------------------------------------------------------------------------------------------------------------------------------
+----              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+3366   
+3367   
+>> Error: Unexpected `-------------------------------------------------------------' in continuation
+
 run_reportwriter.at-9078-reference:3368.6-3368.7:
 3365   --------------------------------------------------------------------------------------------------------------------------------
 3366   
@@ -11775,6 +12375,16 @@ run_reportwriter.at-9078-reference:3425.7-3425.11:
 3427   
 >> Warning: Unexpected non-blank area A on continuation line
 
+run_reportwriter.at-9078-reference:3425.11-3425.72:
+3422   Region:    SW
+3423   Location:            1000211
+3424   Invoice#   Date                              Order#          Line#  Item#                            TX Qty      Cost
+3425 > --------------------------------------------------------------------------------------------------------------------------------
+----              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+3426   
+3427   
+>> Error: Unexpected `-------------------------------------------------------------' in continuation
+
 run_reportwriter.at-9078-reference:3428.6-3428.7:
 3425   --------------------------------------------------------------------------------------------------------------------------------
 3426   
@@ -11835,6 +12445,16 @@ run_reportwriter.at-9078-reference:3485.7-3485.11:
 3487   
 >> Warning: Unexpected non-blank area A on continuation line
 
+run_reportwriter.at-9078-reference:3485.11-3485.72:
+3482   Region:    SW
+3483   Location:            1000271
+3484   Invoice#   Date                              Order#          Line#  Item#                            TX Qty      Cost
+3485 > --------------------------------------------------------------------------------------------------------------------------------
+----              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+3486   
+3487   
+>> Error: Unexpected `-------------------------------------------------------------' in continuation
+
 run_reportwriter.at-9078-reference:3488.6-3488.7:
 3485   --------------------------------------------------------------------------------------------------------------------------------
 3486   
@@ -11895,6 +12515,16 @@ run_reportwriter.at-9078-reference:3545.7-3545.11:
 3547   
 >> Warning: Unexpected non-blank area A on continuation line
 
+run_reportwriter.at-9078-reference:3545.11-3545.72:
+3542   Region:    SW
+3543   Location:            1000401
+3544   Invoice#   Date                              Order#          Line#  Item#                            TX Qty      Cost
+3545 > --------------------------------------------------------------------------------------------------------------------------------
+----              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+3546   
+3547   
+>> Error: Unexpected `-------------------------------------------------------------' in continuation
+
 run_reportwriter.at-9078-reference:3548.6-3548.7:
 3545   --------------------------------------------------------------------------------------------------------------------------------
 3546   
@@ -11945,6 +12575,16 @@ run_reportwriter.at-9078-reference:3605.7-3605.11:
 3607   
 >> Warning: Unexpected non-blank area A on continuation line
 
+run_reportwriter.at-9078-reference:3605.11-3605.72:
+3602   Region:    SW
+3603   Location:            1000411
+3604   Invoice#   Date                              Order#          Line#  Item#                            TX Qty      Cost
+3605 > --------------------------------------------------------------------------------------------------------------------------------
+----              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+3606   
+3607   
+>> Error: Unexpected `-------------------------------------------------------------' in continuation
+
 run_reportwriter.at-9078-reference:3608.6-3608.7:
 3605   --------------------------------------------------------------------------------------------------------------------------------
 3606   
@@ -11995,6 +12635,16 @@ run_reportwriter.at-9078-reference:3665.7-3665.11:
 3667   
 >> Warning: Unexpected non-blank area A on continuation line
 
+run_reportwriter.at-9078-reference:3665.11-3665.72:
+3662   Region:    SW
+3663   Location:            1000431
+3664   Invoice#   Date                              Order#          Line#  Item#                            TX Qty      Cost
+3665 > --------------------------------------------------------------------------------------------------------------------------------
+----              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+3666   
+3667   
+>> Error: Unexpected `-------------------------------------------------------------' in continuation
+
 run_reportwriter.at-9078-reference:3668.6-3668.7:
 3665   --------------------------------------------------------------------------------------------------------------------------------
 3666   
@@ -12055,6 +12705,16 @@ run_reportwriter.at-9078-reference:3725.7-3725.11:
 3727   
 >> Warning: Unexpected non-blank area A on continuation line
 
+run_reportwriter.at-9078-reference:3725.11-3725.72:
+3722   Region:    SW
+3723   Location:            1000601
+3724   Invoice#   Date                              Order#          Line#  Item#                            TX Qty      Cost
+3725 > --------------------------------------------------------------------------------------------------------------------------------
+----              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+3726   
+3727   
+>> Error: Unexpected `-------------------------------------------------------------' in continuation
+
 run_reportwriter.at-9078-reference:3728.6-3728.7:
 3725   --------------------------------------------------------------------------------------------------------------------------------
 3726   
@@ -12105,6 +12765,16 @@ run_reportwriter.at-9078-reference:3785.7-3785.11:
 3787   
 >> Warning: Unexpected non-blank area A on continuation line
 
+run_reportwriter.at-9078-reference:3785.11-3785.72:
+3782   Region:    SW
+3783   Location:            1000611
+3784   Invoice#   Date                              Order#          Line#  Item#                            TX Qty      Cost
+3785 > --------------------------------------------------------------------------------------------------------------------------------
+----              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+3786   
+3787   
+>> Error: Unexpected `-------------------------------------------------------------' in continuation
+
 run_reportwriter.at-9078-reference:3788.6-3788.7:
 3785   --------------------------------------------------------------------------------------------------------------------------------
 3786   
@@ -12155,6 +12825,16 @@ run_reportwriter.at-9078-reference:3845.7-3845.11:
 3847   
 >> Warning: Unexpected non-blank area A on continuation line
 
+run_reportwriter.at-9078-reference:3845.11-3845.72:
+3842   Region:    SW
+3843   Location:            1000651
+3844   Invoice#   Date                              Order#          Line#  Item#                            TX Qty      Cost
+3845 > --------------------------------------------------------------------------------------------------------------------------------
+----              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+3846   
+3847   
+>> Error: Unexpected `-------------------------------------------------------------' in continuation
+
 run_reportwriter.at-9078-reference:3848.6-3848.7:
 3845   --------------------------------------------------------------------------------------------------------------------------------
 3846   
@@ -12205,6 +12885,16 @@ run_reportwriter.at-9078-reference:3905.7-3905.11:
 3907   
 >> Warning: Unexpected non-blank area A on continuation line
 
+run_reportwriter.at-9078-reference:3905.11-3905.72:
+3902   Region:    SW
+3903   Location:            1000831
+3904   Invoice#   Date                              Order#          Line#  Item#                            TX Qty      Cost
+3905 > --------------------------------------------------------------------------------------------------------------------------------
+----              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+3906   
+3907   
+>> Error: Unexpected `-------------------------------------------------------------' in continuation
+
 run_reportwriter.at-9078-reference:3908.6-3908.7:
 3905   --------------------------------------------------------------------------------------------------------------------------------
 3906   
@@ -12275,6 +12965,16 @@ run_reportwriter.at-9078-reference:3965.7-3965.11:
 3967   
 >> Warning: Unexpected non-blank area A on continuation line
 
+run_reportwriter.at-9078-reference:3965.11-3965.72:
+3962   Region:    SW
+3963   Location:            1000871
+3964   Invoice#   Date                              Order#          Line#  Item#                            TX Qty      Cost
+3965 > --------------------------------------------------------------------------------------------------------------------------------
+----              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+3966   
+3967   
+>> Error: Unexpected `-------------------------------------------------------------' in continuation
+
 run_reportwriter.at-9078-reference:3968.6-3968.7:
 3965   --------------------------------------------------------------------------------------------------------------------------------
 3966   
diff --git a/test/output-tests/syn_misc.expected b/test/output-tests/syn_misc.expected
index a06e7a2e9..bb03b4ea5 100644
--- a/test/output-tests/syn_misc.expected
+++ b/test/output-tests/syn_misc.expected
@@ -1206,6 +1206,14 @@ syn_misc.at-1903-prog.cob:8.0:
 >> Warning: Invalid syntax
 
 Considering: import/gnucobol/tests/testsuite.src/syn_misc.at:1936:0
+syn_misc.at-1936-prog.cob:6.11-6.15:
+   3          PROGRAM-ID.      prog.
+   4          PROCEDURE        DIVISION.
+   5              GO
+   6 >       -    BACK.
+----              ^^^^
+>> Error: Unexpected `BACK' in continuation
+
 Considering: import/gnucobol/tests/testsuite.src/syn_misc.at:2005:0
 Considering: import/gnucobol/tests/testsuite.src/syn_misc.at:2045:0
 syn_misc.at-2045-prog2.cob:11.7-11.46:
@@ -3552,15 +3560,15 @@ syn_misc.at-7027-prog.cob:6.7-6.24:
    8          >> DISPLAY "NOT OK (not both definitions)"
 >> Error: Malformed or unknown compiler directive
 
-syn_misc.at-7027-prog.cob:8.7-8.17:
+syn_misc.at-7027-prog.cob:8.7-8.49:
    5          >>IF A IS DEFINED
    6          >>IF B IS DEFINED
    7              CONTINUE
    8 >        >> DISPLAY "NOT OK (not both definitions)"
-----          ^^^^^^^^^^
+----          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    9              .
   10          >>ELSE
->> Error: Invalid syntax
+>> Error: Malformed or unknown compiler directive
 
 syn_misc.at-7027-prog.cob:10.7-10.13:
    7              CONTINUE
@@ -3572,15 +3580,15 @@ syn_misc.at-7027-prog.cob:10.7-10.13:
   12          >> DISPLAY "NOT OK (no definitions)"
 >> Error: Malformed or unknown compiler directive
 
-syn_misc.at-7027-prog.cob:12.7-12.17:
+syn_misc.at-7027-prog.cob:12.7-12.43:
    9              .
   10          >>ELSE
   11              CONTINUE
   12 >        >> DISPLAY "NOT OK (no definitions)"
-----          ^^^^^^^^^^
+----          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   13              .
   14          >>END-IF
->> Error: Invalid syntax
+>> Error: Malformed or unknown compiler directive
 
 syn_misc.at-7027-prog.cob:14.7-14.15:
   11              CONTINUE
@@ -3602,15 +3610,15 @@ syn_misc.at-7027-prog.cob:15.7-15.13:
   17          >> DISPLAY "OK"
 >> Error: Malformed or unknown compiler directive
 
-syn_misc.at-7027-prog.cob:17.7-17.17:
+syn_misc.at-7027-prog.cob:17.7-17.22:
   14          >>END-IF
   15          >>ELSE
   16              CONTINUE
   17 >        >> DISPLAY "OK"
-----          ^^^^^^^^^^
+----          ^^^^^^^^^^^^^^^
   18              .
   19          >>END-IF
->> Error: Invalid syntax
+>> Error: Malformed or unknown compiler directive
 
 syn_misc.at-7027-prog.cob:19.7-19.15:
   16              CONTINUE

From ee78b32be53dd19a9468392eebcaa55586d3102c Mon Sep 17 00:00:00 2001
From: Nicolas Berthier <nicolas.berthier@ocamlpro.com>
Date: Fri, 15 Sep 2023 16:25:21 +0200
Subject: [PATCH 03/17] Refactor `Cobol_lsp.Lsp_semtoks` (renamed from
 `Lsp_semantic`)

---
 src/lsp/cobol_lsp/lsp_request.ml              |  27 +-
 .../{lsp_semantic.ml => lsp_semtoks.ml}       | 256 +++++++++---------
 src/lsp/cobol_lsp/lsp_semtoks.mli             |  20 ++
 3 files changed, 163 insertions(+), 140 deletions(-)
 rename src/lsp/cobol_lsp/{lsp_semantic.ml => lsp_semtoks.ml} (81%)
 create mode 100644 src/lsp/cobol_lsp/lsp_semtoks.mli

diff --git a/src/lsp/cobol_lsp/lsp_request.ml b/src/lsp/cobol_lsp/lsp_request.ml
index 4cedd22ba..35ffd2080 100644
--- a/src/lsp/cobol_lsp/lsp_request.ml
+++ b/src/lsp/cobol_lsp/lsp_request.ml
@@ -64,19 +64,20 @@ let make_capabilities _ =
     TextDocumentSyncOptions.create ()
       ~openClose:true
       ~change:Incremental
-  in
-  let semantic =
-    let full = SemanticTokensOptions.create_full ~delta:false () in
-    let legend = SemanticTokensLegend.create
-        ~tokenTypes:Lsp_semantic.tokens_types
-        ~tokenModifiers:Lsp_semantic.tokens_modifiers
+  and semantic =
+    let legend =
+      SemanticTokensLegend.create
+        ~tokenTypes:Lsp_semtoks.token_types
+        ~tokenModifiers:Lsp_semtoks.token_modifiers
     in
     SemanticTokensOptions.create ()
-      ~full:(`Full full) ~legend
+      ~full:(`Full (SemanticTokensOptions.create_full ~delta:false ()))
+      ~legend
+  and hover =
+    HoverOptions.create ()
+  and completion_option =
+    CompletionOptions.create ()
   in
-  let hover = HoverOptions.create () in
-  let completion_option = CompletionOptions.create () in
-
   ServerCapabilities.create ()
     ~textDocumentSync:(`TextDocumentSyncOptions sync)
     ~definitionProvider:(`Bool true)
@@ -227,7 +228,7 @@ let handle_semantic_tokens_full registry (params: SemanticTokensParams.t) =
   try_with_document_data registry params.textDocument
     ~f:begin fun ~project:_ ~textdoc:_ ~pplog:_ ~tokens Lsp_document.{ ast; _ } ->
       let filename = Lsp.Uri.to_path params.textDocument.uri in
-      let data = Lsp_semantic.data ~filename (Lazy.force tokens) ast in
+      let data = Lsp_semtoks.data ~filename (Lazy.force tokens) ast in
       Some (SemanticTokens.create ~data ())
     end
 
@@ -301,8 +302,8 @@ let on_request
     | TextDocumentFormatting params ->
         begin try Ok (handle_formatting registry params, state)
         with Failure msg -> Error (FormattingError msg) end
-    | SemanticTokensFull semantic_params ->
-        Ok (handle_semantic_tokens_full registry semantic_params, state)
+    | SemanticTokensFull params ->
+        Ok (handle_semantic_tokens_full registry params, state)
     | TextDocumentHover hover_params ->
         Ok (handle_hover registry hover_params, state)
     | TextDocumentCompletion completion_params ->
diff --git a/src/lsp/cobol_lsp/lsp_semantic.ml b/src/lsp/cobol_lsp/lsp_semtoks.ml
similarity index 81%
rename from src/lsp/cobol_lsp/lsp_semantic.ml
rename to src/lsp/cobol_lsp/lsp_semtoks.ml
index 37f1c4ba9..d952aee8e 100644
--- a/src/lsp/cobol_lsp/lsp_semantic.ml
+++ b/src/lsp/cobol_lsp/lsp_semtoks.ml
@@ -15,27 +15,28 @@ open Cobol_common                                          (* Srcloc, Visitor *)
 open Cobol_common.Srcloc.INFIX
 open Cobol_parser.Grammar_tokens
 
-type semantic_token = {
-  line: int;
-  start: int;
-  length: int;
-  token_type: string;
-  token_modifiers: string list;
-}
-
-let tokens_types = [
-  "type";
-  "operator";
-  "variable";
-  "function";
-  "parameter";
-  "keyword";
-  "string";
-  "number";
-  "namespace";
-  "decorator";
-  "modifier";
-  "comment";
+module TOKTYP = struct
+  type t = { index: int; name: string }
+  let all: t list ref = ref []
+  let mk: string -> t =
+    let idx = ref 0 in
+    fun name ->
+      let res = { index = !idx; name } in
+      incr idx;
+      all := res :: !all;
+      res
+  let type_     = mk "type"
+  let operator  = mk "operator"
+  let variable  = mk "variable"
+  let function_ = mk "function"
+  let parameter = mk "parameter"
+  let keyword   = mk "keyword"
+  let string    = mk "string"
+  let number    = mk "number"
+  let namespace = mk "namespace"
+  let decorator = mk "decorator"
+  (* let modifier  = mk "modifier" *)
+  (* let comment   = mk "comment" *)
   (* "class"; *)
   (* "enum"; *)
   (* "interface"; *)
@@ -47,29 +48,63 @@ let tokens_types = [
   (* "method"; *)
   (* "macro"; *)
   (* "regexp"; *)
-]
-
-let tokens_modifiers = [
-  "declaration";
-  "definition";
-  "readonly";
-  "modification";
-  "defaultLibrary";
-(*"static";
-  "deprecated";
-  "abstract";
-  "async";
-  "documentation";*)
-]
-
-let semantic_token lexloc token_type token_modifiers =
+  let all =
+    List.sort (fun a b -> b.index - a.index) !all |>
+    List.rev_map (fun a -> a.name)
+end
+
+module TOKMOD = struct
+  type t = { mask: int; name: string }
+  let all: t list ref = ref []
+  let mk: string -> t =
+    let mask = ref 0b1 in
+    fun name ->
+      let res = { mask = !mask; name } in
+      mask := !mask lsl 1;
+      all := res :: !all;
+      res
+  let declaration    = mk "declaration"
+  let definition     = mk "definition"
+  let readonly       = mk "readonly"
+  let modification   = mk "modification"
+  let defaultLibrary = mk "defaultLibrary"
+  (*"static";
+    "deprecated";
+    "abstract";
+    "async";
+    "documentation";*)
+  let all =
+    List.sort (fun a b -> b.mask - a.mask) !all |>
+    List.rev_map (fun a -> a.name)
+  type set = { flags: int }
+  let none = { flags = 0b0 }
+  let one { mask; _ } = { flags = mask }
+  let union: t list -> set =
+    List.fold_left (fun set m -> { flags = set.flags lor m.mask }) none
+end
+
+type token_type = TOKTYP.t
+type token_modifiers = TOKMOD.set
+
+let token_types = TOKTYP.all
+let token_modifiers = TOKMOD.all
+
+type semtok = {
+  line: int;
+  start: int;
+  length: int;
+  toktyp: token_type;
+  tokmods: token_modifiers;
+}
+
+let semtok lexloc ?(tokmods = TOKMOD.none) toktyp =
   let range = Lsp_position.range_of_lexloc lexloc in
   let line = range.start.line in
   let start = range.start.character in
   let length = range.end_.character - start in
-  { line; start; length; token_type; token_modifiers }
+  { line; start; length; toktyp; tokmods }
 
-type token_type =
+type token_category =
   | ProgramName
   | ParagraphName
   | ProcName
@@ -89,53 +124,53 @@ let semantic_visitor ~filename =
   let open Cobol_ast.Operands_visitor in
   let open Cobol_common.Visitor in
 
-  let semantic_token_of lexloc token_type =
-    let semantic_token_of lexloc (token_type, token_modifiers) =
-      semantic_token lexloc token_type token_modifiers
+  let semtok_of lexloc category =
+    let semtok_of lexloc (toktyp, tokmods) =
+      semtok lexloc toktyp ~tokmods
     in
-    semantic_token_of lexloc @@ match token_type with
-      | ProgramName -> "string", ["definition"; "readonly"]
-      | ParagraphName -> "function", ["definition"]
-      | ProcName -> "function", []
-      | Parameter -> "parameter", []
-      | DataDecl -> "variable", ["declaration"]
-      | DataLevel -> "decorator", []
-      | Var -> "variable", []
-      | VarModif -> "variable", ["modification"]
-      | ReportName
-      | ExceptionName
-      | MnemonicName
-      | FileName -> "variable", ["readonly"]
+    semtok_of lexloc @@ match category with
+    | ProgramName -> TOKTYP.string, TOKMOD.(union [definition; readonly])
+    | ParagraphName -> TOKTYP.function_, TOKMOD.(one definition)
+    | ProcName -> TOKTYP.function_, TOKMOD.none
+    | Parameter -> TOKTYP.parameter, TOKMOD.none
+    | DataDecl -> TOKTYP.variable, TOKMOD.(one declaration)
+    | DataLevel -> TOKTYP.decorator, TOKMOD.none
+    | Var -> TOKTYP.variable, TOKMOD.none
+    | VarModif -> TOKTYP.variable, TOKMOD.(one modification)
+    | ReportName
+    | ExceptionName
+    | MnemonicName
+    | FileName -> TOKTYP.variable, TOKMOD.(one readonly)
   in
-  let add_name' name token_type acc =
+  let add_name' name toktyp acc =
     match Srcloc.lexloc_in ~filename ~@name with
-    | lexloc -> List.cons (semantic_token_of lexloc token_type) acc
+    | lexloc -> List.cons (semtok_of lexloc toktyp) acc
     | exception Invalid_argument _ -> acc
   in
-  let rec add_qualname (qn:Cobol_ast.qualname) token_type acc =
+  let rec add_qualname (qn:Cobol_ast.qualname) toktyp acc =
     match qn with
     | Name name ->
-        add_name' name token_type acc
+        add_name' name toktyp acc
     | Qual (name, qn) ->
-        add_name' name token_type acc |> add_qualname qn token_type
+        add_name' name toktyp acc |> add_qualname qn toktyp
   in
-  let add_ident (id:Cobol_ast.ident) token_type acc =
+  let add_ident (id:Cobol_ast.ident) toktyp acc =
     match id with
-    | QualIdent {ident_name; _} -> add_qualname ident_name token_type acc
+    | QualIdent {ident_name; _} -> add_qualname ident_name toktyp acc
     | _ -> acc (* TODO *)
   in
   let add_ident' id = add_ident ~&id in
-  let add_list add_fun l token_type acc =
-    List.fold_left (fun acc n -> add_fun n token_type acc) acc l
+  let add_list add_fun l toktyp acc =
+    List.fold_left (fun acc n -> add_fun n toktyp acc) acc l
   in
-  let add_option add_fun v token_type acc =
+  let add_option add_fun v toktyp acc =
     match v with
     | None -> acc
-    | Some v -> add_fun v token_type acc
+    | Some v -> add_fun v toktyp acc
   in
 
   Cobol_parser.PTree_visitor.fold_compilation_group (object (self)
-    inherit [semantic_token List.t] Cobol_parser.PTree_visitor.folder
+    inherit [semtok List.t] Cobol_parser.PTree_visitor.folder
 
     (* program-name *)
     method! fold_program_unit {program_name; _} acc = acc
@@ -522,22 +557,23 @@ let make_non_ambigious ~filename tokens = tokens |>
        match token with
        | WORD _ | WORD_IN_AREA_A _ -> None
        | ALPHANUM _ | ALPHANUM_PREFIX _ ->
-          Some (semantic_token lexloc "string" [])
+           Some (semtok lexloc TOKTYP.string)
        | BOOLIT _
        | HEXLIT _ | NULLIT _
        | NATLIT _ | SINTLIT _
        | FIXEDLIT _ | FLOATLIT _
        | DIGITS _
        | EIGHTY_EIGHT ->
-          Some (semantic_token lexloc "number" [])
+           Some (semtok lexloc TOKTYP.number)
        | PICTURE_STRING _ ->
-          Some (semantic_token lexloc "type" ["declaration"])
+           Some (semtok lexloc TOKTYP.type_
+                   ~tokmods:TOKMOD.(one declaration))
        (* | EQUAL | PLUS | MINUS  *)
        | AMPERSAND | ASTERISK | COLON | DASH_SIGN | DOUBLE_ASTERISK | DOUBLE_COLON
        | EQ | GE | GT | LE | LPAR | LT | NE | PLUS_SIGN | RPAR | SLASH ->
-          Some (semantic_token lexloc "operator" [])
+           Some (semtok lexloc TOKTYP.operator)
        | PARAGRAPH | STATEMENT | PROGRAM |SECTION | DIVISION ->
-          Some (semantic_token lexloc "namespace" [])
+           Some (semtok lexloc TOKTYP.namespace)
        | ACCEPT | ACCESS | ADD | ALLOCATE | ALTER | APPLY | ARE | ASSIGN | CALL | CANCEL | CHAIN | CLOSE
        | COMMIT | COMPUTE | CONTINUE | CONTROL | CONTROLS | COPY | COPY_SELECTION | COUNT | CYCLE
        | DELETE | DESTROY | DISABLE | DISP | DISPLAY | DISPLAY_1 | DISPLAY_COLUMNS | DISPLAY_FORMAT
@@ -553,69 +589,35 @@ let make_non_ambigious ~filename tokens = tokens |>
        | END_ACCEPT | END_ADD | END_CALL | END_COMPUTE | END_DELETE | END_DISPLAY | END_DIVIDE | END_EVALUATE
        | END_IF | END_MULTIPLY | END_PERFORM | END_READ | END_RETURN | END_REWRITE | END_SEARCH | END_START
        | END_STRING | END_SUBTRACT | END_UNSTRING | END_WRITE ->
-          Some (semantic_token lexloc "function" ["defaultLibrary";])
+           Some (semtok lexloc TOKTYP.function_
+                   ~tokmods:TOKMOD.(one defaultLibrary))
        | _ ->
-          Some (semantic_token lexloc "keyword" []))
-
-let semantic_tbl = Hashtbl.create 16
-let () = List.iteri (fun i elt -> Hashtbl.add semantic_tbl elt i) tokens_types
-let index i = Hashtbl.find semantic_tbl i
-
-let tokens_modifiers_bit_flag = Hashtbl.create 8
-let () =
-  List.iteri (fun i v ->
-    Hashtbl.add tokens_modifiers_bit_flag
-    v (0b1 lsl i))
-  tokens_modifiers
-
-let token_modifiers_flag modifiers =
-  List.fold_left
-    (fun acc modifier ->
-       let modifier_flag = Hashtbl.find tokens_modifiers_bit_flag modifier  in
-       acc lor modifier_flag)
-    0b0
-    modifiers
-
-let data_of_semantic_token semantic_token =
-  let data = Array.make 5 0 in
-  data.(0) <- semantic_token.line;
-  data.(1) <- semantic_token.start;
-  data.(2) <- semantic_token.length;
-  data.(3) <- index semantic_token.token_type;
-  data.(4) <- token_modifiers_flag semantic_token.token_modifiers;
-  data
+           Some (semtok lexloc TOKTYP.keyword))
 
-let data_of_semantic_tokens semantic_tokens =
-  let data = Array.make (5 * List.length semantic_tokens) 0 in
-  ignore @@ List.fold_left
-    (fun (idx, last_line, last_start) semantic_token ->
-       let token_data = data_of_semantic_token semantic_token in
-       let delta_line = token_data.(0) - last_line in
-       let delta_start = if delta_line = 0 then
-           token_data.(1) - last_start
-         else
-           token_data.(1)
-       in
-       data.(5 * idx) <- delta_line;
-       data.(5 * idx + 1) <- delta_start;
-       data.(5 * idx + 2) <- token_data.(2);
-       data.(5 * idx + 3) <- token_data.(3);
-       data.(5 * idx + 4) <- token_data.(4);
-       (idx + 1, semantic_token.line, semantic_token.start))
-    (0, 0, 0)
-    semantic_tokens;
-  data
-
-let sort_semantic_token first second = (* TODO: use Lexing.position, and then a
-                                          comparison on `pos_cnum` only? *)
+let compare_semtoks first second =      (* TODO: use Lexing.position, and then a
+                                           comparison on `pos_cnum` only? *)
   let cmp = Stdlib.compare first.line second.line in
   if cmp = 0
   then Stdlib.compare first.start second.start
   else cmp
 
+let relative_semtoks semtoks =
+  let semtoks = Array.of_list semtoks in
+  Array.fast_sort compare_semtoks semtoks;
+  let data = Array.make (5 * Array.length semtoks) 0 in
+  ignore @@ Array.fold_left begin fun (i, prev_line, prev_start) semtok ->
+    data.(5 * i + 0) <- semtok.line - prev_line;
+    data.(5 * i + 1) <- semtok.start -
+                        if semtok.line = prev_line then prev_start else 0;
+    data.(5 * i + 2) <- semtok.length;
+    data.(5 * i + 3) <- semtok.toktyp.index;
+    data.(5 * i + 4) <- semtok.tokmods.flags;
+    (succ i, semtok.line, semtok.start)
+  end (0, 0, 0) semtoks;
+  data
+
 let data ~filename tokens ptree : int array =
   tokens
   |> make_non_ambigious ~filename
   |> semantic_visitor ~filename ptree
-  |> List.fast_sort sort_semantic_token
-  |> data_of_semantic_tokens
+  |> relative_semtoks
diff --git a/src/lsp/cobol_lsp/lsp_semtoks.mli b/src/lsp/cobol_lsp/lsp_semtoks.mli
new file mode 100644
index 000000000..07f0bc125
--- /dev/null
+++ b/src/lsp/cobol_lsp/lsp_semtoks.mli
@@ -0,0 +1,20 @@
+(**************************************************************************)
+(*                                                                        *)
+(*                        SuperBOL OSS Studio                             *)
+(*                                                                        *)
+(*  Copyright (c) 2022-2023 OCamlPro SAS                                  *)
+(*                                                                        *)
+(* All rights reserved.                                                   *)
+(* This source code is licensed under the GNU Affero General Public       *)
+(* License version 3 found in the LICENSE.md file in the root directory   *)
+(* of this source tree.                                                   *)
+(*                                                                        *)
+(**************************************************************************)
+
+val token_types: string list
+val token_modifiers: string list
+val data
+  : filename: string
+  -> Cobol_parser.tokens_with_locs
+  -> Lsp_imports.PTREE.compilation_group
+  -> int array

From f621cd44e2358d2e2d22051e6a99777e7b9bb154 Mon Sep 17 00:00:00 2001
From: Nicolas Berthier <nicolas.berthier@ocamlpro.com>
Date: Fri, 15 Sep 2023 16:37:46 +0200
Subject: [PATCH 04/17] Rework LSP internals, emit semantic tokens for comments

A more efficient generation of semantic tokens may require parse-tree
nodes to be visited in the same order as in the source code.  This
commit also starts implementing the necessary changes to enforce that
behavior.
---
 src/lsp/cobol_ast/branching_statements.ml     |  44 ++-
 .../cobol_ast/raw_data_sections_visitor.ml    |   3 +
 src/lsp/cobol_ast/raw_statements_visitor.ml   |  27 +-
 src/lsp/cobol_common/srcloc.ml                |  87 ++++--
 src/lsp/cobol_common/srcloc.mli               |  18 +-
 src/lsp/cobol_lsp/lsp_document.ml             |  52 ++--
 src/lsp/cobol_lsp/lsp_io.ml                   |  82 +++--
 src/lsp/cobol_lsp/lsp_io.mli                  |   4 +-
 src/lsp/cobol_lsp/lsp_notif.ml                |  15 +-
 src/lsp/cobol_lsp/lsp_request.ml              | 156 ++++++----
 src/lsp/cobol_lsp/lsp_request.mli             |   2 +-
 src/lsp/cobol_lsp/lsp_semtoks.ml              | 286 ++++++++++--------
 src/lsp/cobol_lsp/lsp_semtoks.mli             |   9 +-
 src/lsp/cobol_lsp/lsp_server.ml               |  26 +-
 src/lsp/cobol_lsp/lsp_server.mli              |   3 +-
 src/lsp/cobol_lsp/lsp_server_loop.ml          |  42 ++-
 src/lsp/cobol_parser/cobol_parser.ml          |   3 +-
 src/lsp/cobol_parser/grammar.mly              |  10 +-
 src/lsp/cobol_parser/parser_engine.ml         |  24 +-
 src/lsp/cobol_parser/parser_engine.mli        |   6 +-
 src/lsp/cobol_parser/parser_options.ml        |   8 +-
 src/lsp/cobol_preproc/cobol_preproc.ml        |   2 +
 src/lsp/cobol_preproc/preproc.ml              |   2 +
 src/lsp/cobol_preproc/preproc.mli             |  16 +-
 src/lsp/cobol_preproc/preproc_engine.ml       |   4 +-
 src/lsp/cobol_preproc/preproc_engine.mli      |   1 +
 src/lsp/cobol_preproc/src_lexing.ml           |  12 +-
 src/lsp/cobol_preproc/src_lexing.mli          |   2 +-
 src/lsp/cobol_preproc/text.mli                |   1 +
 src/lsp/cobol_preproc/text_types.ml           |   1 +
 src/lsp/cobol_typeck/cobol_typeck.ml          |   4 +-
 test/cobol_parsing/parser_testing.ml          |   2 +-
 32 files changed, 553 insertions(+), 401 deletions(-)

diff --git a/src/lsp/cobol_ast/branching_statements.ml b/src/lsp/cobol_ast/branching_statements.ml
index 45adc2aef..c76e1b6df 100644
--- a/src/lsp/cobol_ast/branching_statements.ml
+++ b/src/lsp/cobol_ast/branching_statements.ml
@@ -60,15 +60,17 @@ and evaluate_branch =
 
 
 (* PERFORM *)
-and perform_stmt =
+and perform_target_stmt =
   {
-    perform_target: perform_target;
+    perform_target: qualname procedure_range;
     perform_mode: perform_mode option;
   }
 
-and perform_target =
-  | PerformOutOfLine of qualname procedure_range
-  | PerformInline of statements
+and perform_inline_stmt =
+  {
+    perform_inline_mode: perform_mode option;
+    perform_statements: statements;
+  }
 
 and perform_mode =
   | PerformNTimes of ident_or_intlit
@@ -396,7 +398,8 @@ and statement =
   | Move of move_stmt
   | Multiply of multiply_stmt
   | Open of open_stmt
-  | Perform of perform_stmt
+  | PerformTarget of perform_target_stmt
+  | PerformInline of perform_inline_stmt
   | Purge of name with_loc
   | Raise of raise_operand
   | Read of read_stmt
@@ -525,21 +528,15 @@ and pp_evaluate_branch ppf { eval_selection; eval_actions } =
 
 (* PERFORM *)
 
-and pp_perform_stmt ppf { perform_target; perform_mode } =
-  match perform_target with
-  | PerformInline _ ->
-    Fmt.pf ppf "@[<v>@[PERFORM%a@]@;<1 2>%a@]"
-      Fmt.(option (sp ++ pp_perform_mode)) perform_mode
-      pp_perform_target perform_target
-  | PerformOutOfLine _ ->
-    Fmt.pf ppf "@[<hv>PERFORM@;<1 2>%a%a@]"
-      pp_perform_target perform_target
-      Fmt.(option (sp ++ pp_perform_mode)) perform_mode
-
-and pp_perform_target ppf = function
-  | PerformOutOfLine qnpr -> pp_procedure_range pp_qualname ppf qnpr
-  | PerformInline isl ->
-    Fmt.pf ppf "%a@ END-PERFORM" pp_statements isl
+and pp_perform_target_stmt ppf { perform_target; perform_mode } =
+  Fmt.pf ppf "@[<hv>PERFORM@;<1 2>%a%a@]"
+    (pp_procedure_range pp_qualname) perform_target
+    Fmt.(option (sp ++ pp_perform_mode)) perform_mode
+
+and pp_perform_inline_stmt ppf { perform_inline_mode; perform_statements } =
+  Fmt.pf ppf "@[<v>@[PERFORM%a@]@;<1 2>%a@ END-PERFORM@]"
+    Fmt.(option (sp ++ pp_perform_mode)) perform_inline_mode
+    pp_statements perform_statements
 
 and pp_perform_mode ppf = function
   | PerformNTimes i -> Fmt.pf ppf "%a TIMES" pp_ident_or_intlit i
@@ -877,7 +874,8 @@ and pp_statement ppf = function
   | Move s -> pp_move_stmt ppf s
   | Multiply s -> pp_multiply_stmt ppf s
   | Open s -> pp_open_stmt ppf s
-  | Perform s -> pp_perform_stmt ppf s
+  | PerformInline s -> pp_perform_inline_stmt ppf s
+  | PerformTarget s -> pp_perform_target_stmt ppf s
   | Purge n -> Fmt.pf ppf "PURGE %a" (pp_with_loc pp_name) n
   | Raise ro -> pp_raise_operand ppf ro
   | Read s -> pp_read_stmt ppf s
@@ -908,4 +906,4 @@ and pp_statements ppf =
 
 and pp_branch ppf = function
   | Statements ss -> pp_statements ppf ss
-  | NextSentence -> Fmt.pf ppf "@[NEXT@ SENTENCE@]"
\ No newline at end of file
+  | NextSentence -> Fmt.pf ppf "@[NEXT@ SENTENCE@]"
diff --git a/src/lsp/cobol_ast/raw_data_sections_visitor.ml b/src/lsp/cobol_ast/raw_data_sections_visitor.ml
index e08ef10c1..31f09f0a4 100644
--- a/src/lsp/cobol_ast/raw_data_sections_visitor.ml
+++ b/src/lsp/cobol_ast/raw_data_sections_visitor.ml
@@ -229,6 +229,9 @@ struct
         | DataGlobal
         | DataJustified -> Fun.id
         | DataOccurs c -> fold_data_occurs_clause v c
+        | DataRedefines n
+        | DataType n
+        | DataSameAs n -> fold_name' v n
         | _ -> partial __LINE__ "fold_data_clause"
       end
 
diff --git a/src/lsp/cobol_ast/raw_statements_visitor.ml b/src/lsp/cobol_ast/raw_statements_visitor.ml
index 534d4f7b9..500deb5f6 100644
--- a/src/lsp/cobol_ast/raw_statements_visitor.ml
+++ b/src/lsp/cobol_ast/raw_statements_visitor.ml
@@ -80,7 +80,6 @@ module Make = struct
     (* high-level structures and branches *)
     method fold_handler'            : (handler with_loc           , 'a) fold = default
     method fold_dual_handler        : (dual_handler               , 'a) fold = default
-    method fold_perform_target      : (perform_target             , 'a) fold = default
     method fold_call_error_handler  : (call_error_handler         , 'a) fold = default
     method fold_search_when_clause' : (search_when_clause with_loc, 'a) fold = default
     method fold_search_spec         : (search_spec                , 'a) fold = default
@@ -114,7 +113,8 @@ module Make = struct
     method fold_move'          : (move_stmt with_loc            , 'a) fold = default
     method fold_multiply'      : (multiply_stmt with_loc        , 'a) fold = default
     method fold_open'          : (open_stmt with_loc            , 'a) fold = default
-    method fold_perform'       : (perform_stmt with_loc         , 'a) fold = default
+    method fold_perform_target': (perform_target_stmt with_loc  , 'a) fold = default
+    method fold_perform_inline': (perform_inline_stmt with_loc  , 'a) fold = default
     method fold_raise'         : (raise_operand with_loc        , 'a) fold = default
     method fold_read'          : (read_stmt with_loc            , 'a) fold = default
     method fold_release'       : (release_stmt with_loc         , 'a) fold = default
@@ -632,7 +632,8 @@ module Make = struct
         | Move          s -> fold_move'           v (s &@ loc)
         | Multiply      s -> fold_multiply'       v (s &@ loc)
         | Open          s -> fold_open'           v (s &@ loc)
-        | Perform       s -> fold_perform'        v (s &@ loc)
+        | PerformTarget s -> fold_perform_target' v (s &@ loc)
+        | PerformInline s -> fold_perform_inline' v (s &@ loc)
         | Raise         s -> fold_raise'          v (s &@ loc)
         | Read          s -> fold_read'           v (s &@ loc)
         | Release       s -> fold_release'        v (s &@ loc)
@@ -808,20 +809,18 @@ module Make = struct
         >> fold_dual_handler v multiply_on_size_error
       end
 
-  and fold_perform' (v: _ #folder) : perform_stmt with_loc -> 'a -> 'a =
-    handle' v#fold_perform' v
-      ~fold:begin fun v { perform_target; perform_mode } x -> x
-        >> fold_perform_target v perform_target
+  and fold_perform_target' (v: _ #folder) : perform_target_stmt with_loc -> 'a -> 'a =
+    handle' v#fold_perform_target' v
+      ~fold:begin fun v { perform_target = proc_range; perform_mode } x -> x
+        >> fold_procedure_range ~fold:fold_qualname v proc_range
         >> fold_option ~fold:fold_perform_mode v perform_mode
       end
 
-  and fold_perform_target (v: _ #folder) =
-    handle v#fold_perform_target
-      ~continue:begin function
-        | PerformOutOfLine proc_range ->
-            fold_procedure_range ~fold:fold_qualname v proc_range
-        | PerformInline stmts ->
-            fold_statements v stmts
+  and fold_perform_inline' (v: _ #folder) : perform_inline_stmt with_loc -> 'a -> 'a =
+    handle' v#fold_perform_inline' v
+      ~fold:begin fun v { perform_inline_mode; perform_statements } x -> x
+        >> fold_option ~fold:fold_perform_mode v perform_inline_mode
+        >> fold_statements v perform_statements
       end
 
   and fold_read_error_handler (v: _ #folder) =
diff --git a/src/lsp/cobol_common/srcloc.ml b/src/lsp/cobol_common/srcloc.ml
index 807a249e8..689ca4154 100644
--- a/src/lsp/cobol_common/srcloc.ml
+++ b/src/lsp/cobol_common/srcloc.ml
@@ -102,6 +102,22 @@ let rec start_pos: type t. t slt -> Lexing.position = function
   | Rpl { old; _ } -> start_pos old
   | Cat { left; _ } -> start_pos left
 
+let shallow_multiline_lexloc_in ~filename loc =
+  let rec aux: type t. t slt -> lexloc option = function
+    | Raw (s, e, _) when s.pos_fname = filename -> Some (s, e)
+    | Raw _ | Cpy _ | Rpl _ -> None
+    | Cat { left; right } -> match aux left, aux right with
+      | Some (s, _), Some (_, e)
+      | Some (s, e), None
+      | None, Some (s, e) -> Some (s, e)
+      | None, None -> None
+  in
+  aux loc
+
+let shallow_single_line_lexloc_in ~filename = function
+  | Raw (s, e, _) when s.pos_fname = filename -> Some (s, e)
+  | Raw _ | Cpy _ | Rpl _ | Cat _ -> None
+
 let start_pos_in ~filename =
   let rec aux: type t. t slt -> Lexing.position option = function
     | Raw (s, _, _) when s.pos_fname = filename -> Some s
@@ -176,15 +192,46 @@ let as_lexloc: srcloc -> lexloc =
   forget_preproc ~favor_direction:`Left
     ~traverse_copies:true ~traverse_replaces:false
 
-let lookup_pos ~lookup ~lookup_name ~filename loc =
+let lookup_ ~lookup ~lookup_name ~filename loc =
   match lookup ~filename loc with
-  | None -> Fmt.invalid_arg "%s.%s: no part of \"%s\" was used to construct the \
-                             given location (loc = %a)" __MODULE__ lookup_name filename
-              pp_srcloc_struct loc
-  | Some s -> s
-
-let start_pos_in = lookup_pos ~lookup:start_pos_in ~lookup_name:"start_pos_in"
-let end_pos_in = lookup_pos ~lookup:end_pos_in ~lookup_name:"end_pos_in"
+  | None ->
+      Pretty.invalid_arg
+        "%s.%s: no part of \"%s\" was used to construct the given location (loc \
+         = %a)" __MODULE__ lookup_name filename pp_srcloc_struct loc
+  | Some s ->
+      s
+
+let start_pos_in =
+  lookup_ ~lookup:start_pos_in
+    ~lookup_name:"start_pos_in"
+let end_pos_in =
+  lookup_ ~lookup:end_pos_in
+    ~lookup_name:"end_pos_in"
+let shallow_multiline_lexloc_in =
+  lookup_ ~lookup:shallow_multiline_lexloc_in
+    ~lookup_name:"shallow_multiline_lexloc_in"
+let shallow_single_line_lexloc_in =
+  lookup_ ~lookup:shallow_single_line_lexloc_in
+    ~lookup_name:"shallow_single_line_lexloc_in"
+(* let shallow_single_line_lexlocs_in = *)
+(*   lookup_ ~lookup:shallow_single_line_lexlocs_in *)
+(*     ~lookup_name:"shallow_single_line_lexlocs_in" *)
+
+let shallow_single_line_lexlocs_in
+    ?(ignore_invalid_filename = false) ~filename loc =
+  let rec aux: type t. t slt -> (lexloc list as 'a) -> 'a = function
+    | Raw (s, e, _) when s.pos_fname = filename -> List.cons (s, e)
+    | Raw _ | Cpy _ | Rpl _ -> Fun.id
+    | Cat { left; right } -> fun acc -> acc |> aux right |> aux left
+  in
+  match aux loc [] with
+  | l when ignore_invalid_filename -> l
+  | _ :: _ as l -> l
+  | [] ->
+      Pretty.invalid_arg
+        "%s.%s: no part of \"%s\" was used to construct the given location (loc \
+         = %a)" __MODULE__ "shallow_single_line_lexlocs_in"
+        filename pp_srcloc_struct loc
 
 (** [lexloc_in ~filename loc] projects the source location [loc] on the file
     [filename] by eliminating relevant preprocessor-related locations.
@@ -233,18 +280,18 @@ let scan ?(kind: [`TopDown | `BottomUp] = `TopDown) ~cpy ~rpl =
   in
   aux
 
-let fold_lexlocs f loc acc =
-  let rec aux: type t. t slt -> 'a -> 'a = fun loc -> match loc with
-    | Raw (s, e, _) -> f (s, e)
-    | Cpy { copied; _ } -> aux copied
-    | Rpl { old; _ } -> aux old
-    | Cat { left; right } -> fun acc -> acc |> aux left |> aux right
-  in
-  aux loc acc
-
-let has_lexloc p loc =
-  try fold_lexlocs (fun lexloc () -> if p lexloc then raise Exit) loc (); false
-  with Exit -> true
+(* let fold_lexlocs f loc acc = *)
+(*   let rec aux: type t. t slt -> 'a -> 'a = fun loc -> match loc with *)
+(*     | Raw (s, e, _) -> f (s, e) *)
+(*     | Cpy { copied; _ } -> aux copied *)
+(*     | Rpl { old; _ } -> aux old *)
+(*     | Cat { left; right } -> fun acc -> acc |> aux left |> aux right *)
+(*   in *)
+(*   aux loc acc *)
+
+(* let has_lexloc p loc = *)
+(*   try fold_lexlocs (fun lexloc () -> if p lexloc then raise Exit) loc (); false *)
+(*   with Exit -> true *)
 
 let retrieve_file_lines =
   let module Cache =
diff --git a/src/lsp/cobol_common/srcloc.mli b/src/lsp/cobol_common/srcloc.mli
index b371757d7..f7cb37d68 100644
--- a/src/lsp/cobol_common/srcloc.mli
+++ b/src/lsp/cobol_common/srcloc.mli
@@ -70,6 +70,19 @@ val lexloc_in
   : filename: string
   -> srcloc
   -> lexloc
+val shallow_multiline_lexloc_in
+  : filename: string
+  -> srcloc
+  -> lexloc
+val shallow_single_line_lexloc_in
+  : filename: string
+  -> srcloc
+  -> lexloc
+val shallow_single_line_lexlocs_in
+  : ?ignore_invalid_filename: bool
+  -> filename: string
+  -> srcloc
+  -> lexloc list
 val as_unique_lexloc
   : srcloc
   -> lexloc option
@@ -82,8 +95,8 @@ val start_pos: srcloc -> Lexing.position    (* only suitable for Area A checks *
 val start_pos_in: filename: string -> srcloc -> Lexing.position
 val end_pos_in: filename: string -> srcloc -> Lexing.position
 
-val fold_lexlocs: (lexloc -> 'a -> 'a) -> srcloc -> 'a -> 'a
-val has_lexloc: (lexloc -> bool) -> srcloc -> bool
+(* val fold_lexlocs: (lexloc -> 'a -> 'a) -> srcloc -> 'a -> 'a *)
+(* val has_lexloc: (lexloc -> bool) -> srcloc -> bool *)
 
 val concat: srcloc -> srcloc -> srcloc
 val concat_srclocs: srcloc list -> srcloc option
@@ -95,6 +108,7 @@ val sub : srcloc -> pos:int -> len:int -> srcloc
 
 val pp: 'a Pretty.printer -> 'a with_loc Pretty.printer
 val pp_with_loc: 'a Pretty.printer -> 'a with_loc Pretty.printer
+val pp_raw_loc: (string * (int * int) * (int * int)) Pretty.printer
 val flagit: 'a -> srcloc -> 'a with_loc
 val payload: 'a with_loc -> 'a
 val loc: 'a with_loc -> srcloc
diff --git a/src/lsp/cobol_lsp/lsp_document.ml b/src/lsp/cobol_lsp/lsp_document.ml
index a8127962b..9c93566f4 100644
--- a/src/lsp/cobol_lsp/lsp_document.ml
+++ b/src/lsp/cobol_lsp/lsp_document.ml
@@ -25,8 +25,7 @@ module TYPES = struct
       project: Lsp_project.t;
       textdoc: Lsp.Text_document.t;
       copybook: bool;
-      pplog: Cobol_preproc.log;
-      tokens: Cobol_parser.tokens_with_locs Lazy.t;
+      artifacts: Cobol_parser.parsing_artifacts;
       parsed: parsed_data option;
       (* Used for caching, when loading a cache file as the file is not reparsed,
          then diagnostics are not sent. *)
@@ -34,7 +33,7 @@ module TYPES = struct
     }
   and parsed_data =
     {
-      ast: PTREE.compilation_group;
+      ast: PTREE.compilation_group;                (* TODO: rename into ptree *)
       cus: CUs.t;
       (* Extracted info: lazy to only ever retrieve what's relevant upon a first
          request. *)
@@ -54,6 +53,7 @@ module TYPES = struct
       doc_cache_version: int;
       doc_cache_pplog: Cobol_preproc.log;
       doc_cache_tokens: Cobol_parser.tokens_with_locs;
+      doc_cache_comments: Cobol_preproc.comments;
       doc_cache_parsed: (PTREE.compilation_group * CUs.t) option;
       doc_cache_diags: DIAGS.Set.serializable;
     }
@@ -88,26 +88,29 @@ let lazy_definitions ast cus =
 let lazy_references ast cus defs =
   lazy begin
     let defs = Lazy.force defs in
-    try
-      List.fold_left
-        (fun map cu ->
-           let cu_name = Lsp_lookup.name_of_compunit cu in
-           let _, cu_defs = CUMap.find_by_name cu_name defs in
-           CUMap.add
-             (CUs.find_by_name cu_name cus)
-             (Lsp_lookup.references cu_defs cu) map )
-        CUMap.empty ast
-    with Not_found -> CUMap.empty
+    List.fold_left begin fun map cu ->
+        let cu_name = Lsp_lookup.name_of_compunit cu in
+        try
+          let _, cu_defs = CUMap.find_by_name cu_name defs in
+          CUMap.add
+            (CUs.find_by_name cu_name cus)
+          (Lsp_lookup.references cu_defs cu) map
+        with Not_found -> map
+    end CUMap.empty ast
   end
 
+let no_parsing_artifacts =
+  Cobol_parser.{ tokens = lazy [];
+                 pplog = Cobol_preproc.Trace.empty;
+                 comments = [] }
+
 let analyze ({ project; textdoc; copybook; _ } as doc) =
-  let pplog, tokens, (parsed, diags) =
+  let artifacts, (parsed, diags) =
     if copybook then
-      Cobol_preproc.Trace.empty, lazy [], (None, DIAGS.Set.none)
+      no_parsing_artifacts, (None, DIAGS.Set.none)
     else
       let ptree = parse ~project textdoc in
-      Cobol_parser.preproc_rev_log ptree,
-      Cobol_parser.parsed_tokens ptree,
+      Cobol_parser.parsing_artifacts ptree,
       match Cobol_typeck.analyze_compilation_group ptree with
       | Ok (cus, ast, diags) ->
           let definitions = lazy_definitions ast cus in
@@ -117,7 +120,7 @@ let analyze ({ project; textdoc; copybook; _ } as doc) =
           None, diags (* NB: no token if unrecoverable error (e.g, wrong
                          indicator) *)
   in
-  { doc with pplog; tokens; diags; parsed }
+  { doc with artifacts; diags; parsed }
 
 (** Creates a record for a document that is not yet parsed or analyzed. *)
 let blank ~project ?copybook textdoc =
@@ -129,8 +132,7 @@ let blank ~project ?copybook textdoc =
   {
     project;
     textdoc;
-    pplog = Cobol_preproc.Trace.empty;
-    tokens = lazy [];
+    artifacts = no_parsing_artifacts;
     diags = DIAGS.Set.none;
     parsed = None;
     copybook;
@@ -157,7 +159,8 @@ let retrieve_parsed_data: document -> parsed_data = function
 
 (** Caching utilities *)
 
-let to_cache ({ project; textdoc; pplog; tokens; parsed; diags; _ } as doc) =
+let to_cache ({ project; textdoc; parsed; diags;
+                artifacts = { pplog; tokens; comments }; _ } as doc) =
   {
     doc_cache_filename = Lsp_project.relative_path_for ~uri:(uri doc) project;
     doc_cache_checksum = Digest.string (Lsp.Text_document.text textdoc);
@@ -165,6 +168,7 @@ let to_cache ({ project; textdoc; pplog; tokens; parsed; diags; _ } as doc) =
     doc_cache_version = Lsp.Text_document.version textdoc;
     doc_cache_pplog = pplog;
     doc_cache_tokens = Lazy.force tokens;
+    doc_cache_comments = comments;
     doc_cache_parsed = Option.map (fun { ast; cus; _ } -> ast, cus) parsed;
     doc_cache_diags = DIAGS.Set.apply_delayed_formatting diags;
   }
@@ -179,6 +183,7 @@ let of_cache ~project
       doc_cache_version = version;
       doc_cache_pplog = pplog;
       doc_cache_tokens = tokens;
+      doc_cache_comments = comments;
       doc_cache_parsed = parsed;
       doc_cache_diags = diags } =
   let absolute_filename = Lsp_project.absolute_path_for ~filename project in
@@ -199,8 +204,9 @@ let of_cache ~project
           { ast; cus; definitions; references})
         parsed
     in
-    let diags = DIAGS.Set.of_serializable diags in
-    { doc with pplog; tokens = lazy tokens; parsed; diags }
+    { doc with artifacts = { pplog; tokens = lazy tokens; comments };
+               diags = DIAGS.Set.of_serializable diags;
+               parsed }
 
 (* --- *)
 
diff --git a/src/lsp/cobol_lsp/lsp_io.ml b/src/lsp/cobol_lsp/lsp_io.ml
index 6c13999bb..e148dbe92 100644
--- a/src/lsp/cobol_lsp/lsp_io.ml
+++ b/src/lsp/cobol_lsp/lsp_io.ml
@@ -14,19 +14,24 @@
 (** Simple communication functions for the LSP server to send an receive json
     RPC messages. *)
 
+exception Parse_error of string
+
+let parse_error fmt =
+  Pretty.string_to (fun msg -> raise (Parse_error msg)) fmt
+
 (** [send_out msg] returns {!type:unit} and is used to send out a message. This
     function can be edited later to use other channels than stdin or stdout as
     IO. *)
 let send_out msg = print_string msg
 
 (** [read_message ()] tries to read a json RPC message from the standard input
-    stream.  Returns [Ok packet] upon success, or [Error error_response] if the
-    message is in the wrong format. *)
-let read_message () : (Jsonrpc.Packet.t, Jsonrpc.Response.Error.t) result =
+    stream.  Returns a proper [packet] upon success, or raises {!Parse_error} if
+    the message is in a wrong format. *)
+let read_message () : Jsonrpc.Packet.t =
   let rec read_headers acc =
     let line = read_line () in
     match String.trim line with
-    | "" -> Ok acc (* an empty line after the headers *)
+    | "" -> acc (* an empty line after the headers *)
     | line ->
         try
           let i = String.index line ':' in
@@ -37,73 +42,62 @@ let read_message () : (Jsonrpc.Packet.t, Jsonrpc.Response.Error.t) result =
             String.sub line (i + 1) (String.length line - i - 1)
           in
           read_headers @@ (header_key, header_value)::acc
-        with _ -> Error (Fmt.str "invalid header: %s" line)
+        with Not_found ->
+          parse_error "invalid header: %s" line
   in
   let rec read_len buf i len =
     if len > 0 then
       let n = input stdin buf i len in
       read_len buf (i + n) (len - n)
   in
-  let headers = read_headers [] in
-  match headers with
-  | Ok headers ->
-      begin match List.assoc_opt "content-type" headers, List.assoc_opt "content-length" headers with
-        | (Some ("utf8" | "utf-8") | None), Some len_str ->
-            let content_length = int_of_string_opt len_str in
-            begin match content_length with
-              | Some len ->
-                  let buf = Bytes.make len '\000' in
-                  let () = read_len buf 0 len in
-                  let str = Bytes.to_string buf in
-                  begin try
-                      let json = Yojson.Safe.from_string str in
-                      Ok (Jsonrpc.Packet.t_of_yojson json)
-                    with Yojson.Json_error msg ->
-                      let message = Fmt.str "invalid json: %s:\n%s" msg str in
-                      Error (Jsonrpc.Response.Error.(make ~code:Code.ParseError ~message ()))
-                  end
-              | None ->
-                  let message = Fmt.str "not an integer value: %s" len_str in
-                  Error (Jsonrpc.Response.Error.(make ~code:Code.ParseError ~message ()))
+  match
+    let headers = read_headers [] in
+    List.assoc_opt "content-type" headers,
+    List.assoc_opt "content-length" headers
+  with
+  | (Some ("utf8" | "utf-8") | None), Some len_str ->
+      begin match int_of_string_opt len_str with
+        | Some len ->
+            let buf = Bytes.make len '\000' in
+            let () = read_len buf 0 len in
+            let str = Bytes.to_string buf in
+            begin
+              try Jsonrpc.Packet.t_of_yojson @@ Yojson.Safe.from_string str
+              with Yojson.Json_error msg ->
+                parse_error "invalid json: %s:\n%s" msg str
             end
-        | Some _, _ ->
-            Error
-              (Jsonrpc.Response.Error.(
-                  make ~code:Code.InvalidRequest ~message:"content-type must be 'utf-8'" ()))
-        | _, None ->
-            Error
-              (Jsonrpc.Response.Error.(
-                  make ~code:Code.ParseError ~message:"missing content-length header" ()))
+        | None ->
+            parse_error "not an integer value: %s" len_str
       end
-  | Error message ->
-      Error
-        (Jsonrpc.Response.Error.(make ~code:Code.ParseError ~message ()))
+  | Some _, _ ->
+      parse_error "content-type must be 'utf-8'"
+  | _, None ->
+      parse_error "missing content-length header"
+  | exception End_of_file ->
+      parse_error "premature end of input stream"
 
 (** [send_json json] sends out a json rpc package. *)
 let send_json json =
   let str = Yojson.Safe.to_string json in
   let len = String.length str in
-  let msg = Fmt.str "Content-Length: %d\r\n\r\n%s" len str in
-  send_out msg
+  Pretty.string_to send_out "Content-Length: %d\r\n\r\n%s" len str
 
 (** [send_response response] sends out a json RPC response on standard
     output. *)
 let send_response response =
-  let json = Jsonrpc.Response.yojson_of_t response in
-  send_json json
+  send_json @@ Jsonrpc.Response.yojson_of_t response
 
 (** [send_notification notif] sends out a json RPC notification on standard
     output. *)
 let send_notification notif =
-  let json = Jsonrpc.Notification.yojson_of_t notif in
-  send_json json
+  send_json @@ Jsonrpc.Notification.yojson_of_t notif
 
 (** [send_diagnostics ~uri diagnostics] sends out a list of diagnostics that
     pertain to the given URI. *)
 let send_diagnostics ~uri diagnostics =
   let params = Lsp.Types.PublishDiagnosticsParams.create ~diagnostics ~uri () in
   let notif = Lsp.Server_notification.PublishDiagnostics params in
-  send_notification (Lsp.Server_notification.to_jsonrpc notif)
+  send_notification @@ Lsp.Server_notification.to_jsonrpc notif
 
 (** [pretty_notification ~log ~type_ fmt ...] formats any number of arguments
     according to the format string [fmt], and sends the result via a json RPC
diff --git a/src/lsp/cobol_lsp/lsp_io.mli b/src/lsp/cobol_lsp/lsp_io.mli
index d21a2d414..637a60645 100644
--- a/src/lsp/cobol_lsp/lsp_io.mli
+++ b/src/lsp/cobol_lsp/lsp_io.mli
@@ -14,9 +14,11 @@
 (** Simple communication functions for the LSP server to send an receive json
     RPC messages. *)
 
+exception Parse_error of string
+
 (** [read_message ()] tries to read a json RPC message from the standard input
     stream. *)
-val read_message: unit -> (Jsonrpc.Packet.t, Jsonrpc.Response.Error.t) result
+val read_message: unit -> Jsonrpc.Packet.t
 
 (** [send_response response] sends out a json RPC response on standard
     output. *)
diff --git a/src/lsp/cobol_lsp/lsp_notif.ml b/src/lsp/cobol_lsp/lsp_notif.ml
index 2ae01984d..e865ea291 100644
--- a/src/lsp/cobol_lsp/lsp_notif.ml
+++ b/src/lsp/cobol_lsp/lsp_notif.ml
@@ -34,9 +34,18 @@ let on_notification state notif =
   | _ ->
       state
 
-let handle notif status =
+let handle notif state =
   match Lsp.Client_notification.of_jsonrpc notif with
   | Error str ->
-      Pretty.failwith "LSP@ sever@ could@ not@ decode@ notification:@ %s" str
+      Lsp_io.pretty_notification ~type_:Error "Invalid@ notification:@ %s" str;
+      state
   | Ok notif ->
-      on_notification status notif
+      try on_notification state notif with
+      | Lsp_server.Document_not_found { uri } ->
+          Lsp_io.pretty_notification ~type_:Error
+            "Document@ %s@ is@ not@ opened@ yet"
+            (Lsp.Types.DocumentUri.to_string uri);
+          state
+      | e ->
+          Lsp_io.pretty_notification ~type_:Error "%a" Fmt.exn e;
+          state
diff --git a/src/lsp/cobol_lsp/lsp_request.ml b/src/lsp/cobol_lsp/lsp_request.ml
index 35ffd2080..ec69a2a41 100644
--- a/src/lsp/cobol_lsp/lsp_request.ml
+++ b/src/lsp/cobol_lsp/lsp_request.ml
@@ -20,7 +20,7 @@ open Lsp.Types
 open Ez_file.V1
 
 
-(** Some preliminary utilities for manipulating source locations *)
+(** {2 Some preliminary utilities for manipulating source locations} *)
 
 type loc_translator =
   {
@@ -39,19 +39,39 @@ let loc_translator TextDocumentIdentifier.{ uri } =
     location_of = fun { loc; _ } -> location_of_srcloc loc;
   }
 
+(** {2 Error handling} *)
 
-(** Catching cases where we miss some document data *)
+(** Raises {!Jsonrpc.Response.Error.E} *)
+let error ~code fmt =
+  Pretty.string_to begin fun message ->
+    Jsonrpc.Response.Error.(raise @@ make ~code ~message ())
+  end fmt
 
-let try_with_document_data ?(on_error = None) ~f registry document_id =
-  try
-    let Lsp_document.{ project; textdoc; pplog; tokens; _ } as doc =
-      Lsp_server.find_document document_id registry in
-    f ~project ~textdoc ~pplog ~tokens @@ Lsp_document.retrieve_parsed_data doc
+let request_failed fmt =
+  error ~code:Jsonrpc.Response.Error.Code.RequestFailed fmt
+let internal_error fmt =
+  error ~code:Jsonrpc.Response.Error.Code.InternalError fmt
+
+(** Catch generic exception cases, and report errors using {!error} above *)
+let try_doc ~f registry doc_id =
+  let doc =
+    try Lsp_server.find_document doc_id registry
+    with Not_found ->
+      request_failed
+        "Received a request about a document that has not been opened yet (uri = \
+         %s) --- possible cause is the client did not manage to send the didOpen \
+         notification; this may happen due to unhandled character encodings.\
+        " (DocumentUri.to_string doc_id.TextDocumentIdentifier.uri)
+  in
+  try f ~doc
   with e ->
-    Lsp_io.pretty_notification ~type_:Warning "Caught exception: %a" Fmt.exn e;
-    on_error
+    internal_error "Caught exception: %a" Fmt.exn e
 
-(** Handling requests *)
+(** Same as [try_doc], with some additional document data *)
+let try_with_document_data ~f =
+  try_doc ~f:(fun ~doc -> f ~doc @@ Lsp_document.retrieve_parsed_data doc)
+
+(** {2 Handling requests} *)
 
 (* Client capabilities are to be used for special request response, for example
    a definition request can be answered with a LocationLink iff the client
@@ -128,8 +148,7 @@ let lookup_definition_in_doc
 
 let handle_definition registry (params: DefinitionParams.t) =
   try_with_document_data registry params.textDocument
-    ~f:(fun ~project:_ ~textdoc:_ ~pplog:_ ~tokens:_ ->
-        lookup_definition_in_doc params)
+    ~f:(fun ~doc:_ -> lookup_definition_in_doc params)
 
 let lookup_references_in_doc
     ReferenceParams.{ textDocument = doc; position; context; _ }
@@ -163,8 +182,7 @@ let lookup_references_in_doc
 
 let handle_references state (params: ReferenceParams.t) =
   try_with_document_data state params.textDocument
-    ~f:(fun ~project:_ ~textdoc:_ ~pplog:_ ~tokens:_ ->
-        lookup_references_in_doc params)
+    ~f:(fun ~doc:_ -> lookup_references_in_doc params)
 
 
 (*Remark:
@@ -215,20 +233,27 @@ let handle_formatting registry params =
       ~end_:(Position.create ~character:width ~line:length)
   in
   let path = Lsp.Uri.to_path doc.uri in
-  let newText =
-    Cobol_indent.indent_range'
-      ~source_format:project.source_format
-      ~indent_config:None
-      ~file:path
-      ~range:None
-  in
-  Some [TextEdit.create ~newText ~range:edit_range]
+  try
+    let newText =
+      Cobol_indent.indent_range'
+        ~source_format:project.source_format
+        ~indent_config:None
+        ~file:path
+        ~range:None
+    in
+    Some [TextEdit.create ~newText ~range:edit_range]
+  with Failure msg ->
+    internal_error "Formatting error: %s" msg
 
 let handle_semantic_tokens_full registry (params: SemanticTokensParams.t) =
   try_with_document_data registry params.textDocument
-    ~f:begin fun ~project:_ ~textdoc:_ ~pplog:_ ~tokens Lsp_document.{ ast; _ } ->
+    ~f:begin fun ~doc:{ artifacts = { pplog; tokens; comments };
+                        _ } Lsp_document.{ ast; _ } ->
       let filename = Lsp.Uri.to_path params.textDocument.uri in
-      let data = Lsp_semtoks.data ~filename (Lazy.force tokens) ast in
+      let data =
+        Lsp_semtoks.data ~filename ~pplog ~comments
+          ~tokens:(Lazy.force tokens) ~ptree:ast
+      in
       Some (SemanticTokens.create ~data ())
     end
 
@@ -247,28 +272,31 @@ let handle_hover registry (params: HoverParams.t) =
     let range = Lsp_position.range_of_srcloc_in ~filename loc in
     Some (Hover.create () ~contents:(`MarkupContent content) ~range)
   in
-  let Lsp_document.{ project; pplog; _ } =
-    Lsp_server.find_document params.textDocument registry in
-  match find_hovered_pplog_event pplog with
-  | Some Replacement { matched_loc = loc; replacement_text; _ } ->
-      Pretty.string_to (hover_markdown ~loc) "``@[<h>%a@]``"
-        Cobol_preproc.Text.pp_text replacement_text
-  | Some FileCopy { copyloc = loc; status = CopyDone lib | CyclicCopy lib } ->
-      let text = EzFile.read_file lib in
-      (* TODO: grab source-format from preprocessor state? *)
-      let module Config = (val project.cobol_config) in
-      let mdlang = match Config.format#value with
-        | SF (SFFree | SFVariable | SFCOBOLX) -> "cobolfree"
-        | SF _ | Auto -> "cobol"
-      in
-      Pretty.string_to (hover_markdown ~loc) "```%s\n%s\n```" mdlang text
-  | Some FileCopy { status = MissingCopy _; _ } | None ->
-      None
+  try_doc registry params.textDocument
+    ~f:begin fun ~doc:{ project; artifacts = { pplog; _ }; _ } ->
+      match find_hovered_pplog_event pplog with
+      | Some Replacement { matched_loc = loc;
+                           replacement_text; _ } ->
+          Pretty.string_to (hover_markdown ~loc) "``@[<h>%a@]``"
+            Cobol_preproc.Text.pp_text replacement_text
+      | Some FileCopy { copyloc = loc;
+                        status = CopyDone lib | CyclicCopy lib } ->
+          let text = EzFile.read_file lib in
+          (* TODO: grab source-format from preprocessor state? *)
+          let module Config = (val project.cobol_config) in
+          let mdlang = match Config.format#value with
+            | SF (SFFree | SFVariable | SFCOBOLX) -> "cobolfree"
+            | SF _ | Auto -> "cobol"
+          in
+          Pretty.string_to (hover_markdown ~loc) "```%s\n%s\n```" mdlang text
+      | Some FileCopy { status = MissingCopy _; _ } | None ->
+          None
+    end
 
 let handle_completion registry (params:CompletionParams.t) =
   let open Lsp_completion in
   try_with_document_data registry params.textDocument
-    ~f:begin fun ~project:_ ~textdoc ~pplog:_ ~tokens:_ { ast; _ } ->
+    ~f:begin fun ~doc:{ textdoc; _ } { ast; _ } ->
       let items = completion_items textdoc params.position ast in
       let completionlist = CompletionList.create ~isIncomplete:false ~items () in
       Some (`CompletionList completionlist)
@@ -276,8 +304,9 @@ let handle_completion registry (params:CompletionParams.t) =
 
 let handle_shutdown registry =
   try Lsp_server.save_project_caches registry
-  with e -> Pretty.error "Exception caught while saving project caches: %a@.\
-                         " Fmt.exn e
+  with e ->
+    internal_error
+      "Exception caught while saving project caches: %a@." Fmt.exn e
 
 let on_request
   : type r. state -> r Lsp.Client_request.t ->
@@ -300,8 +329,7 @@ let on_request
     | TextDocumentRangeFormatting params ->
         Ok (handle_range_formatting registry params, state)
     | TextDocumentFormatting params ->
-        begin try Ok (handle_formatting registry params, state)
-        with Failure msg -> Error (FormattingError msg) end
+        Ok (handle_formatting registry params, state)
     | SemanticTokensFull params ->
         Ok (handle_semantic_tokens_full registry params, state)
     | TextDocumentHover hover_params ->
@@ -347,28 +375,28 @@ let on_request
     | WillRenameFiles  (* RenameFilesParams.t.t *) _
       ->
         Error (UnhandledRequest client_req)
-    | UnknownRequest { meth ; params=_ } ->
+    | UnknownRequest { meth; _ } ->
         Error (UnknownRequest meth)
 
-let handle req state =
+let handle (Jsonrpc.Request.{ id; _ } as req) state =
   match Lsp.Client_request.of_jsonrpc req with
+  | Error message ->
+      let code = Jsonrpc.Response.Error.Code.InvalidRequest in
+      let err = Jsonrpc.Response.Error.make ~message ~code () in
+      state, Jsonrpc.Response.(error id err)
   | Ok (E r) ->
-      let response, state =
-        match on_request state r ~id:req.id with
-        | Ok (reply, state) ->
-            let reply_json = Lsp.Client_request.yojson_of_result r reply in
-            Jsonrpc.Response.ok req.id reply_json, state
-        | Error server_error ->
-            let json_error =
-              Lsp_server.jsonrpc_of_error server_error req.method_ in
-            Jsonrpc.Response.error req.id json_error, state
-        | exception e ->
-            Jsonrpc.Response.error req.id @@ Jsonrpc.Response.Error.of_exn e, state
-      in
-      Lsp_io.send_response response;
-      state
-  | Error str ->
-      Pretty.failwith "Could not read request: %s" str
+      match on_request state r ~id with
+      | Ok (reply, state) ->
+          let reply_json = Lsp.Client_request.yojson_of_result r reply in
+          state, Jsonrpc.Response.ok id reply_json
+      | Error server_error ->
+          state,
+          Jsonrpc.Response.error id @@
+          Lsp_server.jsonrpc_of_error server_error req.method_
+      | exception Jsonrpc.Response.Error.E e ->
+          state, Jsonrpc.Response.error id e
+      | exception e ->
+          state, Jsonrpc.Response.(error id @@ Error.of_exn e)
 
 module INTERNAL = struct
   let lookup_definition = handle_definition
diff --git a/src/lsp/cobol_lsp/lsp_request.mli b/src/lsp/cobol_lsp/lsp_request.mli
index 2bd0cbbf5..03d6cc500 100644
--- a/src/lsp/cobol_lsp/lsp_request.mli
+++ b/src/lsp/cobol_lsp/lsp_request.mli
@@ -11,7 +11,7 @@
 (*                                                                        *)
 (**************************************************************************)
 
-val handle: Jsonrpc.Request.t -> (Lsp_server.state as 's) -> 's
+val handle: Jsonrpc.Request.t -> (Lsp_server.state as 's) -> 's * Jsonrpc.Response.t
 
 module INTERNAL: sig
   val lookup_definition
diff --git a/src/lsp/cobol_lsp/lsp_semtoks.ml b/src/lsp/cobol_lsp/lsp_semtoks.ml
index d952aee8e..00e95568f 100644
--- a/src/lsp/cobol_lsp/lsp_semtoks.ml
+++ b/src/lsp/cobol_lsp/lsp_semtoks.ml
@@ -36,7 +36,7 @@ module TOKTYP = struct
   let namespace = mk "namespace"
   let decorator = mk "decorator"
   (* let modifier  = mk "modifier" *)
-  (* let comment   = mk "comment" *)
+  let comment   = mk "comment"
   (* "class"; *)
   (* "enum"; *)
   (* "interface"; *)
@@ -97,13 +97,16 @@ type semtok = {
   tokmods: token_modifiers;
 }
 
-let semtok lexloc ?(tokmods = TOKMOD.none) toktyp =
+let semtok ?(tokmods = TOKMOD.none) toktyp lexloc =
   let range = Lsp_position.range_of_lexloc lexloc in
   let line = range.start.line in
   let start = range.start.character in
   let length = range.end_.character - start in
   { line; start; length; toktyp; tokmods }
 
+let single_line_lexlocs_in ~filename =
+  Srcloc.shallow_single_line_lexlocs_in ~ignore_invalid_filename:true ~filename
+
 type token_category =
   | ProgramName
   | ParagraphName
@@ -118,41 +121,41 @@ type token_category =
   | MnemonicName
   | FileName
 
-let semantic_visitor ~filename =
+let semtoks_from_ptree ~filename ptree =
   let open Cobol_parser.PTree_visitor in
   let open Cobol_ast.Terms_visitor in
   let open Cobol_ast.Operands_visitor in
   let open Cobol_common.Visitor in
 
   let semtok_of lexloc category =
-    let semtok_of lexloc (toktyp, tokmods) =
-      semtok lexloc toktyp ~tokmods
+    let toktyp, tokmods = match category with
+      | ProgramName -> TOKTYP.string, TOKMOD.(union [definition; readonly])
+      | ParagraphName -> TOKTYP.function_, TOKMOD.(one definition)
+      | ProcName -> TOKTYP.function_, TOKMOD.none
+      | Parameter -> TOKTYP.parameter, TOKMOD.none
+      | DataDecl -> TOKTYP.variable, TOKMOD.(one declaration)
+      | DataLevel -> TOKTYP.decorator, TOKMOD.none
+      | Var -> TOKTYP.variable, TOKMOD.none
+      | VarModif -> TOKTYP.variable, TOKMOD.(one modification)
+      | ReportName
+      | ExceptionName
+      | MnemonicName
+      | FileName -> TOKTYP.variable, TOKMOD.(one readonly)
     in
-    semtok_of lexloc @@ match category with
-    | ProgramName -> TOKTYP.string, TOKMOD.(union [definition; readonly])
-    | ParagraphName -> TOKTYP.function_, TOKMOD.(one definition)
-    | ProcName -> TOKTYP.function_, TOKMOD.none
-    | Parameter -> TOKTYP.parameter, TOKMOD.none
-    | DataDecl -> TOKTYP.variable, TOKMOD.(one declaration)
-    | DataLevel -> TOKTYP.decorator, TOKMOD.none
-    | Var -> TOKTYP.variable, TOKMOD.none
-    | VarModif -> TOKTYP.variable, TOKMOD.(one modification)
-    | ReportName
-    | ExceptionName
-    | MnemonicName
-    | FileName -> TOKTYP.variable, TOKMOD.(one readonly)
+    semtok ~tokmods toktyp lexloc
   in
   let add_name' name toktyp acc =
-    match Srcloc.lexloc_in ~filename ~@name with
-    | lexloc -> List.cons (semtok_of lexloc toktyp) acc
-    | exception Invalid_argument _ -> acc
+    List.rev_map
+      (fun lexloc -> semtok_of lexloc toktyp)
+      (single_line_lexlocs_in ~filename ~@name) @ acc
   in
   let rec add_qualname (qn:Cobol_ast.qualname) toktyp acc =
     match qn with
     | Name name ->
         add_name' name toktyp acc
     | Qual (name, qn) ->
-        add_name' name toktyp acc |> add_qualname qn toktyp
+        add_name' name toktyp acc |>
+        add_qualname qn toktyp
   in
   let add_ident (id:Cobol_ast.ident) toktyp acc =
     match id with
@@ -176,35 +179,38 @@ let semantic_visitor ~filename =
     method! fold_program_unit {program_name; _} acc = acc
       |> add_name' program_name ProgramName
       |> Visitor.do_children
-      (* we call do_children, so we must ensure that
-         the fold_name' does nothing,
-         otherwise, there will be token overlap.
+    (* we call do_children, so we must ensure that
+       the fold_name' does nothing,
+       otherwise, there will be token overlap.
 
-         Or we can override this method fold_program_unit to explicitly
-         fold its every child and return Visitor.skip_children x.
-         But by doing that for every method(which we need to override),
-         we have to write a great amount of code... like rewriting
-         the code of Cobol_ast.
+       Or we can override this method fold_program_unit to explicitly
+       fold its every child and return Visitor.skip_children x.
+       But by doing that for every method(which we need to override),
+       we have to write a great amount of code... like rewriting
+       the code of Cobol_ast.
 
-      *)
+    *)
 
     (*TODO: File/Report section*)
 
+    method! fold_name' n acc =
+      Visitor.skip_children @@ add_name' n Var acc
+
     (* data-name *)
     method! fold_data_name data_name acc =
       match data_name with
       | DataName n -> acc
-        |> add_name' n DataDecl
-        |> Visitor.skip_children
+          |> add_name' n DataDecl
+          |> Visitor.skip_children
       | _ ->
-        Visitor.do_children acc
+          Visitor.do_children acc
 
     method! fold_rename_item {rename_level; rename_to;
                               rename_renamed; rename_through } acc = acc
-      |> add_name' rename_to DataDecl
       (*|> Visitor.do_children*)
       (* We can remove the code below and return do_children directly*)
       |> fold_data_level' self rename_level
+      |> add_name' rename_to DataDecl
       |> fold_qualname self rename_renamed
       |> fold_qualname_opt self rename_through
       |> Visitor.skip_children
@@ -214,21 +220,20 @@ let semantic_visitor ~filename =
                                        condition_name_values;
                                        condition_name_alphabet;
                                        condition_name_when_false } acc = acc
-      |> add_name' condition_name DataDecl
-      (*|> Visitor.do_children *)
       |> fold_data_level' self condition_name_level
+      |> add_name' condition_name DataDecl
       |> fold_list ~fold:fold_condition_name_value self condition_name_values
       |> fold_name'_opt self condition_name_alphabet
       |> fold_literal_opt self condition_name_when_false
       |> Visitor.skip_children
 
-    method! fold_data_clause dc acc =
-      match dc with
-      | DataRedefines name -> acc
-          |> add_name' name Var
-          |> Visitor.skip_children
-      | _ ->
-          Visitor.skip_children acc (*Not implmented*)
+    (* method! fold_data_clause dc acc = *)
+    (*   match dc with *)
+    (*   | DataRedefines name -> acc *)
+    (*       |> add_name' name Var *)
+    (*       |> Visitor.skip_children *)
+    (*   | _ -> *)
+    (*       Visitor.skip_children acc (\*Not implmented*\) *)
 
     (* data-level *)
     (* TODO: condition_name ??*)
@@ -269,10 +274,10 @@ let semantic_visitor ~filename =
 
     (* Statement *)
     (* distinguish
-      1 variable
-      2 variable modified
-      3 procedure-name
-      4 report-name/file-name/exception-name/mnemonic-name *)
+       1 variable
+       2 variable modified
+       3 procedure-name
+       4 report-name/file-name/exception-name/mnemonic-name *)
     (*TODO: maybe finer analysis*)
 
     method! fold_accept' {payload = accept_stmt; _} acc =
@@ -371,9 +376,9 @@ let semantic_visitor ~filename =
       |> Visitor.skip_children
 
     method! fold_tallying { tallying_target; tallying_clauses } acc = acc
-        |> add_qualname tallying_target.ident_name VarModif
-        |> fold_list ~fold:fold_tallying_clause' self tallying_clauses
-        |> Visitor.skip_children
+      |> add_qualname tallying_target.ident_name VarModif
+      |> fold_list ~fold:fold_tallying_clause' self tallying_clauses
+      |> Visitor.skip_children
 
     method! fold_inspect' { payload = { inspect_item; inspect_spec }; _} acc = acc
       |> add_ident inspect_item VarModif
@@ -400,15 +405,6 @@ let semantic_visitor ~filename =
       |> fold_option ~fold:fold_file_option self named_file_option
       |> Visitor.skip_children
 
-    method! fold_perform_target perform_target acc =
-      match perform_target with
-      | PerformOutOfLine { procedure_start; procedure_end } -> acc
-          |> add_qualname procedure_start ProcName
-          |> add_option add_qualname procedure_end ProcName
-          |> Visitor.skip_children
-      | PerformInline _ ->
-          Visitor.do_children acc
-
     method! fold_varying_phrase { varying_ident; varying_from;
                                   varying_by; varying_until } acc = acc
       |> add_ident varying_ident VarModif
@@ -512,8 +508,8 @@ let semantic_visitor ~filename =
                                           string_target;
                                           string_pointer;
                                           string_on_overflow}; _} acc = acc
-      |> add_ident string_target VarModif
       |> fold_list ~fold:fold_string_source self string_sources
+      |> add_ident string_target VarModif
       |> fold_option ~fold:fold_ident self string_pointer
       |> fold_dual_handler self string_on_overflow
       |> Visitor.skip_children
@@ -539,73 +535,80 @@ let semantic_visitor ~filename =
     (*TODO: Validate *)
     (*TODO: Merge, Sort*)
 
-    (* All qualname not colored yet will be marked as normal variable *)
-    method! fold_qualname qn acc = acc
-      |> add_qualname qn Var
-      |> Visitor.skip_children
+    (* (\* All qualname not colored yet will be marked as normal variable *\) *)
+    (* method! fold_qualname qn acc = acc *)
+    (*   |> add_qualname qn Var *)
+    (*   |> Visitor.skip_children *)
+
+  end) ptree [] |> List.rev
+
+let semtoks_of_comments ~filename comments = comments |>
+  List.filter_map begin function
+    | Cobol_preproc.Text.{ comment_loc = s, _ as lexloc; _ }
+      when s.Lexing.pos_fname = filename ->
+        Some (semtok TOKTYP.comment lexloc)
+    | _ ->
+        None
+  end
+
+(** [semtoks_of_non_ambigious_tokens ~filename tokens] returns tokens that do
+    not need to have more analyzing to get their type. *)
+let semtoks_of_non_ambigious_tokens ~filename tokens =
+  List.rev @@ List.fold_left begin fun acc { payload = token; loc } ->
+    let semtok_infos = match token with
+      | WORD _ | WORD_IN_AREA_A _ -> None
+      | ALPHANUM _ | ALPHANUM_PREFIX _ ->
+          Some (TOKTYP.string, TOKMOD.none)
+      | BOOLIT _
+      | HEXLIT _ | NULLIT _
+      | NATLIT _ | SINTLIT _
+      | FIXEDLIT _ | FLOATLIT _
+      | DIGITS _
+      | EIGHTY_EIGHT ->
+          Some (TOKTYP.number, TOKMOD.none)
+      | PICTURE_STRING _ ->
+          Some (TOKTYP.type_, TOKMOD.(one declaration))
+      (* | EQUAL | PLUS | MINUS  *)
+      | AMPERSAND | ASTERISK | COLON | DASH_SIGN | DOUBLE_ASTERISK | DOUBLE_COLON
+      | EQ | GE | GT | LE | LPAR | LT | NE | PLUS_SIGN | RPAR | SLASH ->
+          Some (TOKTYP.operator, TOKMOD.none)
+      | PARAGRAPH | STATEMENT | PROGRAM |SECTION | DIVISION ->
+          Some (TOKTYP.namespace, TOKMOD.none)
+      | ACCEPT | ACCESS | ADD | ALLOCATE | ALTER | APPLY | ARE | ASSIGN | CALL | CANCEL | CHAIN | CLOSE
+      | COMMIT | COMPUTE | CONTINUE | CONTROL | CONTROLS | COPY | COPY_SELECTION | COUNT | CYCLE
+      | DELETE | DESTROY | DISABLE | DISP | DISPLAY | DISPLAY_1 | DISPLAY_COLUMNS | DISPLAY_FORMAT
+      | DIVIDE | ENABLE | ENSURE_VISIBLE | ENTER | ERASE | ESCAPE | EVALUATE | EXAMINE | EXHIBIT | EXIT
+      | FREE | GENERATE | GET | GO | GOBACK | GO_BACK | GO_FORWARD | GO_HOME | GO_SEARCH | IF | IGNORE
+      | INITIALIZE | INITIATE | INSPECT | INVOKE | LEAVE | LOCK | LOCK_HOLDING | MERGE | MODIFY | MOVE
+      | MULTIPLY | NOTIFY | NOTIFY_CHANGE | OPEN | OUTPUT | OVERRIDE | PARSE | PERFORM | PRINT
+      | PRINT_NO_PROMPT | PRINT_PREVIEW | PROCEED | PURGE | RAISE | READ | RECEIVE | REFRESH
+      | RELEASE | REPLACE | RERUN | RESERVE | RESET | RESUME | RETRY | RETURN | REWRITE | ROLLBACK
+      | SEARCH | SELECT | SELECT_ALL | SEND | SET | SORT | SORT_MERGE | SORT_ORDER | STDCALL | START
+      | STEP | STOP | STRING | SUBTRACT | SUPPRESS | TEST | TERMINATE | TRANSFORM | UNLOCK | UNSTRING
+      | UPDATE | USE | USE_ALT | USE_RETURN | USE_TAB | VALIDATE | VALIDATE_STATUS | WRAP | WRITE
+      | END_ACCEPT | END_ADD | END_CALL | END_COMPUTE | END_DELETE | END_DISPLAY | END_DIVIDE | END_EVALUATE
+      | END_IF | END_MULTIPLY | END_PERFORM | END_READ | END_RETURN | END_REWRITE | END_SEARCH | END_START
+      | END_STRING | END_SUBTRACT | END_UNSTRING | END_WRITE ->
+          Some (TOKTYP.function_, TOKMOD.(one defaultLibrary))
+      | _ ->
+          Some (TOKTYP.keyword, TOKMOD.none)
+    in
+    match semtok_infos with
+    | None -> acc
+    | Some (toktyp, tokmods) ->
+        List.rev_map (semtok toktyp ~tokmods)
+          (single_line_lexlocs_in ~filename loc) @ acc
+  end [] tokens
 
-    end)
-
-(** [make_non_ambigious tokens] returns tokens that do not need to have more analyzing to get their
-    type. *)
-let make_non_ambigious ~filename tokens = tokens |>
-  List.filter_map
-    (fun { payload; loc } ->
-       try Some (payload, Srcloc.lexloc_in ~filename loc) with _ -> None) |>
-  List.filter_map
-    (fun (token, lexloc) ->
-       match token with
-       | WORD _ | WORD_IN_AREA_A _ -> None
-       | ALPHANUM _ | ALPHANUM_PREFIX _ ->
-           Some (semtok lexloc TOKTYP.string)
-       | BOOLIT _
-       | HEXLIT _ | NULLIT _
-       | NATLIT _ | SINTLIT _
-       | FIXEDLIT _ | FLOATLIT _
-       | DIGITS _
-       | EIGHTY_EIGHT ->
-           Some (semtok lexloc TOKTYP.number)
-       | PICTURE_STRING _ ->
-           Some (semtok lexloc TOKTYP.type_
-                   ~tokmods:TOKMOD.(one declaration))
-       (* | EQUAL | PLUS | MINUS  *)
-       | AMPERSAND | ASTERISK | COLON | DASH_SIGN | DOUBLE_ASTERISK | DOUBLE_COLON
-       | EQ | GE | GT | LE | LPAR | LT | NE | PLUS_SIGN | RPAR | SLASH ->
-           Some (semtok lexloc TOKTYP.operator)
-       | PARAGRAPH | STATEMENT | PROGRAM |SECTION | DIVISION ->
-           Some (semtok lexloc TOKTYP.namespace)
-       | ACCEPT | ACCESS | ADD | ALLOCATE | ALTER | APPLY | ARE | ASSIGN | CALL | CANCEL | CHAIN | CLOSE
-       | COMMIT | COMPUTE | CONTINUE | CONTROL | CONTROLS | COPY | COPY_SELECTION | COUNT | CYCLE
-       | DELETE | DESTROY | DISABLE | DISP | DISPLAY | DISPLAY_1 | DISPLAY_COLUMNS | DISPLAY_FORMAT
-       | DIVIDE | ENABLE | ENSURE_VISIBLE | ENTER | ERASE | ESCAPE | EVALUATE | EXAMINE | EXHIBIT | EXIT
-       | FREE | GENERATE | GET | GO | GOBACK | GO_BACK | GO_FORWARD | GO_HOME | GO_SEARCH | IF | IGNORE
-       | INITIALIZE | INITIATE | INSPECT | INVOKE | LEAVE | LOCK | LOCK_HOLDING | MERGE | MODIFY | MOVE
-       | MULTIPLY | NOTIFY | NOTIFY_CHANGE | OPEN | OUTPUT | OVERRIDE | PARSE | PERFORM | PRINT
-       | PRINT_NO_PROMPT | PRINT_PREVIEW | PROCEED | PURGE | RAISE | READ | RECEIVE | REFRESH
-       | RELEASE | REPLACE | RERUN | RESERVE | RESET | RESUME | RETRY | RETURN | REWRITE | ROLLBACK
-       | SEARCH | SELECT | SELECT_ALL | SEND | SET | SORT | SORT_MERGE | SORT_ORDER | STDCALL | START
-       | STEP | STOP | STRING | SUBTRACT | SUPPRESS | TEST | TERMINATE | TRANSFORM | UNLOCK | UNSTRING
-       | UPDATE | USE | USE_ALT | USE_RETURN | USE_TAB | VALIDATE | VALIDATE_STATUS | WRAP | WRITE
-       | END_ACCEPT | END_ADD | END_CALL | END_COMPUTE | END_DELETE | END_DISPLAY | END_DIVIDE | END_EVALUATE
-       | END_IF | END_MULTIPLY | END_PERFORM | END_READ | END_RETURN | END_REWRITE | END_SEARCH | END_START
-       | END_STRING | END_SUBTRACT | END_UNSTRING | END_WRITE ->
-           Some (semtok lexloc TOKTYP.function_
-                   ~tokmods:TOKMOD.(one defaultLibrary))
-       | _ ->
-           Some (semtok lexloc TOKTYP.keyword))
-
-let compare_semtoks first second =      (* TODO: use Lexing.position, and then a
-                                           comparison on `pos_cnum` only? *)
+let compare_semtoks first second =
   let cmp = Stdlib.compare first.line second.line in
   if cmp = 0
   then Stdlib.compare first.start second.start
   else cmp
 
 let relative_semtoks semtoks =
-  let semtoks = Array.of_list semtoks in
-  Array.fast_sort compare_semtoks semtoks;
-  let data = Array.make (5 * Array.length semtoks) 0 in
-  ignore @@ Array.fold_left begin fun (i, prev_line, prev_start) semtok ->
+  let data = Array.make (5 * List.length semtoks) 0 in
+  ignore @@ List.fold_left begin fun (i, prev_line, prev_start) semtok ->
     data.(5 * i + 0) <- semtok.line - prev_line;
     data.(5 * i + 1) <- semtok.start -
                         if semtok.line = prev_line then prev_start else 0;
@@ -616,8 +619,39 @@ let relative_semtoks semtoks =
   end (0, 0, 0) semtoks;
   data
 
-let data ~filename tokens ptree : int array =
-  tokens
-  |> make_non_ambigious ~filename
-  |> semantic_visitor ~filename ptree
-  |> relative_semtoks
+let ensure_sorted name ~filename cmp l =
+  let rec unsorted_pair = function
+    | [] | [_] -> None
+    | x :: (y :: _ as tl) when cmp x y <= 0 -> unsorted_pair tl
+    | x ::  y :: _ -> Some (x, y)
+  in
+  match unsorted_pair l with
+  | None -> l
+  | Some (x, y) ->
+      Pretty.error "@[<2>** Internal@ note:@ semantic@ tokens@ in@ %s@ are@ \
+                    not@ sorted.@ Two@ offenders@ are:@]@\n%a%a@." name
+        Srcloc.pp_raw_loc (filename,
+                           (x.line + 1, x.start),
+                           (x.line + 1, x.start + x.length))
+        Srcloc.pp_raw_loc (filename,
+                           (y.line + 1, y.start),
+                           (y.line + 1, y.start + y.length));
+      List.fast_sort cmp l
+
+
+let data ~filename ~tokens ~pplog:_ ~comments ~ptree : int array =
+  let semtoks1 = semtoks_of_non_ambigious_tokens ~filename tokens in
+  let semtoks2 = semtoks_from_ptree ~filename ptree in
+  let semtoks3 = semtoks_of_comments ~filename comments in
+  (* NB: In *principle* all those lists are already sorted w.r.t lexical
+     locations in [filename].  We just check that for now and raise a warning,
+     in case. *)
+  (* let semtoks1 = List.fast_sort compare_semtoks semtoks1 *)
+  (* and semtoks2 = List.fast_sort compare_semtoks semtoks2 *)
+  (* and semtoks3 = List.fast_sort compare_semtoks semtoks3 in *)
+  let semtoks1 = ensure_sorted "nonambiguous" ~filename compare_semtoks semtoks1
+  and semtoks2 = ensure_sorted "ptree" ~filename compare_semtoks semtoks2
+  and semtoks3 = ensure_sorted "comments" ~filename compare_semtoks semtoks3 in
+  relative_semtoks
+    List.(merge compare_semtoks semtoks1 @@
+          merge compare_semtoks semtoks2 semtoks3)
diff --git a/src/lsp/cobol_lsp/lsp_semtoks.mli b/src/lsp/cobol_lsp/lsp_semtoks.mli
index 07f0bc125..6b684c9f6 100644
--- a/src/lsp/cobol_lsp/lsp_semtoks.mli
+++ b/src/lsp/cobol_lsp/lsp_semtoks.mli
@@ -13,8 +13,13 @@
 
 val token_types: string list
 val token_modifiers: string list
+
+(* TODO: once we decide to fix the min OCaml version to >=4.14, we can upgrade
+   to lsp>=16, and avoid having to use an array below. *)
 val data
   : filename: string
-  -> Cobol_parser.tokens_with_locs
-  -> Lsp_imports.PTREE.compilation_group
+  -> tokens: Cobol_parser.tokens_with_locs
+  -> pplog: Cobol_preproc.log
+  -> comments: Cobol_preproc.comments
+  -> ptree: Lsp_imports.PTREE.compilation_group
   -> int array
diff --git a/src/lsp/cobol_lsp/lsp_server.ml b/src/lsp/cobol_lsp/lsp_server.ml
index 8a413e542..06ab11e8e 100644
--- a/src/lsp/cobol_lsp/lsp_server.ml
+++ b/src/lsp/cobol_lsp/lsp_server.ml
@@ -45,7 +45,8 @@ module TYPES = struct
     | InvalidStatus of state
     | UnhandledRequest of 'a Lsp.Client_request.t
     | UnknownRequest of string
-    | FormattingError of string
+
+  exception Document_not_found of TextDocumentIdentifier.t
 
 end
 include TYPES
@@ -158,24 +159,21 @@ let add (DidOpenTextDocumentParams.{ textDocument = { uri; text; _ };
   in
   aux ~try_cache:true registry
 
+(** Raises {!Document_not_found} if the document is not currently opened. *)
+let find_document (TextDocumentIdentifier.{ uri; _ } as doc) { docs; _ } =
+  try URIMap.find uri docs
+  with Not_found -> raise @@ Document_not_found doc
+
 let update DidChangeTextDocumentParams.{ textDocument = { uri; _ };
                                          contentChanges; _ } registry =
-  try
-    let doc = URIMap.find uri registry.docs in
-    let doc = Lsp_document.update doc contentChanges in
-    let registry = dispatch_diagnostics doc registry in
-    add_or_replace_doc doc registry
-  with Not_found ->
-    Pretty.failwith "Document@ %s@ was@ not@ opened@ before@ changes"
-      (DocumentUri.to_string uri)
+  let doc = find_document TextDocumentIdentifier.{ uri } registry in
+  let doc = Lsp_document.update doc contentChanges in
+  let registry = dispatch_diagnostics doc registry in
+  add_or_replace_doc doc registry
 
 let remove DidCloseTextDocumentParams.{ textDocument = { uri } } registry =
   { registry with docs = URIMap.remove uri registry.docs }
 
-(** Raises {!Not_found} if the document is not currently opened. *)
-let find_document TextDocumentIdentifier.{ uri; _ } { docs; _ } =
-  URIMap.find uri docs
-
 (** {2 Miscellaneous} *)
 
 let jsonrpc_of_error error method_ =
@@ -194,7 +192,5 @@ let jsonrpc_of_error error method_ =
         RequestFailed, Fmt.str "Unhandled request: %s" method_
     | UnknownRequest method_ ->
         MethodNotFound, Fmt.str "Unknown request method: %s" method_
-    | FormattingError msg ->
-        RequestFailed, Fmt.str "Formatting request error: %s" msg
   in
   Jsonrpc.Response.Error.make ~code ~message ()
diff --git a/src/lsp/cobol_lsp/lsp_server.mli b/src/lsp/cobol_lsp/lsp_server.mli
index c57115aa7..d8f46dc8f 100644
--- a/src/lsp/cobol_lsp/lsp_server.mli
+++ b/src/lsp/cobol_lsp/lsp_server.mli
@@ -42,7 +42,8 @@ module TYPES: sig
     | InvalidStatus of state
     | UnhandledRequest of 'a Lsp.Client_request.t
     | UnknownRequest of string
-    | FormattingError of string
+
+  exception Document_not_found of Lsp.Types.TextDocumentIdentifier.t
 
 end
 include module type of TYPES
diff --git a/src/lsp/cobol_lsp/lsp_server_loop.ml b/src/lsp/cobol_lsp/lsp_server_loop.ml
index 9e39aea55..5192b6aff 100644
--- a/src/lsp/cobol_lsp/lsp_server_loop.ml
+++ b/src/lsp/cobol_lsp/lsp_server_loop.ml
@@ -48,21 +48,33 @@ let config ~project_config_filename ~relative_work_dirname =
     request.  Returns [Ok ()] if the server ran and shut down properly, or
     [Error error_message] otherwise. *)
 let run ~config =
-  let process_msg = function
+  let rec loop state =
+    match Lsp_io.read_message () with
     | Jsonrpc.Packet.Notification n ->
-        Lsp_notif.handle n
-    | Request r ->
-        Lsp_request.handle r
-    | _ ->
-        Fun.id
-  in
-  let rec loop status =
-    let status = match Lsp_io.read_message () with
-      | Error e -> Jsonrpc.Response.Error.raise e
-      | Ok m -> process_msg m status
-    in
-    match status with
-    | Exit code -> code
-    | _ -> loop status
+        continue @@ Lsp_notif.handle n state
+    | Jsonrpc.Packet.Request r ->
+        continue @@ reply @@ Lsp_request.handle r state
+    | Jsonrpc.Packet.Batch_call calls ->
+        batch calls state
+    | Jsonrpc.Packet.Response _ | Batch_response _ ->
+        Pretty.error "Response@ recieved@ unexpectedly@.";
+        continue state
+    | exception Lsp_io.Parse_error msg ->
+        Lsp_io.pretty_notification ~type_:Error "%s" msg;
+        Error msg                                                (* exit loop *)
+  and batch calls state =
+    match calls with
+    | [] ->
+        continue state
+    | `Notification n :: calls' ->
+        batch calls' @@ Lsp_notif.handle n state
+    | `Request n :: calls' ->
+        batch calls' @@ reply @@ Lsp_request.handle n state
+  and reply (state, response) =
+    Lsp_io.send_response response;
+    state
+  and continue = function
+    | Lsp_server.Exit code -> code                                (* exit loop *)
+    | state -> loop state
   in
   loop (NotInitialized config)
diff --git a/src/lsp/cobol_parser/cobol_parser.ml b/src/lsp/cobol_parser/cobol_parser.ml
index 4ed6d1d10..9cce50219 100644
--- a/src/lsp/cobol_parser/cobol_parser.ml
+++ b/src/lsp/cobol_parser/cobol_parser.ml
@@ -42,8 +42,7 @@ type 'x source_handling = ?source_format:Cobol_config.source_format_spec -> 'x
 
 let parse_simple: _ source_handling = Parser_engine.parse_simple
 let parse_with_tokens: _ source_handling = Parser_engine.parse_with_tokens
-let parsed_tokens = Parser_engine.parsed_tokens
-let preproc_rev_log = Parser_engine.preproc_rev_log
+let parsing_artifacts = Parser_engine.parsing_artifacts
 
 (* --- *)
 
diff --git a/src/lsp/cobol_parser/grammar.mly b/src/lsp/cobol_parser/grammar.mly
index 8e77997ac..926f75ac1 100644
--- a/src/lsp/cobol_parser/grammar.mly
+++ b/src/lsp/cobol_parser/grammar.mly
@@ -3353,12 +3353,12 @@ let perform_statement :=
  | PERFORM; i = qualified_procedure_name;
    io = ro(pf(THROUGH,qualified_procedure_name));
    po = io(perform_phrase);
-   { Perform { perform_target = PerformOutOfLine { procedure_start = i;
-                                                   procedure_end = io };
-               perform_mode = po } }
+   { PerformTarget { perform_target = { procedure_start = i;
+                                        procedure_end = io };
+                     perform_mode = po } }
  | PERFORM; po = ro(perform_phrase); isl = imp_stmts; END_PERFORM;
-   { Perform { perform_target = PerformInline isl;
-               perform_mode = po } }
+   { PerformInline { perform_inline_mode = po;
+                     perform_statements = isl } }
 
 let perform_phrase :=
  | ~ = ident_or_integer; TIMES; <PerformNTimes>
diff --git a/src/lsp/cobol_parser/parser_engine.ml b/src/lsp/cobol_parser/parser_engine.ml
index 528ee1907..fe1f48854 100644
--- a/src/lsp/cobol_parser/parser_engine.ml
+++ b/src/lsp/cobol_parser/parser_engine.ml
@@ -40,9 +40,8 @@ module Make (Config: Cobol_config.T) = struct
       log of operations performed by the pre-processor.  An
       {!Cobol_common.Behaviors.amnesic} parser does not provide this ability,
       contrary to an {!Cobol_common.Behaviors.eidetic} parser.  This is
-      reflected in the final result (see {!parsed_result}), as {!parsed_tokens}
-      and {!preproc_rev_log} may only be called on results of eidetic
-      parsers. *)
+      reflected in the final result (see {!parsed_result}), as
+      {!parsing_artifacts} may only be called on results of eidetic parsers. *)
   type 'm state =
     {
       prev_limit: Cobol_preproc.Src_overlay.limit option; (* last right-limit *)
@@ -445,9 +444,12 @@ module Make (Config: Cobol_config.T) = struct
     | Amnesic ->
         Only res, all_diags ps
     | Eidetic ->
-        let tokens = Tokzr.parsed_tokens ps.preproc.tokzr
-        and log = Cobol_preproc.log ps.preproc.pp in
-        WithTokens (res, tokens, log), all_diags ps
+        let artifacts = {
+          tokens = Tokzr.parsed_tokens ps.preproc.tokzr;
+          pplog = Cobol_preproc.log ps.preproc.pp;
+          comments = Cobol_preproc.comments ps.preproc.pp;
+        } in
+        WithArtifacts (res, artifacts), all_diags ps
 
 end
 
@@ -499,12 +501,6 @@ let parse
 let parse_simple = parse ~memory:Amnesic
 let parse_with_tokens = parse ~memory:Eidetic
 
-let parsed_tokens
+let parsing_artifacts
   : (_, Cobol_common.Behaviors.eidetic) parsed_result -> _ = function
-  | { parsed_output = WithTokens (_, parsed_token_memory, _); _ } ->
-      parsed_token_memory
-
-let preproc_rev_log
-  : (_, Cobol_common.Behaviors.eidetic) parsed_result -> _ = function
-  | { parsed_output = WithTokens (_, _, preproc_rev_log); _ } ->
-      preproc_rev_log
+  | { parsed_output = WithArtifacts (_, artifacts); _ } -> artifacts
diff --git a/src/lsp/cobol_parser/parser_engine.mli b/src/lsp/cobol_parser/parser_engine.mli
index 20d82f080..0054a1ccf 100644
--- a/src/lsp/cobol_parser/parser_engine.mli
+++ b/src/lsp/cobol_parser/parser_engine.mli
@@ -27,7 +27,5 @@ val parse: memory: 'm Parser_options.memory -> 'm parsing_function
 val parse_simple: Cobol_common.Behaviors.amnesic parsing_function
 val parse_with_tokens: Cobol_common.Behaviors.eidetic parsing_function
 
-val parsed_tokens
-  : (_, Cobol_common.Behaviors.eidetic) parsed_result -> tokens_with_locs Lazy.t
-val preproc_rev_log
-  : (_, Cobol_common.Behaviors.eidetic) parsed_result -> Cobol_preproc.log
+val parsing_artifacts
+  : (_, Cobol_common.Behaviors.eidetic) parsed_result -> parsing_artifacts
diff --git a/src/lsp/cobol_parser/parser_options.ml b/src/lsp/cobol_parser/parser_options.ml
index b113cf5be..dc237d101 100644
--- a/src/lsp/cobol_parser/parser_options.ml
+++ b/src/lsp/cobol_parser/parser_options.ml
@@ -31,10 +31,16 @@ type 'a memory =
   | Eidetic: Cobol_common.Behaviors.eidetic memory
 
 type tokens_with_locs = Grammar_tokens.token with_loc list
+type parsing_artifacts =
+  {
+    tokens: tokens_with_locs Lazy.t;
+    pplog: Cobol_preproc.log;
+    comments: Cobol_preproc.comments
+  }
 type ('a, 'm) output =
   | Only: 'a ->
       ('a, Cobol_common.Behaviors.amnesic) output
-  | WithTokens: 'a * tokens_with_locs Lazy.t * Cobol_preproc.log ->
+  | WithArtifacts: 'a * parsing_artifacts ->
       ('a, Cobol_common.Behaviors.eidetic) output
 
 type ('a, 'm) parsed_result =
diff --git a/src/lsp/cobol_preproc/cobol_preproc.ml b/src/lsp/cobol_preproc/cobol_preproc.ml
index a425eaf96..ebcce066f 100644
--- a/src/lsp/cobol_preproc/cobol_preproc.ml
+++ b/src/lsp/cobol_preproc/cobol_preproc.ml
@@ -20,5 +20,7 @@ module Text_printer = Text_printer
 module Copybook = Copybook
 module Trace = Preproc_trace
 
+type text = Text.text
+type comments = Text.comments
 include Trace.TYPES
 include Preproc_engine
diff --git a/src/lsp/cobol_preproc/preproc.ml b/src/lsp/cobol_preproc/preproc.ml
index 09e39d8bf..584c18c0d 100644
--- a/src/lsp/cobol_preproc/preproc.ml
+++ b/src/lsp/cobol_preproc/preproc.ml
@@ -33,6 +33,8 @@ let srclex_lexbuf (Plx (_, lexbuf)) = lexbuf
 let srclex_pos pl = (srclex_lexbuf pl).Lexing.lex_curr_p
 let srclex_diags (Plx (pl, _)) =
   Src_lexing.diagnostics pl
+let srclex_comments (Plx (pl, _)) =
+  Src_lexing.comments pl
 let srclex_source_format (Plx (pl, _)) =
   Src_lexing.(source_format_spec @@ source_format pl)
 
diff --git a/src/lsp/cobol_preproc/preproc.mli b/src/lsp/cobol_preproc/preproc.mli
index b22d09741..9227c66ae 100644
--- a/src/lsp/cobol_preproc/preproc.mli
+++ b/src/lsp/cobol_preproc/preproc.mli
@@ -101,10 +101,6 @@ val apply_replacing
   -> text
   -> 'a
 
-val srclex_diags
-  : any_srclexer
-  -> Cobol_common.Diagnostics.Set.t
-
 val cdir_source_format
   : dialect: Cobol_config.dialect
   -> string with_loc
@@ -117,9 +113,6 @@ val with_source_format
   -> any_srclexer
   -> any_srclexer
 
-val srclex_pos
-  : any_srclexer
-  -> Lexing.position
 val srclex_from_file
   : source_format:Cobol_config.source_format
   -> string
@@ -134,6 +127,15 @@ val srclex_from_channel
   -> source_format:Cobol_config.source_format
   -> in_channel
   -> any_srclexer
+val srclex_diags
+  : any_srclexer
+  -> Cobol_common.Diagnostics.Set.t
+val srclex_pos
+  : any_srclexer
+  -> Lexing.position
+val srclex_comments
+  : any_srclexer
+  -> comments
 
 val next_source_line: any_srclexer -> any_srclexer * text
 val fold_source_lines: any_srclexer -> (text -> 'a -> 'a) -> 'a -> 'a
diff --git a/src/lsp/cobol_preproc/preproc_engine.ml b/src/lsp/cobol_preproc/preproc_engine.ml
index 1c97fd951..5859cd371 100644
--- a/src/lsp/cobol_preproc/preproc_engine.ml
+++ b/src/lsp/cobol_preproc/preproc_engine.ml
@@ -62,10 +62,10 @@ let diags { diags; srclex; _ } =
   DIAGS.Set.union diags @@ Preproc.srclex_diags srclex
 let add_diag lp d = { lp with diags = DIAGS.Set.cons d lp.diags }
 let add_diags lp d = { lp with diags = DIAGS.Set.union d lp.diags }
-let log { pplog; _ } = (* List.rev *) pplog
-(* let rev_log { pplog; _ } = pplog *)
+let log { pplog; _ } = pplog
 let srclexer { srclex; _ } = srclex
 let position { srclex; _ } = Preproc.srclex_pos srclex
+let comments { srclex; _ } = Preproc.srclex_comments srclex
 
 let with_srclex lp srclex =
   if lp.srclex == srclex then lp else { lp with srclex }
diff --git a/src/lsp/cobol_preproc/preproc_engine.mli b/src/lsp/cobol_preproc/preproc_engine.mli
index 44b4d7f0f..14bceb89b 100644
--- a/src/lsp/cobol_preproc/preproc_engine.mli
+++ b/src/lsp/cobol_preproc/preproc_engine.mli
@@ -31,6 +31,7 @@ val diags: preprocessor -> Cobol_common.Diagnostics.Set.t
 val add_diag: preprocessor -> Cobol_common.Diagnostics.t -> preprocessor
 val add_diags: preprocessor -> Cobol_common.Diagnostics.Set.t -> preprocessor
 val log: preprocessor -> Preproc_trace.log
+val comments: preprocessor -> Text.comments
 val srclexer: preprocessor -> Preproc.any_srclexer
 val position: preprocessor -> Lexing.position
 val next_sentence: preprocessor -> Text.text * preprocessor
diff --git a/src/lsp/cobol_preproc/src_lexing.ml b/src/lsp/cobol_preproc/src_lexing.ml
index d0d16fb2d..fb9936907 100644
--- a/src/lsp/cobol_preproc/src_lexing.ml
+++ b/src/lsp/cobol_preproc/src_lexing.ml
@@ -143,7 +143,7 @@ type 'k state =
     lex_prods: text;
     continued: continued;
     pseudotext: (srcloc * text) option;
-    comments: comment list;
+    comments: comments;
     cdir_seen: bool;
     newline: bool;
     diags: DIAGS.Set.t;
@@ -186,13 +186,9 @@ let init_state : 'k source_format -> 'k state = fun source_format ->
   }
 
 let diagnostics { diags; _ } = diags
-let comments { comments; _ } = comments
-
-let source_format { config = { source_format; _ }; _ } =
-  source_format
-
-let allow_debug { config = { debug; _ }; _ } =
-  debug
+let comments { comments; _ } = List.rev comments
+let source_format { config = { source_format; _ }; _ } = source_format
+let allow_debug { config = { debug; _ }; _ } = debug
 
 (* Just check there are no buffered stuffs.  *)
 let flushed = function
diff --git a/src/lsp/cobol_preproc/src_lexing.mli b/src/lsp/cobol_preproc/src_lexing.mli
index ec9566c60..e9e2fe394 100644
--- a/src/lsp/cobol_preproc/src_lexing.mli
+++ b/src/lsp/cobol_preproc/src_lexing.mli
@@ -55,7 +55,7 @@ type 'k state
 
 val init_state: 'k source_format -> 'k state
 val diagnostics: _ state -> Cobol_common.Diagnostics.Set.t
-val comments: _ state -> Text.comment list
+val comments: _ state -> Text.comments
 val source_format: 'k state -> 'k source_format
 val change_source_format: 'k state -> 'c source_format Cobol_common.Srcloc.with_loc
   -> ('c state, 'k state) result
diff --git a/src/lsp/cobol_preproc/text.mli b/src/lsp/cobol_preproc/text.mli
index e48c1490c..a7cbcc732 100644
--- a/src/lsp/cobol_preproc/text.mli
+++ b/src/lsp/cobol_preproc/text.mli
@@ -22,6 +22,7 @@ include module type of Text_types
    and type quotation = Text_types.quotation
    and type pseudotext = Text_types.pseudotext
    and type comment = Text_types.comment
+   and type comments = Text_types.comments
 
 val textwordp : text_word with_loc -> bool
 val textword_eqp : eq:string -> text_word with_loc -> bool
diff --git a/src/lsp/cobol_preproc/text_types.ml b/src/lsp/cobol_preproc/text_types.ml
index df1764b81..25e883df7 100644
--- a/src/lsp/cobol_preproc/text_types.ml
+++ b/src/lsp/cobol_preproc/text_types.ml
@@ -58,3 +58,4 @@ type comment =
     comment_kind: [`Line | `Floating];
     comment_contents: string;
   }
+and comments = comment list
diff --git a/src/lsp/cobol_typeck/cobol_typeck.ml b/src/lsp/cobol_typeck/cobol_typeck.ml
index f0dbac1cc..600fa77b8 100644
--- a/src/lsp/cobol_typeck/cobol_typeck.ml
+++ b/src/lsp/cobol_typeck/cobol_typeck.ml
@@ -1163,10 +1163,10 @@ let analyze_compilation_group ?(config = Cobol_config.default)
     Ok (Typeck.typeck_compilation_group cg, DIAGS.Set.none)
   in
   function
-  | { parsed_output = Only None | WithTokens (None, _, _);
+  | { parsed_output = Only None | WithArtifacts (None, _);
       parsed_diags; _ } ->
       Error parsed_diags
-  | { parsed_output = Only Some cg | WithTokens (Some cg, _, _);
+  | { parsed_output = Only Some cg | WithArtifacts (Some cg, _);
       parsed_diags; _ } ->
       match Cobol_common.catch_diagnostics analyze_cg cg with
       | Ok (res, diags) ->
diff --git a/test/cobol_parsing/parser_testing.ml b/test/cobol_parsing/parser_testing.ml
index 5d626f151..cce65ca4d 100644
--- a/test/cobol_parsing/parser_testing.ml
+++ b/test/cobol_parsing/parser_testing.ml
@@ -15,7 +15,7 @@ let show_parsed_tokens
     ?(verbose = false)
     ?(source_format = Cobol_config.(SF SFFixed))
     prog =
-  let { parsed_output = WithTokens (_, tokens, _log); _ } =
+  let { parsed_output = WithArtifacts (_, { tokens; _ }); _ } =
     Cobol_parser.parse_with_tokens ~verbose ~source_format
       ~recovery:(EnableRecovery { silence_benign_recoveries = false })
       ~libpath:[] @@

From 25648835f6774689861e9a97da7636894a4566e2 Mon Sep 17 00:00:00 2001
From: Nicolas Berthier <nicolas.berthier@ocamlpro.com>
Date: Fri, 15 Sep 2023 16:39:44 +0200
Subject: [PATCH 05/17] Use distinct AST representations for `SEARCH` and
 `SEARCH ALL`

---
 src/lsp/cobol_ast/branching_statements.ml   | 62 +++++++++++----------
 src/lsp/cobol_ast/raw_statements_visitor.ml | 47 ++++++++--------
 src/lsp/cobol_lsp/lsp_semtoks.ml            | 16 +++---
 src/lsp/cobol_parser/grammar.mly            | 16 +++---
 4 files changed, 74 insertions(+), 67 deletions(-)

diff --git a/src/lsp/cobol_ast/branching_statements.ml b/src/lsp/cobol_ast/branching_statements.ml
index c76e1b6df..7c1947bb5 100644
--- a/src/lsp/cobol_ast/branching_statements.ml
+++ b/src/lsp/cobol_ast/branching_statements.ml
@@ -99,28 +99,26 @@ and varying_phrase =
 and search_stmt =
   {
     search_item: qualname;
+    search_varying: ident option;
     search_at_end: handler;
-    search_spec: search_spec;
+    search_when_clauses: search_when_clause with_loc list;
   }
 
-and search_spec =
-  | SearchSerial of
-      {
-        varying: ident option;
-        when_clauses: search_when_clause with_loc list;
-      }
-  | SearchAll of
-      {
-        conditions: search_condition list;
-        action: branch;
-      }
-
 and search_when_clause =
   {
     search_when_cond: condition;
     search_when_stmts: branch;
   }
 
+(* SEARCH ALL *)
+and search_all_stmt =
+  {
+    search_all_item: qualname;
+    search_all_at_end: handler;
+    search_all_conditions: search_condition list;
+    search_all_action: branch;
+  }
+
 
 (* IF *)
 and if_stmt =
@@ -410,6 +408,7 @@ and statement =
   | Return of return_stmt
   | Rewrite of rewrite_stmt
   | Search of search_stmt
+  | SearchAll of search_all_stmt
   | Send of send_stmt
   | Set of set_stmt
   | Sort of sort_stmt
@@ -560,23 +559,25 @@ and pp_varying_phrase ppf
 
 (* SEARCH *)
 
-and pp_search_stmt ppf { search_item = si; search_at_end = h; search_spec = ss } =
-  match ss with
-  | SearchSerial { varying; when_clauses } ->
-    Fmt.pf ppf "SEARCH %a" pp_qualname si;
-    Fmt.(option (any "@ VARYING " ++ pp_ident)) ppf varying;
-    List.iter (fun pf -> pf ppf ()) @@
-    list_clause Fmt.(any "@ AT END " ++ box pp_handler) h;
-    Fmt.(sp ++ list ~sep:sp (pp_with_loc pp_search_when_clause)) ppf when_clauses;
-    Fmt.pf ppf "@ END-SEARCH"
-  | SearchAll { conditions; action } ->
-    Fmt.pf ppf "SEARCH ALL %a" pp_qualname si;
-    List.iter (fun pf -> pf ppf ()) @@
-    list_clause Fmt.(any "@ AT END " ++ box pp_handler) h;
-    Fmt.(any "@ WHEN " ++ list ~sep:(any " AND@ ") pp_search_condition)
-      ppf conditions;
-    Fmt.(sp ++ pp_branch) ppf action;
-    Fmt.pf ppf "@ END-SEARCH"
+and pp_search_stmt ppf { search_item = si; search_varying = sv;
+                         search_at_end = h; search_when_clauses = swc } =
+  Fmt.pf ppf "SEARCH %a" pp_qualname si;
+  Fmt.(option (any "@ VARYING " ++ pp_ident)) ppf sv;
+  List.iter (fun pf -> pf ppf ()) @@
+  list_clause Fmt.(any "@ AT END " ++ box pp_handler) h;
+  Fmt.(sp ++ list ~sep:sp (pp_with_loc pp_search_when_clause)) ppf swc;
+  Fmt.pf ppf "@ END-SEARCH"
+
+and pp_search_all_stmt ppf { search_all_item = si;
+                             search_all_at_end = h;
+                             search_all_conditions = c;
+                             search_all_action = a } =
+  Fmt.pf ppf "SEARCH ALL %a" pp_qualname si;
+  List.iter (fun pf -> pf ppf ()) @@
+  list_clause Fmt.(any "@ AT END " ++ box pp_handler) h;
+  Fmt.(any "@ WHEN " ++ list ~sep:(any " AND@ ") pp_search_condition) ppf c;
+  Fmt.(sp ++ pp_branch) ppf a;
+  Fmt.pf ppf "@ END-SEARCH"
 
 and pp_search_when_clause ppf { search_when_cond = c; search_when_stmts = w } =
   Fmt.pf ppf "WHEN %a@ %a" pp_condition c pp_branch w
@@ -886,6 +887,7 @@ and pp_statement ppf = function
   | Return s -> pp_return_stmt ppf s
   | Rewrite s -> pp_rewrite_stmt ppf s
   | Search s -> pp_search_stmt ppf s
+  | SearchAll s -> pp_search_all_stmt ppf s
   | Send s -> pp_send_stmt ppf s
   | Set s -> pp_set_stmt ppf s
   | Sort s -> pp_sort_stmt ppf s
diff --git a/src/lsp/cobol_ast/raw_statements_visitor.ml b/src/lsp/cobol_ast/raw_statements_visitor.ml
index 500deb5f6..2e201c9b8 100644
--- a/src/lsp/cobol_ast/raw_statements_visitor.ml
+++ b/src/lsp/cobol_ast/raw_statements_visitor.ml
@@ -82,7 +82,6 @@ module Make = struct
     method fold_dual_handler        : (dual_handler               , 'a) fold = default
     method fold_call_error_handler  : (call_error_handler         , 'a) fold = default
     method fold_search_when_clause' : (search_when_clause with_loc, 'a) fold = default
-    method fold_search_spec         : (search_spec                , 'a) fold = default
     method fold_read_error_handler  : (read_error * dual_handler  , 'a) fold = default
     method fold_write_error_handler : (write_error * dual_handler , 'a) fold = default
 
@@ -122,6 +121,7 @@ module Make = struct
     method fold_return'        : (return_stmt with_loc          , 'a) fold = default
     method fold_rewrite'       : (rewrite_stmt with_loc         , 'a) fold = default
     method fold_search'        : (search_stmt with_loc          , 'a) fold = default
+    method fold_search_all'    : (search_all_stmt with_loc      , 'a) fold = default
     method fold_set'           : (set_stmt with_loc             , 'a) fold = default
     method fold_start'         : (start_stmt with_loc           , 'a) fold = default
     method fold_stop'          : (stop_stmt with_loc            , 'a) fold = default
@@ -632,8 +632,8 @@ module Make = struct
         | Move          s -> fold_move'           v (s &@ loc)
         | Multiply      s -> fold_multiply'       v (s &@ loc)
         | Open          s -> fold_open'           v (s &@ loc)
-        | PerformTarget s -> fold_perform_target' v (s &@ loc)
         | PerformInline s -> fold_perform_inline' v (s &@ loc)
+        | PerformTarget s -> fold_perform_target' v (s &@ loc)
         | Raise         s -> fold_raise'          v (s &@ loc)
         | Read          s -> fold_read'           v (s &@ loc)
         | Release       s -> fold_release'        v (s &@ loc)
@@ -641,6 +641,7 @@ module Make = struct
         | Return        s -> fold_return'         v (s &@ loc)
         | Rewrite       s -> fold_rewrite'        v (s &@ loc)
         | Search        s -> fold_search'         v (s &@ loc)
+        | SearchAll     s -> fold_search_all'     v (s &@ loc)
         | Set           s -> fold_set'            v (s &@ loc)
         | Start         s -> fold_start'          v (s &@ loc)
         | Stop          s -> fold_stop'           v (s &@ loc)
@@ -809,13 +810,6 @@ module Make = struct
         >> fold_dual_handler v multiply_on_size_error
       end
 
-  and fold_perform_target' (v: _ #folder) : perform_target_stmt with_loc -> 'a -> 'a =
-    handle' v#fold_perform_target' v
-      ~fold:begin fun v { perform_target = proc_range; perform_mode } x -> x
-        >> fold_procedure_range ~fold:fold_qualname v proc_range
-        >> fold_option ~fold:fold_perform_mode v perform_mode
-      end
-
   and fold_perform_inline' (v: _ #folder) : perform_inline_stmt with_loc -> 'a -> 'a =
     handle' v#fold_perform_inline' v
       ~fold:begin fun v { perform_inline_mode; perform_statements } x -> x
@@ -823,6 +817,13 @@ module Make = struct
         >> fold_statements v perform_statements
       end
 
+  and fold_perform_target' (v: _ #folder) : perform_target_stmt with_loc -> 'a -> 'a =
+    handle' v#fold_perform_target' v
+      ~fold:begin fun v { perform_target = proc_range; perform_mode } x -> x
+        >> fold_procedure_range ~fold:fold_qualname v proc_range
+        >> fold_option ~fold:fold_perform_mode v perform_mode
+      end
+
   and fold_read_error_handler (v: _ #folder) =
     handle v#fold_read_error_handler
       ~continue:begin fun (read_error, dual_handler) x -> x
@@ -872,24 +873,24 @@ module Make = struct
         >> fold_branch v search_when_stmts
       end
 
-  and fold_search_spec (v: _ #folder) =
-    handle v#fold_search_spec
-      ~continue:begin fun s x -> match s with
-        | SearchSerial { varying; when_clauses } -> x
-            >> fold_option ~fold:fold_ident v varying
-            >> fold_list ~fold:fold_search_when_clause' v when_clauses
-        | SearchAll { conditions; action } -> x
-            >> fold_list ~fold:fold_search_condition v conditions
-            >> fold_branch v action
-      end
-
   and fold_search' (v: _ #folder) =
     handle' v#fold_search' v
-      ~fold:begin fun v { search_item; search_spec;
-                          search_at_end} x -> x
+      ~fold:begin fun v { search_item; search_at_end;
+                          search_varying; search_when_clauses } x -> x
         >> fold_qualname v search_item
         >> fold_handler v search_at_end
-        >> fold_search_spec v search_spec
+        >> fold_option ~fold:fold_ident v search_varying
+        >> fold_list ~fold:fold_search_when_clause' v search_when_clauses
+      end
+
+  and fold_search_all' (v: _ #folder) =
+    handle' v#fold_search_all' v
+      ~fold:begin fun v { search_all_item; search_all_at_end;
+                          search_all_conditions; search_all_action } x -> x
+        >> fold_qualname v search_all_item
+        >> fold_handler v search_all_at_end
+        >> fold_list ~fold:fold_search_condition v search_all_conditions
+        >> fold_branch v search_all_action
       end
 
   and fold_start' (v: _ #folder) =
diff --git a/src/lsp/cobol_lsp/lsp_semtoks.ml b/src/lsp/cobol_lsp/lsp_semtoks.ml
index 00e95568f..2d1a85ac5 100644
--- a/src/lsp/cobol_lsp/lsp_semtoks.ml
+++ b/src/lsp/cobol_lsp/lsp_semtoks.ml
@@ -453,13 +453,15 @@ let semtoks_from_ptree ~filename ptree =
           |> add_name' name FileName
           |> Visitor.skip_children
 
-    method! fold_search_spec search_spec acc =
-      match search_spec with
-      | SearchSerial { varying; when_clauses } -> acc
-          |> add_option add_ident varying VarModif
-          |> fold_list ~fold:fold_search_when_clause' self when_clauses
-          |> Visitor.skip_children
-      | SearchAll _ -> Visitor.do_children acc
+    method! fold_search' { payload = { search_item;
+                                       search_varying;
+                                       search_at_end;
+                                       search_when_clauses }; _ } acc = acc
+      |> fold_qualname self search_item
+      |> add_option add_ident search_varying VarModif
+      |> fold_statements self search_at_end
+      |> fold_list ~fold:fold_search_when_clause' self search_when_clauses
+      |> Visitor.skip_children
 
     method! fold_set_switch_spec {set_switch_targets;
                                   set_switch_value } acc = acc
diff --git a/src/lsp/cobol_parser/grammar.mly b/src/lsp/cobol_parser/grammar.mly
index 926f75ac1..347fac092 100644
--- a/src/lsp/cobol_parser/grammar.mly
+++ b/src/lsp/cobol_parser/grammar.mly
@@ -3496,24 +3496,26 @@ let rewrite_statement :=
 (* SEARCH STATEMENT *)
 (* TODO: merge when_clause / statements_or_next *)
 
-%public let unconditional_action := ~ = search_statement; <Search>
+%public let unconditional_action := ~ = search_statement; < >
 let search_statement :=
  | SEARCH; i = qualname;
    io = ro(pf(VARYING,ident));
    ae = ilo(pf(at_end,imp_stmts));
    wcl = nell(loc(when_clause));
    end_search;
-   { { search_item = i;
-       search_at_end = ae;
-       search_spec = SearchSerial { varying = io; when_clauses = wcl } } }
+   { Search { search_item = i;
+              search_varying = io;
+              search_at_end = ae;
+              search_when_clauses = wcl } }
  | SEARCH; ALL; i = qualname;
    ae = ilo(pf(at_end,imp_stmts));
    WHEN; sc = search_condition; scl = ll(and_clause);
    sn = statements_or_next;
    end_search;
-   { { search_item = i;
-       search_at_end = ae;
-       search_spec = SearchAll { conditions = sc :: scl; action = sn } } }
+   { SearchAll { search_all_item = i;
+                 search_all_at_end = ae;
+                 search_all_conditions = sc :: scl;
+                 search_all_action = sn } }
 
 let end_search := oterm_(END_SEARCH)
 

From 616a10ac729dc3c522ec62c672cdca3148f3f489 Mon Sep 17 00:00:00 2001
From: Nicolas Berthier <nicolas.berthier@ocamlpro.com>
Date: Fri, 15 Sep 2023 16:46:34 +0200
Subject: [PATCH 06/17] Emit semantic tokens for `COPY` and `REPLACE`
 preprocessor statements

---
 src/lsp/cobol_lsp/lsp_request.ml        |  6 ++++-
 src/lsp/cobol_lsp/lsp_semtoks.ml        | 33 +++++++++++++++++++------
 src/lsp/cobol_preproc/preproc_engine.ml |  4 +--
 src/lsp/cobol_preproc/preproc_trace.ml  |  6 +++++
 src/lsp/cobol_preproc/preproc_trace.mli | 11 +++++++--
 5 files changed, 48 insertions(+), 12 deletions(-)

diff --git a/src/lsp/cobol_lsp/lsp_request.ml b/src/lsp/cobol_lsp/lsp_request.ml
index ec69a2a41..111009268 100644
--- a/src/lsp/cobol_lsp/lsp_request.ml
+++ b/src/lsp/cobol_lsp/lsp_request.ml
@@ -265,6 +265,8 @@ let handle_hover registry (params: HoverParams.t) =
       | Cobol_preproc.FileCopy { copyloc = loc; _ } ->
           Lsp_position.is_in_lexloc params.position
             (Cobol_common.Srcloc.lexloc_in ~filename loc)
+      | Cobol_preproc.Replace _ ->
+          false
     end (Cobol_preproc.Trace.events pplog)
   in
   let hover_markdown ~loc value =
@@ -289,7 +291,9 @@ let handle_hover registry (params: HoverParams.t) =
             | SF _ | Auto -> "cobol"
           in
           Pretty.string_to (hover_markdown ~loc) "```%s\n%s\n```" mdlang text
-      | Some FileCopy { status = MissingCopy _; _ } | None ->
+      | Some FileCopy { status = MissingCopy _; _ }
+      | Some Replace _
+      | None ->
           None
     end
 
diff --git a/src/lsp/cobol_lsp/lsp_semtoks.ml b/src/lsp/cobol_lsp/lsp_semtoks.ml
index 2d1a85ac5..7ff1cea9c 100644
--- a/src/lsp/cobol_lsp/lsp_semtoks.ml
+++ b/src/lsp/cobol_lsp/lsp_semtoks.ml
@@ -46,7 +46,7 @@ module TOKTYP = struct
   (* "enumMember"; *)
   (* "event"; *)
   (* "method"; *)
-  (* "macro"; *)
+  let macro     = mk "macro"
   (* "regexp"; *)
   let all =
     List.sort (fun a b -> b.index - a.index) !all |>
@@ -121,6 +121,12 @@ type token_category =
   | MnemonicName
   | FileName
 
+
+(* TODO: incrementally build a map that associates locations in filename with
+   token types and modifiers, and then extract the (sorted) list at the end.  In
+   this way, we don't need to worry about the order in which parse-tree elements
+   are visited.  If really needed, the accumulator may carry some context
+   information that can be used in generic methods like `fold_name'`. *)
 let semtoks_from_ptree ~filename ptree =
   let open Cobol_parser.PTree_visitor in
   let open Cobol_ast.Terms_visitor in
@@ -553,6 +559,16 @@ let semtoks_of_comments ~filename comments = comments |>
         None
   end
 
+let semtoks_of_preproc_statements ~filename pplog =
+  List.fold_left begin fun acc -> function
+    | Cobol_preproc.Trace.FileCopy { copyloc = loc; _ }
+    | Cobol_preproc.Trace.Replace { replloc = loc } ->
+        List.rev_map (semtok TOKTYP.macro)
+          (single_line_lexlocs_in ~filename loc) @ acc
+    | Cobol_preproc.Trace.Replacement _ ->
+        acc
+  end [] (Cobol_preproc.Trace.events pplog)
+
 (** [semtoks_of_non_ambigious_tokens ~filename tokens] returns tokens that do
     not need to have more analyzing to get their type. *)
 let semtoks_of_non_ambigious_tokens ~filename tokens =
@@ -641,10 +657,11 @@ let ensure_sorted name ~filename cmp l =
       List.fast_sort cmp l
 
 
-let data ~filename ~tokens ~pplog:_ ~comments ~ptree : int array =
+let data ~filename ~tokens ~pplog ~comments ~ptree : int array =
   let semtoks1 = semtoks_of_non_ambigious_tokens ~filename tokens in
-  let semtoks2 = semtoks_from_ptree ~filename ptree in
-  let semtoks3 = semtoks_of_comments ~filename comments in
+  let semtoks2 = semtoks_from_ptree              ~filename ptree in
+  let semtoks3 = semtoks_of_comments             ~filename comments in
+  let semtoks4 = semtoks_of_preproc_statements   ~filename pplog in
   (* NB: In *principle* all those lists are already sorted w.r.t lexical
      locations in [filename].  We just check that for now and raise a warning,
      in case. *)
@@ -652,8 +669,10 @@ let data ~filename ~tokens ~pplog:_ ~comments ~ptree : int array =
   (* and semtoks2 = List.fast_sort compare_semtoks semtoks2 *)
   (* and semtoks3 = List.fast_sort compare_semtoks semtoks3 in *)
   let semtoks1 = ensure_sorted "nonambiguous" ~filename compare_semtoks semtoks1
-  and semtoks2 = ensure_sorted "ptree" ~filename compare_semtoks semtoks2
-  and semtoks3 = ensure_sorted "comments" ~filename compare_semtoks semtoks3 in
+  and semtoks2 = ensure_sorted "ptree"        ~filename compare_semtoks semtoks2
+  and semtoks3 = ensure_sorted "comments"     ~filename compare_semtoks semtoks3
+  and semtoks4 = ensure_sorted "preproc"      ~filename compare_semtoks semtoks4 in
   relative_semtoks
     List.(merge compare_semtoks semtoks1 @@
-          merge compare_semtoks semtoks2 semtoks3)
+          merge compare_semtoks semtoks2 @@
+          merge compare_semtoks semtoks3 @@ semtoks4)
diff --git a/src/lsp/cobol_preproc/preproc_engine.ml b/src/lsp/cobol_preproc/preproc_engine.ml
index 5859cd371..d056f8305 100644
--- a/src/lsp/cobol_preproc/preproc_engine.ml
+++ b/src/lsp/cobol_preproc/preproc_engine.ml
@@ -274,7 +274,7 @@ and do_copy lp rev_prefix copy suffix =
   `CopyDone (lp, text)
 
 and do_replace lp rev_prefix repl suffix =
-  let { result = repl; diags } = ~&repl in
+  let { payload = { result = repl; diags }; loc } = repl in
   let lp = add_diags lp diags in
   let prefix, pplog =
     (* NB: this applies the current replacing on all remaining text leading to
@@ -283,7 +283,7 @@ and do_replace lp rev_prefix repl suffix =
        replacing phrase. *)
     apply_active_replacing_full lp @@ List.rev rev_prefix
   in
-  let lp = with_pplog lp pplog in
+  let lp = with_pplog lp @@ Preproc_trace.new_replace ~loc pplog in
   let lp = match repl, lp.persist.replacing with
     | CDirReplace { replacing = repl; _ }, ([] as replacing)
     | CDirReplace { replacing = repl; also = false }, replacing ->
diff --git a/src/lsp/cobol_preproc/preproc_trace.ml b/src/lsp/cobol_preproc/preproc_trace.ml
index 2d00b4433..6a2bf84e2 100644
--- a/src/lsp/cobol_preproc/preproc_trace.ml
+++ b/src/lsp/cobol_preproc/preproc_trace.ml
@@ -19,6 +19,10 @@ module TYPES = struct
           copyloc: srcloc;
           status: copy_event_status;
         }
+    | Replace of
+        {
+          replloc: srcloc;
+        }
     | Replacement of
         {
           matched_loc: srcloc;
@@ -45,6 +49,8 @@ let cyclic_copy ~loc ~filename : log -> log =
   List.cons @@ FileCopy { copyloc = loc; status = CyclicCopy filename }
 let missing_copy ~loc ~info : log -> log =
   List.cons @@ FileCopy { copyloc = loc; status = MissingCopy info }
+let new_replace ~loc : log -> log =
+  List.cons @@ Replace { replloc = loc }
 
 (* --- *)
 
diff --git a/src/lsp/cobol_preproc/preproc_trace.mli b/src/lsp/cobol_preproc/preproc_trace.mli
index 3e99a6a17..b20e7775f 100644
--- a/src/lsp/cobol_preproc/preproc_trace.mli
+++ b/src/lsp/cobol_preproc/preproc_trace.mli
@@ -12,12 +12,16 @@ module TYPES: sig
   type log_entry =
     | FileCopy of
         {
-          copyloc: Cobol_common.Srcloc.srcloc;
+          copyloc: Cobol_common.srcloc;
           status: copy_event_status;
         }
+    | Replace of
+        {
+          replloc: Cobol_common.srcloc;
+        }
     | Replacement of
         {
-          matched_loc: Cobol_common.Srcloc.srcloc;
+          matched_loc: Cobol_common.srcloc;
           replacement_text: Text.text;
         }
 
@@ -50,6 +54,9 @@ val missing_copy
   : loc: Cobol_common.srcloc
   -> info: Copybook.lib_not_found_info
   -> log -> log
+val new_replace
+  : loc: Cobol_common.srcloc
+  -> log -> log
 
 (* --- *)
 

From 7d36692d21a5f6358a479e9f7a1454d1ee69743d Mon Sep 17 00:00:00 2001
From: Nicolas Berthier <nicolas.berthier@ocamlpro.com>
Date: Sat, 16 Sep 2023 00:11:35 +0200
Subject: [PATCH 07/17] Emit macro semantic tokens in proper order; more doc in
 `Cobol_common.Srcloc`

---
 src/lsp/cobol_common/srcloc.ml   | 51 ++++++++++----------------------
 src/lsp/cobol_common/srcloc.mli  |  4 +--
 src/lsp/cobol_lsp/lsp_semtoks.ml |  2 +-
 3 files changed, 17 insertions(+), 40 deletions(-)

diff --git a/src/lsp/cobol_common/srcloc.ml b/src/lsp/cobol_common/srcloc.ml
index 689ca4154..2042b844b 100644
--- a/src/lsp/cobol_common/srcloc.ml
+++ b/src/lsp/cobol_common/srcloc.ml
@@ -93,7 +93,7 @@ let pp_srcloc_struct: srcloc Pretty.printer =
   in
   pp
 
-(** {2 Manipulating source locations} *)
+(** {2 Querying source locations} *)
 
 (** copied, but original (replaced) position upon replacing *)
 let rec start_pos: type t. t slt -> Lexing.position = function
@@ -118,27 +118,27 @@ let shallow_single_line_lexloc_in ~filename = function
   | Raw (s, e, _) when s.pos_fname = filename -> Some (s, e)
   | Raw _ | Cpy _ | Rpl _ | Cat _ -> None
 
-let start_pos_in ~filename =
+let start_pos_in ~filename ~traverse_replaces =
   let rec aux: type t. t slt -> Lexing.position option = function
     | Raw (s, _, _) when s.pos_fname = filename -> Some s
     | Raw _ -> None
     | Cat { left; right } -> or_else left right
     | Cpy { copied; copyloc = { copyloc; _ } } -> or_else copied copyloc
-    | Rpl { new_; old; replloc; _ } ->
-        match aux new_ with None -> or_else old replloc | res -> res
+    | Rpl { old; new_; _ } ->
+        aux (if traverse_replaces then new_ else old)
   and or_else: type t u. t slt -> u slt -> _ = fun a b ->
     match aux a with None -> aux b | res -> res
   in
   aux
 
-let end_pos_in ~filename =
+let end_pos_in ~filename ~traverse_replaces =
   let rec aux: type t. t slt -> Lexing.position option = function
     | Raw (_, e, _) when e.pos_fname = filename -> Some e
     | Raw _ -> None
     | Cat { left; right } -> or_else right left
     | Cpy { copied; copyloc = { copyloc; _ } } -> or_else copied copyloc
-    | Rpl { new_; old; replloc; _ } ->
-        match aux new_ with None -> or_else old replloc | res -> res
+    | Rpl { old; new_; _ } ->
+        aux (if traverse_replaces then new_ else old)
   and or_else: type t u. t slt -> u slt -> _ = fun a b ->
     match aux a with None -> aux b | res -> res
   in
@@ -168,6 +168,8 @@ let forget_preproc
     ~(favor_direction: [`Left | `Right])
     ~(traverse_copies: bool)
     ~(traverse_replaces: bool) =
+  let start_pos_in = start_pos_in ~traverse_replaces
+  and end_pos_in = end_pos_in ~traverse_replaces in
   let rec aux: type t. t slt -> lexloc = function
     | Raw (s, e, _) ->
         s, e
@@ -202,10 +204,10 @@ let lookup_ ~lookup ~lookup_name ~filename loc =
       s
 
 let start_pos_in =
-  lookup_ ~lookup:start_pos_in
+  lookup_ ~lookup:(start_pos_in ~traverse_replaces:false)
     ~lookup_name:"start_pos_in"
 let end_pos_in =
-  lookup_ ~lookup:end_pos_in
+  lookup_ ~lookup:(end_pos_in ~traverse_replaces:false)
     ~lookup_name:"end_pos_in"
 let shallow_multiline_lexloc_in =
   lookup_ ~lookup:shallow_multiline_lexloc_in
@@ -280,18 +282,7 @@ let scan ?(kind: [`TopDown | `BottomUp] = `TopDown) ~cpy ~rpl =
   in
   aux
 
-(* let fold_lexlocs f loc acc = *)
-(*   let rec aux: type t. t slt -> 'a -> 'a = fun loc -> match loc with *)
-(*     | Raw (s, e, _) -> f (s, e) *)
-(*     | Cpy { copied; _ } -> aux copied *)
-(*     | Rpl { old; _ } -> aux old *)
-(*     | Cat { left; right } -> fun acc -> acc |> aux left |> aux right *)
-(*   in *)
-(*   aux loc acc *)
-
-(* let has_lexloc p loc = *)
-(*   try fold_lexlocs (fun lexloc () -> if p lexloc then raise Exit) loc (); false *)
-(*   with Exit -> true *)
+(** {2 Pretty-printing} *)
 
 let retrieve_file_lines =
   let module Cache =
@@ -417,6 +408,8 @@ let pp_srcloc: srcloc Pretty.printer =
 let pp_file_loc ppf loc =
   pp_file_loc ppf (to_raw_loc @@ as_lexloc loc)
 
+(** {2 Constructors} *)
+
 (** [raw ~in_area_a lexloc] builds a raw source location from a pair of left-
     and right- lexing positions from the same file, optionally setting an
     [in_area_a] flag (that defaults to [false]) to indicate whether the location
@@ -436,21 +429,7 @@ let copy ~filename ~copyloc copied : srcloc =
 let replacement ~old ~new_ ~in_area_a ~replloc : srcloc =
   Rpl { old; new_; in_area_a; replloc }
 
-
-(* let is_copy = function *)
-(*   | Cpy _ -> true *)
-(*   | _ -> false *)
-
-(* let rec last_copy_origin: type t. t slt -> string option = function *)
-(*   | Raw _ -> None *)
-(*   | Rpl { replaced; _ } -> *)
-(*       last_copy_origin replaced *)
-(*   | Cat {left; right} -> *)
-(*       begin match last_copy_origin left with *)
-(*       | None -> last_copy_origin right *)
-(*       | _ as v -> v *)
-(*       end *)
-(*   | Cpy {copyloc = {filename; _}; _} -> Some filename *)
+(** {2 Composition & truncation} *)
 
 (** [may_join_as_single_raw a b] checks whether a lexloc {i l{_ a}} with a a
     left-hand lexing position [a] and a lexloc {i l{_ b}} with a right-hand
diff --git a/src/lsp/cobol_common/srcloc.mli b/src/lsp/cobol_common/srcloc.mli
index f7cb37d68..d8cf9beb3 100644
--- a/src/lsp/cobol_common/srcloc.mli
+++ b/src/lsp/cobol_common/srcloc.mli
@@ -40,6 +40,7 @@ module INFIX: sig
 end
 
 val pp_srcloc: srcloc Pretty.printer
+val pp_srcloc_struct: srcloc Pretty.printer
 val pp_file_loc: srcloc Pretty.printer
 val raw
   : ?in_area_a:bool
@@ -95,9 +96,6 @@ val start_pos: srcloc -> Lexing.position    (* only suitable for Area A checks *
 val start_pos_in: filename: string -> srcloc -> Lexing.position
 val end_pos_in: filename: string -> srcloc -> Lexing.position
 
-(* val fold_lexlocs: (lexloc -> 'a -> 'a) -> srcloc -> 'a -> 'a *)
-(* val has_lexloc: (lexloc -> bool) -> srcloc -> bool *)
-
 val concat: srcloc -> srcloc -> srcloc
 val concat_srclocs: srcloc list -> srcloc option
 val prefix: int -> srcloc -> srcloc
diff --git a/src/lsp/cobol_lsp/lsp_semtoks.ml b/src/lsp/cobol_lsp/lsp_semtoks.ml
index 7ff1cea9c..46a372531 100644
--- a/src/lsp/cobol_lsp/lsp_semtoks.ml
+++ b/src/lsp/cobol_lsp/lsp_semtoks.ml
@@ -560,7 +560,7 @@ let semtoks_of_comments ~filename comments = comments |>
   end
 
 let semtoks_of_preproc_statements ~filename pplog =
-  List.fold_left begin fun acc -> function
+  List.rev @@ List.fold_left begin fun acc -> function
     | Cobol_preproc.Trace.FileCopy { copyloc = loc; _ }
     | Cobol_preproc.Trace.Replace { replloc = loc } ->
         List.rev_map (semtok TOKTYP.macro)

From c3b2019f7e573f505f894cb8af620fe46c14c6e5 Mon Sep 17 00:00:00 2001
From: Nicolas Berthier <nicolas.berthier@ocamlpro.com>
Date: Mon, 18 Sep 2023 11:43:11 +0200
Subject: [PATCH 08/17] Add support for ranged semantic tokens requests

---
 src/lsp/cobol_lsp/lsp_diagnostics.ml |  2 +-
 src/lsp/cobol_lsp/lsp_position.ml    | 74 +++++++++++++++++-----------
 src/lsp/cobol_lsp/lsp_position.mli   |  5 +-
 src/lsp/cobol_lsp/lsp_request.ml     | 40 +++++++++------
 src/lsp/cobol_lsp/lsp_semtoks.ml     | 48 ++++++++++--------
 src/lsp/cobol_lsp/lsp_semtoks.mli    |  1 +
 6 files changed, 100 insertions(+), 70 deletions(-)

diff --git a/src/lsp/cobol_lsp/lsp_diagnostics.ml b/src/lsp/cobol_lsp/lsp_diagnostics.ml
index 525d20317..3a976b6f3 100644
--- a/src/lsp/cobol_lsp/lsp_diagnostics.ml
+++ b/src/lsp/cobol_lsp/lsp_diagnostics.ml
@@ -46,7 +46,7 @@ let translate_one ~rootdir ~uri (diag: DIAG.t) =
     | Some (Lexing.{ pos_fname = f; _ }, _ as lexloc) ->
         pseudo_normalized_uri ~rootdir f, Lsp_position.range_of_lexloc lexloc
     | None ->
-        uri, Lsp_position.none_range
+        uri, Lsp_position.pointwise_range_at_start
   in
   let diag =
     Lsp.Types.Diagnostic.create ()
diff --git a/src/lsp/cobol_lsp/lsp_position.ml b/src/lsp/cobol_lsp/lsp_position.ml
index c587ee140..ece838258 100644
--- a/src/lsp/cobol_lsp/lsp_position.ml
+++ b/src/lsp/cobol_lsp/lsp_position.ml
@@ -19,44 +19,60 @@ open Srcloc.TYPES
 open Lsp.Types
 
 (** Range of length [0], at position [0, 0] *)
-let none_range =
-  let none_pos = Position.create ~line:0 ~character:0 in
-  Range.create ~start:none_pos ~end_:none_pos
+let pointwise_range_at_start =
+  let start_pos = Position.create ~line:0 ~character:0 in
+  Range.create ~start:start_pos ~end_:start_pos
 
 (** {1 Postions {i w.r.t} lexical locations} *)
 
+(** [start_of_lexloc] creates a representation of the start of the given lexical
+    location that is suitable for the LSP library. *)
+let start_of_lexloc ((start_pos, _end_pos): lexloc) =
+  Position.create           (* NOTE: Line numbers start at 0 in LSP protocol. *)
+    ~line:(start_pos.pos_lnum - 1)
+    ~character:(start_pos.pos_cnum - start_pos.pos_bol)
+
+(** [end_of_lexloc] creates a representation of the end of the given lexical
+    location that is suitable for the LSP library. *)
+let end_of_lexloc ((_start_pos, end_pos): lexloc) =
+  Position.create           (* NOTE: Line numbers start at 0 in LSP protocol. *)
+    ~line:(end_pos.pos_lnum - 1)
+    ~character:(end_pos.pos_cnum - end_pos.pos_bol)
+
 (** [range_of_lexloc] creates a representation of the given lexical location
     that is suitable for the LSP library. *)
-let range_of_lexloc ((start_pos, end_pos): lexloc) =
-  (* NOTE: Line numbers start at 0 in LSP protocol. *)
-  let sl = start_pos.pos_lnum - 1
-  and sc = start_pos.pos_cnum - start_pos.pos_bol
-  and el = end_pos.pos_lnum - 1
-  and ec = end_pos.pos_cnum - end_pos.pos_bol in
-  Range.create
-    ~start:(Position.create ~line:sl ~character:sc)
-    ~end_:(Position.create ~line:el ~character:ec)
-
-(** [is_before_lexloc pos lexloc] holds when [pos] is strictly before [lexloc] *)
-let is_before_lexloc pos lexloc =
-  let Range.{start = {line; character;}; _} = range_of_lexloc lexloc in
-  Position.(pos.line < line || (pos.line = line && pos.character < character))
-
-(** [is_after_lexloc pos lexloc] holds when [pos] is strictly after [lexloc] *)
-let is_after_lexloc pos lexloc =
-  let Range.{end_ = {line; character;}; _} = range_of_lexloc lexloc in
-  Position.(pos.line > line || (pos.line = line && pos.character > character))
-
-(** [is_in_lexloc pos lexloc] holds when [pos] is neither before or after
-    [lexloc] *)
+let range_of_lexloc lexloc =
+  Range.create ~start:(start_of_lexloc lexloc) ~end_:(end_of_lexloc lexloc)
+
+(** [is_before_lexloc pos lexloc] holds when [pos] strictly precedes [lexloc] *)
+let is_before_lexloc (pos: Position.t) lexloc =
+  let Position.{ line; character } = start_of_lexloc lexloc in
+  pos.line < line ||
+  pos.line = line && pos.character < character
+
+(** [is_after_lexloc pos lexloc] holds when [pos] strictly follows [lexloc] *)
+let is_after_lexloc (pos: Position.t) lexloc =
+  let Position.{ line; character } = end_of_lexloc lexloc in
+  pos.line > line ||
+  pos.line = line && pos.character > character
+
+(** [is_in_lexloc pos lexloc] holds when [pos] is strictly neither before nor
+    after [lexloc] *)
 let is_in_lexloc pos lexloc =
-  (not @@ is_after_lexloc pos lexloc) && (not @@ is_before_lexloc pos lexloc)
+  not (is_before_lexloc pos lexloc || is_after_lexloc pos lexloc)
 
-(** [contains_lexloc range lexloc] holds when [lexloc] is strictly contained
-    inside [range]. *)
-let contains_lexloc Range.{start; end_} lexloc =
+(** [contains_lexloc range lexloc] holds when the range described by [lexloc] is
+    strictly contained within [range]. *)
+let contains_lexloc Range.{ start; end_ } lexloc =
   is_before_lexloc start lexloc && is_after_lexloc end_ lexloc
 
+(** [intersects_lexloc range lexloc] holds when the range described by [lexloc]
+    and [range] have a non-empty intersection. *)
+let intersects_lexloc (Range.{ start; end_ } as range) lexloc =
+  is_in_lexloc start lexloc ||
+  is_in_lexloc end_ lexloc ||
+  contains_lexloc range lexloc
+
 (* --- *)
 
 (** {1 Postions {i w.r.t} generalized source locations} *)
diff --git a/src/lsp/cobol_lsp/lsp_position.mli b/src/lsp/cobol_lsp/lsp_position.mli
index 9996a587c..a56357d65 100644
--- a/src/lsp/cobol_lsp/lsp_position.mli
+++ b/src/lsp/cobol_lsp/lsp_position.mli
@@ -15,7 +15,7 @@
     {!Lsp.Types.Range} types with {!Srcloc.lexloc} and {!Srcloc.srcloc}. *)
 
 (** Range of length [0], at position [0, 0] *)
-val none_range: Lsp.Types.Range.t
+val pointwise_range_at_start: Lsp.Types.Range.t
 
 (** [range_of_lexloc] creates a representation of the given lexical location
     that is suitable for the LSP library. *)
@@ -32,9 +32,8 @@ val is_after_lexloc: Lsp.Types.Position.t -> Cobol_common.Srcloc.lexloc -> bool
     [lexloc] *)
 val is_in_lexloc: Lsp.Types.Position.t -> Cobol_common.Srcloc.lexloc -> bool
 
-(** [contains_lexloc range lexloc] holds when [lexloc] is strictly contained
-    within [range]. *)
 val contains_lexloc: Lsp.Types.Range.t -> Cobol_common.Srcloc.lexloc -> bool
+val intersects_lexloc: Lsp.Types.Range.t -> Cobol_common.Srcloc.lexloc -> bool
 
 (* --- *)
 
diff --git a/src/lsp/cobol_lsp/lsp_request.ml b/src/lsp/cobol_lsp/lsp_request.ml
index 111009268..074b95978 100644
--- a/src/lsp/cobol_lsp/lsp_request.ml
+++ b/src/lsp/cobol_lsp/lsp_request.ml
@@ -79,12 +79,12 @@ let try_with_document_data ~f =
 
    NOTE: For now we don't use them because we don't have any special
    response. *)
-let make_capabilities _ =
+let make_capabilities (_: ClientCapabilities.t) =
   let sync =
     TextDocumentSyncOptions.create ()
       ~openClose:true
       ~change:Incremental
-  and semantic =
+  and semtoks =
     let legend =
       SemanticTokensLegend.create
         ~tokenTypes:Lsp_semtoks.token_types
@@ -92,6 +92,7 @@ let make_capabilities _ =
     in
     SemanticTokensOptions.create ()
       ~full:(`Full (SemanticTokensOptions.create_full ~delta:false ()))
+      ~range:true
       ~legend
   and hover =
     HoverOptions.create ()
@@ -104,7 +105,7 @@ let make_capabilities _ =
     ~referencesProvider:(`Bool true)
     ~documentRangeFormattingProvider: (`Bool true)
     ~documentFormattingProvider: (`Bool true)
-    ~semanticTokensProvider:(`SemanticTokensOptions semantic)
+    ~semanticTokensProvider:(`SemanticTokensOptions semtoks)
     ~hoverProvider:(`HoverOptions hover)
     ~completionProvider:(completion_option)
 
@@ -245,17 +246,23 @@ let handle_formatting registry params =
   with Failure msg ->
     internal_error "Formatting error: %s" msg
 
-let handle_semantic_tokens_full registry (params: SemanticTokensParams.t) =
-  try_with_document_data registry params.textDocument
-    ~f:begin fun ~doc:{ artifacts = { pplog; tokens; comments };
-                        _ } Lsp_document.{ ast; _ } ->
-      let filename = Lsp.Uri.to_path params.textDocument.uri in
-      let data =
-        Lsp_semtoks.data ~filename ~pplog ~comments
-          ~tokens:(Lazy.force tokens) ~ptree:ast
-      in
-      Some (SemanticTokens.create ~data ())
-    end
+let handle_semtoks_full,
+    handle_semtoks_range =
+  let handle registry ?range (doc: TextDocumentIdentifier.t) =
+    try_with_document_data registry doc
+      ~f:begin fun ~doc:{ artifacts = { pplog; tokens; comments };
+                          _ } Lsp_document.{ ast; _ } ->
+        let data =
+          Lsp_semtoks.data ~filename:(Lsp.Uri.to_path doc.uri) ~range
+            ~pplog ~comments ~tokens:(Lazy.force tokens) ~ptree:ast
+        in
+        Some (SemanticTokens.create ~data ())
+      end
+  in
+  (fun registry (SemanticTokensParams.{ textDocument; _ }) ->
+     handle registry textDocument),
+  (fun registry (SemanticTokensRangeParams.{ textDocument; range; _ }) ->
+     handle registry ~range textDocument)
 
 let handle_hover registry (params: HoverParams.t) =
   let filename = Lsp.Uri.to_path params.textDocument.uri in
@@ -335,7 +342,9 @@ let on_request
     | TextDocumentFormatting params ->
         Ok (handle_formatting registry params, state)
     | SemanticTokensFull params ->
-        Ok (handle_semantic_tokens_full registry params, state)
+        Ok (handle_semtoks_full registry params, state)
+    | SemanticTokensRange params ->
+        Ok (handle_semtoks_range registry params, state)
     | TextDocumentHover hover_params ->
         Ok (handle_hover registry hover_params, state)
     | TextDocumentCompletion completion_params ->
@@ -370,7 +379,6 @@ let on_request
     | SelectionRange  (* SelectionRangeParams.t.t *) _
     | ExecuteCommand  (* ExecuteCommandParams.t.t *) _
     | SemanticTokensDelta  (* SemanticTokensDeltaParams.t.t *) _
-    | SemanticTokensRange  (* SemanticTokensRangeParams.t.t *) _
     | LinkedEditingRange  (* LinkedEditingRangeParams.t.t *) _
     | CallHierarchyIncomingCalls  (* CallHierarchyIncomingCallsParams.t.t *) _
     | CallHierarchyOutgoingCalls  (* CallHierarchyOutgoingCallsParams.t.t *) _
diff --git a/src/lsp/cobol_lsp/lsp_semtoks.ml b/src/lsp/cobol_lsp/lsp_semtoks.ml
index 46a372531..f047f2d80 100644
--- a/src/lsp/cobol_lsp/lsp_semtoks.ml
+++ b/src/lsp/cobol_lsp/lsp_semtoks.ml
@@ -107,6 +107,12 @@ let semtok ?(tokmods = TOKMOD.none) toktyp lexloc =
 let single_line_lexlocs_in ~filename =
   Srcloc.shallow_single_line_lexlocs_in ~ignore_invalid_filename:true ~filename
 
+let acc_semtoks ~filename ?range ?tokmods toktyp loc acc =
+  List.fold_left begin fun acc lexloc -> match range with
+    | Some r when not (Lsp_position.intersects_lexloc r lexloc) -> acc
+    | _ -> semtok toktyp ?tokmods lexloc :: acc
+  end acc @@ single_line_lexlocs_in ~filename loc
+
 type token_category =
   | ProgramName
   | ParagraphName
@@ -127,13 +133,13 @@ type token_category =
    this way, we don't need to worry about the order in which parse-tree elements
    are visited.  If really needed, the accumulator may carry some context
    information that can be used in generic methods like `fold_name'`. *)
-let semtoks_from_ptree ~filename ptree =
+let semtoks_from_ptree ~filename ?range ptree =
   let open Cobol_parser.PTree_visitor in
   let open Cobol_ast.Terms_visitor in
   let open Cobol_ast.Operands_visitor in
   let open Cobol_common.Visitor in
 
-  let semtok_of lexloc category =
+  let acc_semtoks category loc acc =
     let toktyp, tokmods = match category with
       | ProgramName -> TOKTYP.string, TOKMOD.(union [definition; readonly])
       | ParagraphName -> TOKTYP.function_, TOKMOD.(one definition)
@@ -148,12 +154,10 @@ let semtoks_from_ptree ~filename ptree =
       | MnemonicName
       | FileName -> TOKTYP.variable, TOKMOD.(one readonly)
     in
-    semtok ~tokmods toktyp lexloc
+    acc_semtoks ~filename ?range ~tokmods toktyp loc acc
   in
-  let add_name' name toktyp acc =
-    List.rev_map
-      (fun lexloc -> semtok_of lexloc toktyp)
-      (single_line_lexlocs_in ~filename ~@name) @ acc
+  let add_name' name category acc =
+    acc_semtoks category ~@name acc
   in
   let rec add_qualname (qn:Cobol_ast.qualname) toktyp acc =
     match qn with
@@ -550,28 +554,30 @@ let semtoks_from_ptree ~filename ptree =
 
   end) ptree [] |> List.rev
 
-let semtoks_of_comments ~filename comments = comments |>
+let semtoks_of_comments ~filename ?range comments = comments |>
   List.filter_map begin function
     | Cobol_preproc.Text.{ comment_loc = s, _ as lexloc; _ }
-      when s.Lexing.pos_fname = filename ->
+      when s.Lexing.pos_fname = filename &&
+           Option.fold range
+             ~some:(fun r -> Lsp_position.intersects_lexloc r lexloc)
+             ~none:true ->
         Some (semtok TOKTYP.comment lexloc)
     | _ ->
         None
   end
 
-let semtoks_of_preproc_statements ~filename pplog =
+let semtoks_of_preproc_statements ~filename ?range pplog =
   List.rev @@ List.fold_left begin fun acc -> function
     | Cobol_preproc.Trace.FileCopy { copyloc = loc; _ }
     | Cobol_preproc.Trace.Replace { replloc = loc } ->
-        List.rev_map (semtok TOKTYP.macro)
-          (single_line_lexlocs_in ~filename loc) @ acc
+        acc_semtoks ~filename ?range TOKTYP.macro loc acc
     | Cobol_preproc.Trace.Replacement _ ->
         acc
   end [] (Cobol_preproc.Trace.events pplog)
 
 (** [semtoks_of_non_ambigious_tokens ~filename tokens] returns tokens that do
     not need to have more analyzing to get their type. *)
-let semtoks_of_non_ambigious_tokens ~filename tokens =
+let semtoks_of_non_ambigious_tokens ~filename ?range tokens =
   List.rev @@ List.fold_left begin fun acc { payload = token; loc } ->
     let semtok_infos = match token with
       | WORD _ | WORD_IN_AREA_A _ -> None
@@ -612,10 +618,10 @@ let semtoks_of_non_ambigious_tokens ~filename tokens =
           Some (TOKTYP.keyword, TOKMOD.none)
     in
     match semtok_infos with
-    | None -> acc
+    | None ->
+        acc
     | Some (toktyp, tokmods) ->
-        List.rev_map (semtok toktyp ~tokmods)
-          (single_line_lexlocs_in ~filename loc) @ acc
+        acc_semtoks ~filename ?range ~tokmods toktyp loc acc
   end [] tokens
 
 let compare_semtoks first second =
@@ -657,11 +663,11 @@ let ensure_sorted name ~filename cmp l =
       List.fast_sort cmp l
 
 
-let data ~filename ~tokens ~pplog ~comments ~ptree : int array =
-  let semtoks1 = semtoks_of_non_ambigious_tokens ~filename tokens in
-  let semtoks2 = semtoks_from_ptree              ~filename ptree in
-  let semtoks3 = semtoks_of_comments             ~filename comments in
-  let semtoks4 = semtoks_of_preproc_statements   ~filename pplog in
+let data ~filename ~range ~tokens ~pplog ~comments ~ptree : int array =
+  let semtoks1 = semtoks_of_non_ambigious_tokens ~filename ?range tokens in
+  let semtoks2 = semtoks_from_ptree              ~filename ?range ptree in
+  let semtoks3 = semtoks_of_comments             ~filename ?range comments in
+  let semtoks4 = semtoks_of_preproc_statements   ~filename ?range pplog in
   (* NB: In *principle* all those lists are already sorted w.r.t lexical
      locations in [filename].  We just check that for now and raise a warning,
      in case. *)
diff --git a/src/lsp/cobol_lsp/lsp_semtoks.mli b/src/lsp/cobol_lsp/lsp_semtoks.mli
index 6b684c9f6..e8b35572b 100644
--- a/src/lsp/cobol_lsp/lsp_semtoks.mli
+++ b/src/lsp/cobol_lsp/lsp_semtoks.mli
@@ -18,6 +18,7 @@ val token_modifiers: string list
    to lsp>=16, and avoid having to use an array below. *)
 val data
   : filename: string
+  -> range: Lsp.Types.Range.t option
   -> tokens: Cobol_parser.tokens_with_locs
   -> pplog: Cobol_preproc.log
   -> comments: Cobol_preproc.comments

From 2000b52a75bbeac4354e45ac7074998b566a61d3 Mon Sep 17 00:00:00 2001
From: Nicolas Berthier <nicolas.berthier@ocamlpro.com>
Date: Mon, 25 Sep 2023 17:06:25 +0200
Subject: [PATCH 09/17] Extract LSP capabilities out of `Lsp_request`

---
 src/lsp/cobol_lsp/lsp_capabilities.ml  | 50 ++++++++++++++++++++++++++
 src/lsp/cobol_lsp/lsp_capabilities.mli | 14 ++++++++
 src/lsp/cobol_lsp/lsp_request.ml       | 45 +++--------------------
 3 files changed, 68 insertions(+), 41 deletions(-)
 create mode 100644 src/lsp/cobol_lsp/lsp_capabilities.ml
 create mode 100644 src/lsp/cobol_lsp/lsp_capabilities.mli

diff --git a/src/lsp/cobol_lsp/lsp_capabilities.ml b/src/lsp/cobol_lsp/lsp_capabilities.ml
new file mode 100644
index 000000000..4d8aa2ca5
--- /dev/null
+++ b/src/lsp/cobol_lsp/lsp_capabilities.ml
@@ -0,0 +1,50 @@
+(**************************************************************************)
+(*                                                                        *)
+(*                        SuperBOL OSS Studio                             *)
+(*                                                                        *)
+(*  Copyright (c) 2022-2023 OCamlPro SAS                                  *)
+(*                                                                        *)
+(* All rights reserved.                                                   *)
+(* This source code is licensed under the GNU Affero General Public       *)
+(* License version 3 found in the LICENSE.md file in the root directory   *)
+(* of this source tree.                                                   *)
+(*                                                                        *)
+(**************************************************************************)
+
+open Lsp.Types
+
+(* Client capabilities are to be used for special request response, for example
+   a definition request can be answered with a LocationLink iff the client
+   supports it.
+
+   NOTE: For now we don't use them because we don't have any special
+   response. *)
+let reply (_: ClientCapabilities.t) =
+  let sync =
+    TextDocumentSyncOptions.create ()
+      ~openClose:true
+      ~change:Incremental
+  and semtoks =
+    let legend =
+      SemanticTokensLegend.create
+        ~tokenTypes:Lsp_semtoks.token_types
+        ~tokenModifiers:Lsp_semtoks.token_modifiers
+    in
+    SemanticTokensOptions.create ()
+      ~full:(`Full (SemanticTokensOptions.create_full ~delta:false ()))
+      ~range:true
+      ~legend
+  and hover =
+    HoverOptions.create ()
+  and completion_option =
+    CompletionOptions.create ()
+  in
+  ServerCapabilities.create ()
+    ~textDocumentSync:(`TextDocumentSyncOptions sync)
+    ~definitionProvider:(`Bool true)
+    ~referencesProvider:(`Bool true)
+    ~documentRangeFormattingProvider: (`Bool true)
+    ~documentFormattingProvider: (`Bool true)
+    ~semanticTokensProvider:(`SemanticTokensOptions semtoks)
+    ~hoverProvider:(`HoverOptions hover)
+    ~completionProvider:(completion_option)
diff --git a/src/lsp/cobol_lsp/lsp_capabilities.mli b/src/lsp/cobol_lsp/lsp_capabilities.mli
new file mode 100644
index 000000000..72fde01f4
--- /dev/null
+++ b/src/lsp/cobol_lsp/lsp_capabilities.mli
@@ -0,0 +1,14 @@
+(**************************************************************************)
+(*                                                                        *)
+(*                        SuperBOL OSS Studio                             *)
+(*                                                                        *)
+(*  Copyright (c) 2022-2023 OCamlPro SAS                                  *)
+(*                                                                        *)
+(* All rights reserved.                                                   *)
+(* This source code is licensed under the GNU Affero General Public       *)
+(* License version 3 found in the LICENSE.md file in the root directory   *)
+(* of this source tree.                                                   *)
+(*                                                                        *)
+(**************************************************************************)
+
+val reply: Lsp.Types.ClientCapabilities.t -> Lsp.Types.ServerCapabilities.t
diff --git a/src/lsp/cobol_lsp/lsp_request.ml b/src/lsp/cobol_lsp/lsp_request.ml
index 074b95978..e5b81a886 100644
--- a/src/lsp/cobol_lsp/lsp_request.ml
+++ b/src/lsp/cobol_lsp/lsp_request.ml
@@ -73,45 +73,9 @@ let try_with_document_data ~f =
 
 (** {2 Handling requests} *)
 
-(* Client capabilities are to be used for special request response, for example
-   a definition request can be answered with a LocationLink iff the client
-   supports it.
-
-   NOTE: For now we don't use them because we don't have any special
-   response. *)
-let make_capabilities (_: ClientCapabilities.t) =
-  let sync =
-    TextDocumentSyncOptions.create ()
-      ~openClose:true
-      ~change:Incremental
-  and semtoks =
-    let legend =
-      SemanticTokensLegend.create
-        ~tokenTypes:Lsp_semtoks.token_types
-        ~tokenModifiers:Lsp_semtoks.token_modifiers
-    in
-    SemanticTokensOptions.create ()
-      ~full:(`Full (SemanticTokensOptions.create_full ~delta:false ()))
-      ~range:true
-      ~legend
-  and hover =
-    HoverOptions.create ()
-  and completion_option =
-    CompletionOptions.create ()
-  in
-  ServerCapabilities.create ()
-    ~textDocumentSync:(`TextDocumentSyncOptions sync)
-    ~definitionProvider:(`Bool true)
-    ~referencesProvider:(`Bool true)
-    ~documentRangeFormattingProvider: (`Bool true)
-    ~documentFormattingProvider: (`Bool true)
-    ~semanticTokensProvider:(`SemanticTokensOptions semtoks)
-    ~hoverProvider:(`HoverOptions hover)
-    ~completionProvider:(completion_option)
-
 let handle_initialize (params: InitializeParams.t) =
   InitializeResult.create ()
-    ~capabilities:(make_capabilities params.capabilities)
+    ~capabilities:(Lsp_capabilities.reply params.capabilities)
 
 let find_definitions { location_of; _ } cu_name qn defs =
   let location_of_item { item_definition; _ } =
@@ -305,12 +269,11 @@ let handle_hover registry (params: HoverParams.t) =
     end
 
 let handle_completion registry (params:CompletionParams.t) =
-  let open Lsp_completion in
   try_with_document_data registry params.textDocument
     ~f:begin fun ~doc:{ textdoc; _ } { ast; _ } ->
-      let items = completion_items textdoc params.position ast in
-      let completionlist = CompletionList.create ~isIncomplete:false ~items () in
-      Some (`CompletionList completionlist)
+      let items = Lsp_completion.completion_items textdoc params.position ast in
+      Some (`CompletionList (CompletionList.create ()
+                               ~isIncomplete:false ~items))
     end
 
 let handle_shutdown registry =

From 1dd7416a00c5d2196ab73077e8f7e7858b9cf290 Mon Sep 17 00:00:00 2001
From: Nicolas Berthier <nicolas.berthier@ocamlpro.com>
Date: Mon, 25 Sep 2023 17:07:09 +0200
Subject: [PATCH 10/17] Disable partially implemented completion capability

---
 src/lsp/cobol_lsp/lsp_capabilities.ml | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/lsp/cobol_lsp/lsp_capabilities.ml b/src/lsp/cobol_lsp/lsp_capabilities.ml
index 4d8aa2ca5..fe296c908 100644
--- a/src/lsp/cobol_lsp/lsp_capabilities.ml
+++ b/src/lsp/cobol_lsp/lsp_capabilities.ml
@@ -36,8 +36,8 @@ let reply (_: ClientCapabilities.t) =
       ~legend
   and hover =
     HoverOptions.create ()
-  and completion_option =
-    CompletionOptions.create ()
+  (* and completion_option = *)
+  (*   CompletionOptions.create () *)
   in
   ServerCapabilities.create ()
     ~textDocumentSync:(`TextDocumentSyncOptions sync)
@@ -47,4 +47,4 @@ let reply (_: ClientCapabilities.t) =
     ~documentFormattingProvider: (`Bool true)
     ~semanticTokensProvider:(`SemanticTokensOptions semtoks)
     ~hoverProvider:(`HoverOptions hover)
-    ~completionProvider:(completion_option)
+    (* ~completionProvider:completion_option *)

From 343618951a9bed8b11c9b9db910da306e90ac4bb Mon Sep 17 00:00:00 2001
From: DAI Weituo <weituo.dai@polytechnique.edu>
Date: Tue, 18 Jul 2023 18:00:46 +0200
Subject: [PATCH 11/17] Add support for LSP folding range requests

Implements basic support for folding whole paragraphs, sections,
divisions, programs, and data grouped-item
---
 src/lsp/cobol_lsp/lsp_folding.ml | 148 +++++++++++++++++++++++++++++++
 1 file changed, 148 insertions(+)
 create mode 100644 src/lsp/cobol_lsp/lsp_folding.ml

diff --git a/src/lsp/cobol_lsp/lsp_folding.ml b/src/lsp/cobol_lsp/lsp_folding.ml
new file mode 100644
index 000000000..c9370b946
--- /dev/null
+++ b/src/lsp/cobol_lsp/lsp_folding.ml
@@ -0,0 +1,148 @@
+(******************************************************************************)
+(*                                                                            *)
+(*     Copyright (c) 2021-2023 OCamlPro SAS                                   *)
+(*                                                                            *)
+(*     All rights reserved.                                                   *)
+(*     This file is distributed under the terms of the                        *)
+(*     OCAMLPRO-NON-COMMERCIAL license.                                       *)
+(*                                                                            *)
+(******************************************************************************)
+
+open Cobol_common
+open Cobol_common.Srcloc.INFIX
+
+type folding_range = {
+  startLine:int;
+  endLine:int;
+  startCharacter:int;
+  endCharacter:int;
+  (* kind:Lsp.Types.FoldingRangeKind.t option *)
+  (* collapsedText:string option*)
+}
+
+let folding_range_of_loc loc =
+  match Srcloc.as_lexloc loc with
+  | (* None -> None *)
+  (* | Some *) (p1, p2) ->
+      Some {
+        startLine = p1.pos_lnum - 1;
+        startCharacter = p1.pos_cnum - p1.pos_bol;
+        endLine = p2.pos_lnum - 1;
+        endCharacter = p2.pos_cnum - p2.pos_bol
+      }
+
+let add_folding_range r l =
+  match r with
+  | None -> l
+  | Some r -> r :: l
+
+let add_folding_range_of_loc loc l =
+  add_folding_range (folding_range_of_loc loc) l
+
+
+let folding_range_division ast =
+
+  let visitor = Cobol_parser.PTree_visitor.fold_compilation_group (object
+    inherit [folding_range list] Cobol_parser.PTree_visitor.folder
+
+    method! fold_program_unit' {loc; _} acc =
+      Visitor.do_children @@
+        add_folding_range_of_loc loc acc
+
+    method! fold_procedure_division' {loc; _} acc =
+      Visitor.skip_children @@
+        add_folding_range_of_loc loc acc
+
+    method! fold_data_division' {loc; _} acc =
+      Visitor.skip_children @@
+        add_folding_range_of_loc loc acc
+
+    (*TODO: add location for some nodes in the ast
+            so we can define folding_range for
+            environment division, file section... (predefined section)*)
+    (* method! fold_environment_division' {loc; _} acc =
+      Visitor.skip_children @@
+        let folding_range = folding_range_of_loc loc in
+        add_folding_range folding_range acc *)
+  end) in
+  visitor ast []
+
+
+let folding_range_paragraph ast =
+  let update_section_range loc (section_range, l) =
+    match folding_range_of_loc loc with
+    | None -> section_range, l
+    | Some ({endLine; endCharacter; _} as r) ->
+        Option.map (
+          fun folding_range->
+            {folding_range with endLine; endCharacter}
+        ) section_range, r :: l
+  in
+
+  let add_section (r, l) = add_folding_range r l in
+
+  let visitor = Cobol_parser.PTree_visitor.fold_compilation_group (object
+    inherit [folding_range option *
+             folding_range list] Cobol_parser.PTree_visitor.folder
+
+    method! fold_paragraph' {payload = {paragraph_is_section; _}; loc} acc =
+      Visitor.skip_children @@
+        if not paragraph_is_section then
+          update_section_range loc acc
+        else
+          folding_range_of_loc loc,
+          add_section acc
+
+    end) in
+  add_section @@ visitor ast (None, [])
+
+
+(*TODO:
+  Now we use the result of Cobol_typeck (need to be rewritten),
+  which does not work for renames-item, condition-item ... *)
+let folding_range_data ({cu_wss; _}:Cobol_data.Types.compilation_unit) =
+  let update r group_range =
+    match r with
+    | None -> group_range
+    | Some {endLine; endCharacter; _} ->
+        Option.map (
+          fun folding_range ->
+            {folding_range with endLine; endCharacter}
+        ) group_range
+  in
+  (*add the folding_range of grouped item *)
+  let rec add group l =
+    let r = folding_range_of_loc ~@group in
+    match ~&group with
+    | Cobol_data.Group.Elementary _
+    | Constant _ | Renames _ | ConditionName _ -> None, l
+    | Group {elements; _} ->
+        let r, l =
+          List.fold_left
+            (fun (r, l) group -> aux group (r, l))
+            (r, l) elements
+        in
+        match r with
+        | None -> None, l
+        | Some r -> Some r, r :: l
+  (*traverse the elements, update the folding_range of grouped item*)
+  and aux group (r, l) =
+    match ~&group with
+    | Cobol_data.Group.Elementary _
+    | Constant _ | Renames _ | ConditionName _ ->
+        update (folding_range_of_loc ~@group) r, l
+    | Group _ ->
+        let r', l = add group l in
+        update r' r, l
+  in
+  Pretty.error "%a @." Cobol_data.Group.pp_data_group_list cu_wss;
+  List.fold_left
+    (fun acc group -> snd @@ add group acc) [] cu_wss
+
+
+let folding_range Lsp_document.TYPES.{ast; cus; _ }=
+  folding_range_paragraph ast @ folding_range_division ast @
+  ( Cobol_data.Compilation_unit.SET.to_seq cus
+    |> Seq.map (fun cu -> folding_range_data cu)
+    |> List.of_seq
+    |> List.flatten)

From e4e9080f632485c78528e05aa871996944915215 Mon Sep 17 00:00:00 2001
From: DAI Weituo <weituo.dai@polytechnique.edu>
Date: Wed, 19 Jul 2023 12:59:29 +0200
Subject: [PATCH 12/17] Add folding range for whole statements

---
 src/lsp/cobol_lsp/lsp_folding.ml | 49 ++++++++++++++++----------------
 1 file changed, 25 insertions(+), 24 deletions(-)

diff --git a/src/lsp/cobol_lsp/lsp_folding.ml b/src/lsp/cobol_lsp/lsp_folding.ml
index c9370b946..7c194d70c 100644
--- a/src/lsp/cobol_lsp/lsp_folding.ml
+++ b/src/lsp/cobol_lsp/lsp_folding.ml
@@ -14,8 +14,8 @@ open Cobol_common.Srcloc.INFIX
 type folding_range = {
   startLine:int;
   endLine:int;
-  startCharacter:int;
-  endCharacter:int;
+  startCharacter:int; (*not really used *)
+  endCharacter:int;   (*not really used *)
   (* kind:Lsp.Types.FoldingRangeKind.t option *)
   (* collapsedText:string option*)
 }
@@ -39,31 +39,33 @@ let add_folding_range r l =
 let add_folding_range_of_loc loc l =
   add_folding_range (folding_range_of_loc loc) l
 
-
-let folding_range_division ast =
-
+(*Define the folding_range of program/division/statement...
+  We do not need to do any analyze here.
+  However, we need to refine the code of parser/visitor first.*)
+let folding_range_simple ast =
+  let add_node n acc =
+    Visitor.do_children @@ add_folding_range_of_loc ~@n acc
+  in
   let visitor = Cobol_parser.PTree_visitor.fold_compilation_group (object
     inherit [folding_range list] Cobol_parser.PTree_visitor.folder
 
-    method! fold_program_unit' {loc; _} acc =
-      Visitor.do_children @@
-        add_folding_range_of_loc loc acc
+    method! fold_program_unit' = add_node
+    method! fold_data_division' = add_node
+    method! fold_procedure_division' = add_node
+    method! fold_statement' = add_node
 
-    method! fold_procedure_division' {loc; _} acc =
-      Visitor.skip_children @@
-        add_folding_range_of_loc loc acc
+    (*TODO:
+      - add location for some nodes in the ast
+        so that we can define folding_range for
+        environment division, file section... (predefined section)
 
-    method! fold_data_division' {loc; _} acc =
-      Visitor.skip_children @@
-        add_folding_range_of_loc loc acc
+      - it is possible to add folding_range for
+        - branch of statement(else_branch, evaluate_branch...)
+        - handler(on_size_error)
+        - inline_call
+
+      - add folding_range for other type of compilation_unit (not program) *)
 
-    (*TODO: add location for some nodes in the ast
-            so we can define folding_range for
-            environment division, file section... (predefined section)*)
-    (* method! fold_environment_division' {loc; _} acc =
-      Visitor.skip_children @@
-        let folding_range = folding_range_of_loc loc in
-        add_folding_range folding_range acc *)
   end) in
   visitor ast []
 
@@ -98,7 +100,7 @@ let folding_range_paragraph ast =
 
 
 (*TODO:
-  Now we use the result of Cobol_typeck (need to be rewritten),
+  Now we use the type Group.t (need to be rewritten),
   which does not work for renames-item, condition-item ... *)
 let folding_range_data ({cu_wss; _}:Cobol_data.Types.compilation_unit) =
   let update r group_range =
@@ -135,13 +137,12 @@ let folding_range_data ({cu_wss; _}:Cobol_data.Types.compilation_unit) =
         let r', l = add group l in
         update r' r, l
   in
-  Pretty.error "%a @." Cobol_data.Group.pp_data_group_list cu_wss;
   List.fold_left
     (fun acc group -> snd @@ add group acc) [] cu_wss
 
 
 let folding_range Lsp_document.TYPES.{ast; cus; _ }=
-  folding_range_paragraph ast @ folding_range_division ast @
+  folding_range_paragraph ast @ folding_range_simple ast @
   ( Cobol_data.Compilation_unit.SET.to_seq cus
     |> Seq.map (fun cu -> folding_range_data cu)
     |> List.of_seq

From 64c8a5114195379648ebeb54ae4ea2d200366a7e Mon Sep 17 00:00:00 2001
From: Nicolas Berthier <nicolas.berthier@ocamlpro.com>
Date: Tue, 26 Sep 2023 08:48:24 +0200
Subject: [PATCH 13/17] Add LSP folding-range capability

---
 src/lsp/cobol_lsp/lsp_capabilities.ml |  1 +
 src/lsp/cobol_lsp/lsp_folding.ml      | 14 +++++++++-----
 src/lsp/cobol_lsp/lsp_request.ml      | 28 +++++++++++++++++++++------
 3 files changed, 32 insertions(+), 11 deletions(-)

diff --git a/src/lsp/cobol_lsp/lsp_capabilities.ml b/src/lsp/cobol_lsp/lsp_capabilities.ml
index fe296c908..6b474467a 100644
--- a/src/lsp/cobol_lsp/lsp_capabilities.ml
+++ b/src/lsp/cobol_lsp/lsp_capabilities.ml
@@ -47,4 +47,5 @@ let reply (_: ClientCapabilities.t) =
     ~documentFormattingProvider: (`Bool true)
     ~semanticTokensProvider:(`SemanticTokensOptions semtoks)
     ~hoverProvider:(`HoverOptions hover)
+    ~foldingRangeProvider:(`Bool true)
     (* ~completionProvider:completion_option *)
diff --git a/src/lsp/cobol_lsp/lsp_folding.ml b/src/lsp/cobol_lsp/lsp_folding.ml
index 7c194d70c..5759e7606 100644
--- a/src/lsp/cobol_lsp/lsp_folding.ml
+++ b/src/lsp/cobol_lsp/lsp_folding.ml
@@ -102,7 +102,7 @@ let folding_range_paragraph ast =
 (*TODO:
   Now we use the type Group.t (need to be rewritten),
   which does not work for renames-item, condition-item ... *)
-let folding_range_data ({cu_wss; _}:Cobol_data.Types.compilation_unit) =
+let folding_range_data ({ cu_wss; _ }:Cobol_data.Types.compilation_unit) =
   let update r group_range =
     match r with
     | None -> group_range
@@ -141,9 +141,13 @@ let folding_range_data ({cu_wss; _}:Cobol_data.Types.compilation_unit) =
     (fun acc group -> snd @@ add group acc) [] cu_wss
 
 
-let folding_range Lsp_document.TYPES.{ast; cus; _ }=
-  folding_range_paragraph ast @ folding_range_simple ast @
-  ( Cobol_data.Compilation_unit.SET.to_seq cus
+let folding_range ptree cus =
+  let folding_range_cus =
+    Cobol_data.Compilation_unit.SET.to_seq cus
     |> Seq.map (fun cu -> folding_range_data cu)
     |> List.of_seq
-    |> List.flatten)
+    |> List.flatten
+  in
+  folding_range_paragraph ptree @
+  folding_range_simple ptree @
+  folding_range_cus
diff --git a/src/lsp/cobol_lsp/lsp_request.ml b/src/lsp/cobol_lsp/lsp_request.ml
index e5b81a886..3af5ebbe8 100644
--- a/src/lsp/cobol_lsp/lsp_request.ml
+++ b/src/lsp/cobol_lsp/lsp_request.ml
@@ -268,7 +268,7 @@ let handle_hover registry (params: HoverParams.t) =
           None
     end
 
-let handle_completion registry (params:CompletionParams.t) =
+let handle_completion registry (params: CompletionParams.t) =
   try_with_document_data registry params.textDocument
     ~f:begin fun ~doc:{ textdoc; _ } { ast; _ } ->
       let items = Lsp_completion.completion_items textdoc params.position ast in
@@ -276,6 +276,21 @@ let handle_completion registry (params:CompletionParams.t) =
                                ~isIncomplete:false ~items))
     end
 
+(*TODO(if necessary):
+    Now, the request folding has the default perfomance (in VS Code)
+    It only supports folding complete lines, and does
+    not support FoldingRangeKind or CollapsedText
+    (To support these features, need to change the client capability) *)
+let handle_folding_range registry (params: FoldingRangeParams.t) =
+  try_with_document_data registry params.textDocument
+    ~f:begin fun ~doc:_ { ast; cus; _ } ->
+      Some (List.map
+              (fun Lsp_folding.{startLine; endLine; _} ->
+                 FoldingRange.create ~startLine ~endLine ())
+              (Lsp_folding.folding_range ast cus)
+            )
+    end
+
 let handle_shutdown registry =
   try Lsp_server.save_project_caches registry
   with e ->
@@ -308,10 +323,12 @@ let on_request
         Ok (handle_semtoks_full registry params, state)
     | SemanticTokensRange params ->
         Ok (handle_semtoks_range registry params, state)
-    | TextDocumentHover hover_params ->
-        Ok (handle_hover registry hover_params, state)
-    | TextDocumentCompletion completion_params ->
-        Ok (handle_completion registry completion_params, state)
+    | TextDocumentHover params ->
+        Ok (handle_hover registry params, state)
+    | TextDocumentCompletion params ->
+        Ok (handle_completion registry params, state)
+    | TextDocumentFoldingRange params ->
+        Ok (handle_folding_range registry params, state)
     | Shutdown ->
         Ok (handle_shutdown registry, ShuttingDown)
     | TextDocumentDeclaration  (* TextDocumentPositionParams.t.t *) _
@@ -330,7 +347,6 @@ let on_request
     | DebugEcho (* DebugEcho.Params.t *) _
     | DebugTextDocumentGet  (* DebugTextDocumentGet.Params.t *) _
     | TextDocumentHighlight  (* DocumentHighlightParams.t.t *) _
-    | TextDocumentFoldingRange  (* FoldingRangeParams.t.t *) _
     | SignatureHelp  (* SignatureHelpParams.t.t *) _
     | CodeAction  (* CodeActionParams.t.t *) _
     | CodeActionResolve  (* CodeAction.t.t *) _

From 9776e1f32c225e0a3a0ba67b780af2e991cc7457 Mon Sep 17 00:00:00 2001
From: Nicolas Berthier <nicolas.berthier@ocamlpro.com>
Date: Tue, 26 Sep 2023 11:27:18 +0200
Subject: [PATCH 14/17] Add some more wide-ranging source locations in the AST

---
 src/lsp/cobol_ast/misc_descr.ml               |  34 +-
 src/lsp/cobol_ast/raw.ml                      |  57 +--
 .../raw_compilation_group_visitor.ml          |  23 +-
 .../cobol_ast/raw_data_division_visitor.ml    |  52 +-
 .../cobol_ast/raw_misc_sections_visitor.ml    |  35 +-
 src/lsp/cobol_parser/grammar.mly              |  84 ++--
 src/lsp/cobol_parser/grammar_printer.ml       |  72 +--
 src/lsp/cobol_parser/grammar_recover.ml       | 450 +++++++++---------
 src/lsp/cobol_typeck/cobol_typeck.ml          |   2 +-
 9 files changed, 436 insertions(+), 373 deletions(-)

diff --git a/src/lsp/cobol_ast/misc_descr.ml b/src/lsp/cobol_ast/misc_descr.ml
index 38275dbd1..a6f9ba706 100644
--- a/src/lsp/cobol_ast/misc_descr.ml
+++ b/src/lsp/cobol_ast/misc_descr.ml
@@ -38,18 +38,18 @@ type informational_paragraphs =
 (* ------------------------- ENVIRONMENT DIVISION -------------------------- *)
 type environment_division =
   {
-    env_configuration: configuration_section option;
-    env_input_output: input_output_section option;
+    env_configuration: configuration_section with_loc option;
+    env_input_output: input_output_section with_loc option;
   }
 [@@deriving ord]
 
 (* ------------- ENVIRONMENT DIVISION / CONFIGURATION SECTION -------------- *)
 and configuration_section =
   {
-    source_computer_paragraph: source_computer_paragraph option;
-    object_computer_paragraph: object_computer_paragraph option;
-    special_names_paragraph: special_names_paragraph option;
-    repository_paragraph: repository_paragraph option; (* +COB2002 *)
+    source_computer_paragraph: source_computer_paragraph with_loc option;
+    object_computer_paragraph: object_computer_paragraph with_loc option;
+    special_names_paragraph: special_names_paragraph with_loc option;
+    repository_paragraph: repository_paragraph with_loc option;   (* +COB2002 *)
   }
 
 (* ENVIRONMENT DIVISION / CONFIGURATION SECTION / SOURCE-COMPUTER PARAGRAPH *)
@@ -237,8 +237,8 @@ and expands =
 (* -------------- ENVIRONMENT DIVISION / INPUT-OUTPUT SECTION -------------- *)
 and input_output_section =
   {
-    file_control_paragraph: file_control_paragraph option; (* COB85: mandatory *)
-    io_control_paragraph: io_control_paragraph option;
+    file_control_paragraph: file_control_paragraph with_loc option; (* COB85: mandatory *)
+    io_control_paragraph: io_control_paragraph with_loc option;
   }
 
 (* - ENVIRONMENT DIVISION / INPUT-OUTPUT SECTION / FILE-CONTROL PARAGRAPH -- *)
@@ -592,10 +592,10 @@ let pp_configuration_section ppf
     special_names_paragraph = snp; repository_paragraph = rp }
 =
   Fmt.pf ppf "CONFIGURATION SECTION.%a%a%a%a"
-    Fmt.(option (sp ++ pp_source_computer_paragraph)) scp
-    Fmt.(option (sp ++ pp_object_computer_paragraph)) ocp
-    Fmt.(option (sp ++ pp_special_names_paragraph)) snp
-    Fmt.(option (sp ++ pp_repository_paragraph)) rp
+    Fmt.(option (sp ++ pp_with_loc pp_source_computer_paragraph)) scp
+    Fmt.(option (sp ++ pp_with_loc pp_object_computer_paragraph)) ocp
+    Fmt.(option (sp ++ pp_with_loc pp_special_names_paragraph)) snp
+    Fmt.(option (sp ++ pp_with_loc pp_repository_paragraph)) rp
 
 let pp_record_delimiter ppf = function
   | Standard_1 -> Fmt.pf ppf "STANDARD-1"
@@ -678,15 +678,15 @@ let pp_input_output_section ppf
   { file_control_paragraph = fcp ; io_control_paragraph = icp }
 =
   Fmt.pf ppf "INPUT-OUTPUT SECTION.";
-  Fmt.(option (sp ++ pp_file_control_paragraph)) ppf fcp;
-  Fmt.(option (sp ++ pp_io_control_paragraph)) ppf icp
+  Fmt.(option (sp ++ pp_with_loc pp_file_control_paragraph)) ppf fcp;
+  Fmt.(option (sp ++ pp_with_loc pp_io_control_paragraph)) ppf icp
 
 let pp_environment_division ppf
   { env_configuration = ec; env_input_output = eio }
 =
   Fmt.pf ppf "ENVIRONMENT DIVISION.%a%a"
-    Fmt.(option (sp ++ pp_configuration_section)) ec
-    Fmt.(option (sp ++ pp_input_output_section)) eio
+    Fmt.(option (sp ++ pp_with_loc pp_configuration_section)) ec
+    Fmt.(option (sp ++ pp_with_loc pp_input_output_section)) eio
 
 type options_paragraph =
   options_clause with_loc list
@@ -738,4 +738,4 @@ let pp_options_paragraph : options_paragraph Fmt.t =
     any "OPTIONS.@ " ++
     box (list ~sep:sp (pp_with_loc pp_options_clause))
     ++ any "."
-  )
\ No newline at end of file
+  )
diff --git a/src/lsp/cobol_ast/raw.ml b/src/lsp/cobol_ast/raw.ml
index 30f16a56b..3152ec305 100644
--- a/src/lsp/cobol_ast/raw.ml
+++ b/src/lsp/cobol_ast/raw.ml
@@ -565,27 +565,22 @@ module Data_division (Data_sections: Abstract.DATA_SECTIONS) = struct
 
   type data_division =
     {
-      file_section: file_section option;
-      working_storage_section: working_storage_section option;
-      linkage_section: linkage_section option;
-      communication_section: communication_section option;
-      local_storage_section: local_storage_section option;
-      report_section: report_section option;
-      screen_section: screen_section option;
+      file_section: file_section with_loc option;
+      working_storage_section: working_storage_section with_loc option;
+      linkage_section: linkage_section with_loc option;
+      communication_section: communication_section with_loc option;
+      local_storage_section: local_storage_section with_loc option;
+      report_section: report_section with_loc option;
+      screen_section: screen_section with_loc option;
     }
   [@@deriving ord]
 
-  let pp_data_division ppf {
-      file_section;
-      working_storage_section;
-      linkage_section;
-      communication_section;
-      local_storage_section;
-      report_section;
-      screen_section;
-  } =
+  let pp_data_division ppf { file_section;
+                             working_storage_section; linkage_section;
+                             communication_section; local_storage_section;
+                             report_section; screen_section } =
     let pp_section pp ppf section =
-      Fmt.(option (sp ++ vbox pp)) ppf section
+      Fmt.(option (sp ++ vbox (pp_with_loc pp))) ppf section
     in
     Fmt.pf ppf "@[<v 2>DATA DIVISION.";
     pp_section pp_file_section ppf file_section;
@@ -813,7 +808,7 @@ struct
       program_name: name with_loc;
       program_as: strlit option;
       program_level: program_level;
-      program_options: options_paragraph option;
+      program_options: options_paragraph with_loc option;
       program_env: environment_division with_loc option;
       program_data: data_division with_loc option;
       program_proc: procedure_division with_loc option;
@@ -878,7 +873,7 @@ struct
       | ProgramPrototype -> Fmt.pf ppf "@ PROTOTYPE"
     );
     Fmt.pf ppf ".@]";
-    Fmt.(option (sp ++ pp_options_paragraph)) ppf program_options;
+    Fmt.(option (sp ++ pp_with_loc pp_options_paragraph)) ppf program_options;
     Fmt.(option (sp ++ pp_with_loc pp_environment_division)) ppf program_env;
     Fmt.(option (sp ++ pp_with_loc pp_data_division)) ppf program_data;
     Fmt.(option (sp ++ pp_with_loc pp_procedure_division)) ppf program_proc;
@@ -892,7 +887,7 @@ struct
       function_name: name with_loc;
       function_as: strlit option;
       function_is_proto: bool;
-      function_options: options_paragraph option;
+      function_options: options_paragraph with_loc option;
       function_env: environment_division with_loc option;
       function_data: data_division with_loc option;
       function_proc: procedure_division option;
@@ -926,7 +921,7 @@ struct
     pp_id_paragraph ~name:en "FUNCTION-ID" "FUNCTION" ppf
       Fmt.(sp ++ pp_function_id_paragraph ++ any ".") (n, fas, is_proto)
       Fmt.[
-        Option.map (const pp_options_paragraph) opts;
+        Option.map (const (pp_with_loc pp_options_paragraph)) opts;
         Option.map (const (pp_with_loc pp_environment_division)) env;
         Option.map (const (pp_with_loc pp_data_division)) data;
         Option.map (const pp_procedure_division) proc;
@@ -938,7 +933,7 @@ struct
       method_kind: method_kind;
       method_override: bool;
       method_final: bool;
-      method_options: options_paragraph option;
+      method_options: options_paragraph with_loc option;
       method_env: environment_division with_loc option;
       method_data: data_division with_loc option;
       method_proc: procedure_division option;
@@ -967,7 +962,7 @@ struct
     pp_id_paragraph ~name:en "METHOD-ID" "METHOD" ppf
       Fmt.(sp ++ pp_method_id_paragraph ++ any ".") (n, k, o, f)
       Fmt.[
-        Option.map (const pp_options_paragraph) opts;
+        Option.map (const (pp_with_loc pp_options_paragraph)) opts;
         Option.map (const (pp_with_loc pp_environment_division)) env;
         Option.map (const (pp_with_loc pp_data_division)) data;
         Option.map (const pp_procedure_division) proc;
@@ -976,7 +971,7 @@ struct
   type factory_definition = (* Note: could be merged with instance_definition *)
     {
       factory_implements: name with_loc list;
-      factory_options: options_paragraph option;
+      factory_options: options_paragraph with_loc option;
       factory_env: environment_division with_loc option;
       factory_data: data_division with_loc option;
       factory_methods: method_definition with_loc list option;
@@ -1001,7 +996,7 @@ struct
     pp_id_paragraph ~end_:true "FACTORY" "FACTORY" ppf
       pp_implements impl
       Fmt.[
-        Option.map (const pp_options_paragraph) opts;
+        Option.map (const (pp_with_loc pp_options_paragraph)) opts;
         Option.map (const (pp_with_loc pp_environment_division)) env;
         Option.map (const (pp_with_loc pp_data_division)) data;
         Option.map (const pp_object_procedure_division) meths;
@@ -1010,7 +1005,7 @@ struct
   type instance_definition =
     {
       instance_implements: name with_loc list;
-      instance_options: options_paragraph option;
+      instance_options: options_paragraph with_loc option;
       instance_env: environment_division with_loc option;
       instance_data: data_division with_loc option;
       instance_methods: method_definition with_loc list option;
@@ -1024,7 +1019,7 @@ struct
     pp_id_paragraph ~end_:true "OBJECT" "OBJECT" ppf
       pp_implements impl
       Fmt.[
-        Option.map (const pp_options_paragraph) opts;
+        Option.map (const (pp_with_loc pp_options_paragraph)) opts;
         Option.map (const (pp_with_loc pp_environment_division)) env;
         Option.map (const (pp_with_loc pp_data_division)) data;
         Option.map (const pp_object_procedure_division) meths;
@@ -1038,7 +1033,7 @@ struct
       class_final: bool;
       class_inherits: name with_loc list;
       class_usings: name with_loc list;
-      class_options: options_paragraph option;
+      class_options: options_paragraph with_loc option;
       class_env: environment_division with_loc option;
       class_factory: factory_definition option;
       class_instance: instance_definition option;
@@ -1064,7 +1059,7 @@ struct
     pp_id_paragraph ~name:en "CLASS-ID" "CLASS" ppf
       Fmt.(sp ++ pp_class_id_paragraph) (cn, cas, f, inh, us)
       Fmt.[
-        Option.map (const pp_options_paragraph) opts;
+        Option.map (const (pp_with_loc pp_options_paragraph)) opts;
         Option.map (const (pp_with_loc pp_environment_division)) env;
         Option.map (const pp_factory_definition) fac;
         Option.map (const pp_instance_definition) inst;
@@ -1077,7 +1072,7 @@ struct
       interface_as: strlit option;
       interface_inherits: name with_loc list;
       interface_usings: name with_loc list;
-      interface_options: options_paragraph option;
+      interface_options: options_paragraph with_loc option;
       interface_env: environment_division with_loc option;
       interface_methods: method_definition with_loc list option;
       interface_end_name: name with_loc;
@@ -1105,7 +1100,7 @@ struct
     pp_id_paragraph ~name:en "INTERFACE-ID" "INTERFACE" ppf
       Fmt.(sp ++ pp_interface_id_paragraph ++ any ".") (n, a, inh, us)
       Fmt.[
-        Option.map (const pp_options_paragraph) opts;
+        Option.map (const (pp_with_loc pp_options_paragraph)) opts;
         Option.map (const (pp_with_loc pp_environment_division)) env;
         Option.map (const pp_object_procedure_division) meths;
       ]
diff --git a/src/lsp/cobol_ast/raw_compilation_group_visitor.ml b/src/lsp/cobol_ast/raw_compilation_group_visitor.ml
index a19774055..846d17e77 100644
--- a/src/lsp/cobol_ast/raw_compilation_group_visitor.ml
+++ b/src/lsp/cobol_ast/raw_compilation_group_visitor.ml
@@ -46,6 +46,8 @@ struct
     inherit ['a] Terms_visitor.folder
     inherit ['a] Misc_sections_visitor.folder
     inherit ['a] Data_division_visitor.folder
+    method fold_options_paragraph'       : (options_paragraph with_loc   , 'a) fold = default
+    method fold_environment_division'    : (environment_division with_loc, 'a) fold = default
     method fold_data_division'           : (data_division with_loc       , 'a) fold = default
     inherit ['a] Proc_division_visitor.folder
     method fold_procedure_division'      : (procedure_division with_loc  , 'a) fold = default
@@ -67,11 +69,16 @@ struct
   let todo    x = todo    __MODULE__ x
   let partial x = partial __MODULE__ x
 
-  let fold_options_paragraph_opt (v: _ #folder) =
-    fold_option ~fold:(fun v -> v#continue_with_options_paragraph) v
+  let fold_options_paragraph' (v: _ #folder) =
+    handle' v#fold_options_paragraph' v
+      ~fold:(fun v -> v#continue_with_options_paragraph)
+
+  let fold_options_paragraph'_opt (v: _ #folder) =
+    fold_option ~fold:fold_options_paragraph' v
 
   let fold_environment_division' (v: _ #folder) =
-    fold' ~fold:(fun v -> v#continue_with_environment_division) v
+    handle' v#fold_environment_division' v
+      ~fold:(fun v -> v#continue_with_environment_division)
 
   let fold_environment_division'_opt (v: _ #folder) =
     fold_option ~fold:fold_environment_division' v
@@ -99,7 +106,7 @@ struct
                             program_proc; program_end_name } x -> x
         >> fold_name' v program_name
         >> fold_strlit_opt v program_as
-        >> fold_options_paragraph_opt v program_options
+        >> fold_options_paragraph'_opt v program_options
         >> fold_environment_division'_opt v program_env
         >> fold_data_division'_opt v program_data
         >> (fun x -> match program_level with
@@ -126,7 +133,7 @@ struct
         >> fold_name' v function_name
         >> fold_strlit_opt v function_as
         >> fold_bool v function_is_proto                      (* XXX: useful? *)
-        >> fold_options_paragraph_opt v function_options
+        >> fold_options_paragraph'_opt v function_options
         >> fold_environment_division'_opt v function_env
         >> fold_data_division'_opt v function_data
         >> fold_procedure_division_opt v function_proc
@@ -153,7 +160,7 @@ struct
         >> fold_method_kind v method_kind
         >> fold_bool v method_override
         >> fold_bool v method_final
-        >> fold_options_paragraph_opt v method_options
+        >> fold_options_paragraph'_opt v method_options
         >> fold_environment_division'_opt v method_env
         >> fold_data_division'_opt v method_data
         >> fold_procedure_division_opt v method_proc
@@ -165,7 +172,7 @@ struct
       ~continue:begin fun { factory_implements; factory_options; factory_env;
                             factory_data; factory_methods } x -> x
         >> fold_name'_list v factory_implements
-        >> fold_options_paragraph_opt v factory_options
+        >> fold_options_paragraph'_opt v factory_options
         >> fold_environment_division'_opt v factory_env
         >> fold_data_division'_opt v factory_data
         >> fold_option v factory_methods
@@ -180,7 +187,7 @@ struct
         partial __LINE__ "fold_instance_definition" ();
         x
         >> fold_name'_list v instance_implements
-        >> fold_options_paragraph_opt v instance_options
+        >> fold_options_paragraph'_opt v instance_options
         >> fold_data_division'_opt v instance_data
         >> fold_option v instance_methods
           ~fold:(fold_with_loc_list ~fold:fold_method_definition)
diff --git a/src/lsp/cobol_ast/raw_data_division_visitor.ml b/src/lsp/cobol_ast/raw_data_division_visitor.ml
index fb1b5d85c..b10d1aa11 100644
--- a/src/lsp/cobol_ast/raw_data_division_visitor.ml
+++ b/src/lsp/cobol_ast/raw_data_division_visitor.ml
@@ -11,6 +11,7 @@
 (*                                                                        *)
 (**************************************************************************)
 
+open Cobol_common.Srcloc.TYPES
 open Cobol_common.Visitor
 open Cobol_common.Visitor.INFIX                         (* for `>>` (== `|>`) *)
 
@@ -31,12 +32,49 @@ struct
   module Data_division_visitor =
     Abstract_visitor.For_data_division (Data_division)
 
+  open Data_sections
+
   class virtual ['a] folder = object
     inherit ['a] Terms_visitor.folder
     inherit ['a] Data_sections_visitor.folder
     inherit ['a] Data_division_visitor.folder
+    method fold_file_section': (file_section with_loc, 'a) fold = default
+    method fold_working_storage_section': (working_storage_section with_loc, 'a) fold = default
+    method fold_linkage_section': (linkage_section with_loc, 'a) fold = default
+    method fold_communication_section': (communication_section with_loc, 'a) fold = default
+    method fold_local_storage_section': (local_storage_section with_loc, 'a) fold = default
+    method fold_report_section': (report_section with_loc, 'a) fold = default
+    method fold_screen_section': (screen_section with_loc, 'a) fold = default
   end
 
+  let fold_file_section' (v: _ #folder) =
+    handle' v#fold_file_section' v
+      ~fold:(fun v -> v#continue_with_file_section)
+
+  let fold_working_storage_section' (v: _ #folder) =
+    handle' v#fold_working_storage_section' v
+      ~fold:(fun v -> v#continue_with_working_storage_section)
+
+  let fold_linkage_section' (v: _ #folder) =
+    handle' v#fold_linkage_section' v
+      ~fold:(fun v -> v#continue_with_linkage_section)
+
+  let fold_communication_section' (v: _ #folder) =
+    handle' v#fold_communication_section' v
+      ~fold:(fun v -> v#continue_with_communication_section)
+
+  let fold_local_storage_section' (v: _ #folder) =
+    handle' v#fold_local_storage_section' v
+      ~fold:(fun v -> v#continue_with_local_storage_section)
+
+  let fold_report_section' (v: _ #folder) =
+    handle' v#fold_report_section' v
+      ~fold:(fun v -> v#continue_with_report_section)
+
+  let fold_screen_section' (v: _ #folder) =
+    handle' v#fold_screen_section' v
+      ~fold:(fun v -> v#continue_with_screen_section)
+
   let fold_data_division (v: _#folder) =
     handle v#fold_data_division
       ~continue:begin fun { file_section; working_storage_section;
@@ -44,19 +82,19 @@ struct
                             local_storage_section; report_section;
                             screen_section } x -> x
         >> fold_option v file_section
-          ~fold:(fun v -> v#continue_with_file_section)
+          ~fold:fold_file_section'
         >> fold_option v working_storage_section
-          ~fold:(fun v -> v#continue_with_working_storage_section)
+          ~fold:fold_working_storage_section'
         >> fold_option v linkage_section
-          ~fold:(fun v -> v#continue_with_linkage_section)
+          ~fold:fold_linkage_section'
         >> fold_option v communication_section
-          ~fold:(fun v -> v#continue_with_communication_section)
+          ~fold:fold_communication_section'
         >> fold_option v local_storage_section
-          ~fold:(fun v -> v#continue_with_local_storage_section)
+          ~fold:fold_local_storage_section'
         >> fold_option v report_section
-          ~fold:(fun v -> v#continue_with_report_section)
+          ~fold:fold_report_section'
         >> fold_option v screen_section
-          ~fold:(fun v -> v#continue_with_screen_section)
+          ~fold:fold_screen_section'
       end
 
 end
diff --git a/src/lsp/cobol_ast/raw_misc_sections_visitor.ml b/src/lsp/cobol_ast/raw_misc_sections_visitor.ml
index 983164801..b84b92df3 100644
--- a/src/lsp/cobol_ast/raw_misc_sections_visitor.ml
+++ b/src/lsp/cobol_ast/raw_misc_sections_visitor.ml
@@ -33,16 +33,20 @@ module Make = struct
     inherit ['a] Misc_sections_visitor.folder
     method fold_options_clause: (options_clause, 'a) fold = default
     method fold_configuration_section: (configuration_section, 'a) fold = default
+    method fold_configuration_section': (configuration_section with_loc, 'a) fold = default
     method fold_special_names_paragraph: (special_names_paragraph, 'a) fold = default
     method fold_special_names_clause: (special_names_clause, 'a) fold = default
     method fold_special_names_clause': (special_names_clause with_loc, 'a) fold = default
     method fold_repository_paragraph: (repository_paragraph, 'a) fold = default
+    method fold_repository_paragraph': (repository_paragraph with_loc, 'a) fold = default
     method fold_specifier: (specifier, 'a) fold = default
     method fold_expands: (expands, 'a) fold = default
     method fold_select: (select, 'a) fold = default
     method fold_select_clause: (select_clause, 'a) fold = default
     method fold_file_control_paragraph: (file_control_paragraph, 'a) fold = default
+    method fold_file_control_paragraph': (file_control_paragraph with_loc, 'a) fold = default
     method fold_io_control_paragraph: (io_control_paragraph, 'a) fold = default
+    method fold_io_control_paragraph': (io_control_paragraph with_loc, 'a) fold = default
     method fold_io_control_entry: (io_control_entry, 'a) fold = default
     method fold_rerun_clause: (rerun_clause, 'a) fold = default
     method fold_rerun_frequency: (rerun_frequency, 'a) fold = default
@@ -51,6 +55,7 @@ module Make = struct
     method fold_multiple_file_clause: (multiple_file_clause, 'a) fold = default
     method fold_file_portion: (file_portion, 'a) fold = default
     method fold_input_output_section: (input_output_section, 'a) fold = default
+    method fold_input_output_section': (input_output_section with_loc, 'a) fold = default
     method fold_alphabet_specification: (alphabet_specification, 'a) fold = default
   end
 
@@ -77,6 +82,10 @@ module Make = struct
     handle v#fold_file_control_paragraph
       ~continue:(fold_list ~fold:fold_select v)
 
+  let fold_file_control_paragraph' (v: _ #folder) =
+    handle' v#fold_file_control_paragraph' v
+      ~fold:fold_file_control_paragraph
+
   let fold_rerun_frequency (v: _ #folder) =
     handle v#fold_rerun_frequency
       ~continue:begin function
@@ -133,15 +142,23 @@ module Make = struct
     handle v#fold_io_control_paragraph
       ~continue:(fold_option ~fold:fold_io_control_entry v)
 
+  let fold_io_control_paragraph' (v: _ #folder) =
+    handle' v#fold_io_control_paragraph' v
+      ~fold:fold_io_control_paragraph
+
   let fold_input_output_section (v: _ #folder) =
     handle v#fold_input_output_section
       ~continue:begin fun { file_control_paragraph; io_control_paragraph } x -> x
         >> fold_option v file_control_paragraph
-          ~fold:fold_file_control_paragraph
+          ~fold:fold_file_control_paragraph'
         >> fold_option v io_control_paragraph
-          ~fold:fold_io_control_paragraph
+          ~fold:fold_io_control_paragraph'
       end
 
+  let fold_input_output_section' (v: _ #folder) =
+    handle' v#fold_input_output_section' v
+      ~fold:fold_input_output_section
+
   (* --- *)
 
   let fold_informational_paragraphs (v: _ #folder) =
@@ -189,6 +206,10 @@ module Make = struct
     handle v#fold_repository_paragraph
       ~continue:(fold_list ~fold:fold_specifier v)
 
+  let fold_repository_paragraph' (v: _ #folder) =
+    handle' v#fold_repository_paragraph' v
+      ~fold:fold_repository_paragraph
+
   let fold_special_names_clause (v: _ #folder) =
     handle v#fold_special_names_clause
       ~continue:begin fun c x -> match c with
@@ -217,14 +238,18 @@ module Make = struct
         ignore special_names_paragraph;
         x
         >> partial __LINE__ "fold_configuration_section"
-        >> fold_option ~fold:fold_repository_paragraph v repository_paragraph
+        >> fold_option ~fold:fold_repository_paragraph' v repository_paragraph
       end
 
+  let fold_configuration_section' (v: _ #folder) =
+    handle' v#fold_configuration_section' v
+      ~fold:fold_configuration_section
+
   let fold_environment_division (v: _ #folder) =
     handle v#fold_environment_division
       ~continue:begin fun { env_configuration; env_input_output } x -> x
-        >> fold_option ~fold:fold_configuration_section v env_configuration
-        >> fold_option ~fold:fold_input_output_section v env_input_output
+        >> fold_option ~fold:fold_configuration_section' v env_configuration
+        >> fold_option ~fold:fold_input_output_section' v env_input_output
       end
 
   let fold_alphabet_specification (v: _ #folder) =
diff --git a/src/lsp/cobol_parser/grammar.mly b/src/lsp/cobol_parser/grammar.mly
index 347fac092..4ccb51fe9 100644
--- a/src/lsp/cobol_parser/grammar.mly
+++ b/src/lsp/cobol_parser/grammar.mly
@@ -291,7 +291,7 @@ program_definition_no_end:
  | id = bo(identification_division)                       (* COB85: mandatory *)
    pid = program_id_paragraph
    ipo = informational_paragraphs             (* Allowed in nested programs ? *)
-   opo = ro(options_paragraph)
+   opo = ro(loc(options_paragraph))
    edo = ro(loc(environment_division))
    ddo = ro(loc(data_division))
    pdo = ro(loc(program_procedure_division))
@@ -313,7 +313,7 @@ program_definition_no_end:
 program_prototype [@cost 999]:
  | bo(identification_division) (* Note: bo instead of ? to avoid conflict *)
    pid = program_prototype_id_paragraph
-   opo = ro(options_paragraph)
+   opo = ro(loc(options_paragraph))
    edo = ro(loc(environment_division))
    ddo = ro(loc(data_division))
    pdo = ro(loc(procedure_division))
@@ -331,7 +331,7 @@ program_prototype [@cost 999]:
 function_unit [@cost 999]:
  | ro(identification_division)
    fid = function_id_paragraph
-   opo = ro(options_paragraph)
+   opo = ro(loc(options_paragraph))
    edo = ro(loc(environment_division))
    ddo = ro(loc(data_division))
    pdo = ro(procedure_division)
@@ -349,7 +349,7 @@ function_unit [@cost 999]:
 class_definition [@cost 999]:
  | ro(identification_division)
    cid = class_id_paragraph
-   opo = ro(options_paragraph)
+   opo = ro(loc(options_paragraph))
    edo = ro(loc(environment_division))
    fdo = io(factory_definition) (* Note: inline to avoid conflict *)
    ido = ro(instance_definition)
@@ -370,7 +370,7 @@ class_definition [@cost 999]:
 factory_definition:
  | ro(identification_division)
    fp = factory_paragraph
-   opo = ro(options_paragraph)
+   opo = ro(loc(options_paragraph))
    edo = ro(loc(environment_division))
    ddo = ro(loc(data_division))
    pdo = ro(object_procedure_division)
@@ -384,7 +384,7 @@ factory_definition:
 instance_definition:
  | ro(identification_division)
    op = object_paragraph
-   opo = ro(options_paragraph)
+   opo = ro(loc(options_paragraph))
    edo = ro(loc(environment_division))
    ddo = ro(loc(data_division))
    pdo = ro(object_procedure_division)
@@ -398,7 +398,7 @@ instance_definition:
 interface_definition [@cost 999]:
  | ro(identification_division)
    iid = interface_id_paragraph
-   opo = ro(options_paragraph)
+   opo = ro(loc(options_paragraph))
    edo = ro(loc(environment_division))
    pdo = ro(object_procedure_division)
    END INTERFACE ei = name "."
@@ -416,7 +416,7 @@ interface_definition [@cost 999]:
 method_definition: (* Note: used in PROCEDURE DIVISION, see below *)
  | ro(identification_division)
    mid = method_id_paragraph
-   opo = ro(options_paragraph)
+   opo = ro(loc(options_paragraph))
    edo = ro(loc(environment_division))
    ddo = ro(loc(data_division))
    pdo = ro(procedure_division)
@@ -539,25 +539,24 @@ let intermediate_rounding_clause [@context intermediate_rounding_clause] :=
 
 let environment_division :=
  | ENVIRONMENT; DIVISION; ".";
-   c = ro(configuration_section);
-   io = ro(input_output_section);
-   { { env_configuration = c;
-       env_input_output = io; } }
+   env_configuration = ro(loc(configuration_section));
+   env_input_output  = ro(loc(input_output_section));
+   { { env_configuration; env_input_output } }
 
 
 
 (* ------------- ENVIRONMENT DIVISION / CONFIGURATION SECTION -------------- *)
 
-configuration_section:
- | CONFIGURATION SECTION "."
-   sco = ro(source_computer_paragraph)
-   oco = ro(object_computer_paragraph)
-   sno = ro(special_names_paragraph)
-   ro = ro(repository_paragraph)       (* +COB2002 *)
-    { { source_computer_paragraph = sco;
-        object_computer_paragraph = oco;
-        special_names_paragraph = sno;
-        repository_paragraph = ro; } }
+let configuration_section :=
+ | CONFIGURATION; SECTION; ".";
+   source_computer_paragraph = ro(loc(source_computer_paragraph));
+   object_computer_paragraph = ro(loc(object_computer_paragraph));
+   special_names_paragraph   = ro(loc(special_names_paragraph));
+   repository_paragraph      = ro(loc(repository_paragraph));     (* +COB2002 *)
+   { { source_computer_paragraph;
+       object_computer_paragraph;
+       special_names_paragraph;
+       repository_paragraph } }
 
 
 
@@ -785,10 +784,9 @@ let function_specifier [@context function_specifier] :=
 
 let input_output_section :=
  | INPUT_OUTPUT; SECTION; ".";
-   fco = ro(file_control_paragraph); (* COB85: mandatory *)
-   ioco = ro(io_control_paragraph);
-    { { file_control_paragraph = fco;
-        io_control_paragraph = ioco; } }
+   file_control_paragraph = ro(loc(file_control_paragraph)); (* COB85: mandatory *)
+   io_control_paragraph = ro(loc(io_control_paragraph));
+    { { file_control_paragraph; io_control_paragraph } }
 
 
 
@@ -998,26 +996,26 @@ type declaration entry =
 
 *)
 
-data_division:
- | DATA DIVISION "."
-   fso  = ro(file_section)
-   wsso = ro(working_storage_section)
-   lsso = ro(local_storage_section)   (* +COB2002 *)
-   lso  = ro(linkage_section)
-   cso  = ro(communication_section)    (* -COB2002 *)
-   rso  = ro(report_section)
-   sso  = ro(screen_section)           (* +COB2002 *)
-    { { file_section = fso;
-        working_storage_section = wsso;
-        local_storage_section = lsso;
-        linkage_section = lso;
-        communication_section = cso;
-        report_section = rso;
-        screen_section = sso; } }
+let data_division :=
+ | DATA; DIVISION; ".";
+   fso  = ro(file_section);
+   wsso = ro(working_storage_section);
+   lsso = ro(local_storage_section);                              (* +COB2002 *)
+   lso  = ro(linkage_section);
+   cso  = ro(communication_section);                              (* -COB2002 *)
+   rso  = ro(report_section);
+   sso  = ro(screen_section);                                     (* +COB2002 *)
+   { { file_section = fso;
+       working_storage_section = wsso;
+       local_storage_section = lsso;
+       linkage_section = lso;
+       communication_section = cso;
+       report_section = rso;
+       screen_section = sso; } }
 
 
 let section(K, L) ==
-  | K; SECTION; "."; ~ = rl(loc(L)); < >
+  | K; SECTION; "."; ~ = loc(rl(loc(L))); < >
 
 let file_section :=
   | ~ = section (FILE, file_or_sort_merge_descr_entry); < >
diff --git a/src/lsp/cobol_parser/grammar_printer.ml b/src/lsp/cobol_parser/grammar_printer.ml
index c23045638..51ce981af 100644
--- a/src/lsp/cobol_parser/grammar_printer.ml
+++ b/src/lsp/cobol_parser/grammar_printer.ml
@@ -1226,8 +1226,6 @@ let print_symbol = function
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_ro_with_test_) -> ""
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_ro_with_status_) -> ""
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_ro_step_phrase_) -> ""
-  | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_ro_special_names_paragraph_) -> ""
-  | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_ro_source_computer_paragraph_) -> ""
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_ro_signedness_) -> ""
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_ro_sign_) -> ""
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_ro_sharing_phrase_) -> ""
@@ -1235,7 +1233,6 @@ let print_symbol = function
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_ro_s_delimited_by_) -> ""
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_ro_returning_) -> ""
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_ro_retry_phrase_) -> ""
-  | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_ro_repository_paragraph_) -> ""
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_ro_report_section_) -> ""
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_ro_read_direction_) -> ""
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_ro_raising_exception_) -> ""
@@ -1273,33 +1270,36 @@ let print_symbol = function
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_ro_pf_BY_expression__) -> ""
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_ro_pf_AS_string_literal__) -> ""
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_ro_perform_phrase_) -> ""
-  | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_ro_options_paragraph_) -> ""
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_ro_object_reference_kind_) -> ""
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_ro_object_procedure_division_) -> ""
-  | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_ro_object_computer_paragraph_) -> ""
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_ro_name_) -> ""
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_ro_lock_or_retry_) -> ""
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_ro_locale_phrase_) -> ""
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_ro_local_storage_section_) -> ""
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_ro_loc_upon__) -> ""
+  | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_ro_loc_special_names_paragraph__) -> ""
+  | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_ro_loc_source_computer_paragraph__) -> ""
+  | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_ro_loc_repository_paragraph__) -> ""
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_ro_loc_program_procedure_division__) -> ""
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_ro_loc_procedure_division__) -> ""
+  | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_ro_loc_options_paragraph__) -> ""
+  | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_ro_loc_object_computer_paragraph__) -> ""
+  | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_ro_loc_io_control_paragraph__) -> ""
+  | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_ro_loc_input_output_section__) -> ""
+  | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_ro_loc_file_control_paragraph__) -> ""
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_ro_loc_environment_division__) -> ""
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_ro_loc_entry_name_clause__) -> ""
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_ro_loc_data_division__) -> ""
+  | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_ro_loc_configuration_section__) -> ""
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_ro_linkage_section_) -> ""
-  | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_ro_io_control_paragraph_) -> ""
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_ro_integer_) -> ""
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_ro_instance_definition_) -> ""
-  | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_ro_input_output_section_) -> ""
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_ro_identification_division_) -> ""
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_ro_file_section_) -> ""
-  | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_ro_file_control_paragraph_) -> ""
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_ro_expression_no_all_) -> ""
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_ro_expands_phrase_) -> ""
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_ro_endianness_mode_) -> ""
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_ro_depending_phrase_) -> ""
-  | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_ro_configuration_section_) -> ""
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_ro_communication_section_) -> ""
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_ro_collating_sequence_phrase_) -> ""
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_ro_close_format_) -> ""
@@ -1457,8 +1457,6 @@ let print_symbol = function
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_option_with_test_) -> "option_with_test_"
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_option_with_status_) -> "option_with_status_"
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_option_step_phrase_) -> "option_step_phrase_"
-  | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_option_special_names_paragraph_) -> "option_special_names_paragraph_"
-  | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_option_source_computer_paragraph_) -> "option_source_computer_paragraph_"
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_option_signedness_) -> "option_signedness_"
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_option_sign_) -> "option_sign_"
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_option_sharing_phrase_) -> "option_sharing_phrase_"
@@ -1466,7 +1464,6 @@ let print_symbol = function
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_option_s_delimited_by_) -> "option_s_delimited_by_"
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_option_returning_) -> "option_returning_"
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_option_retry_phrase_) -> "option_retry_phrase_"
-  | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_option_repository_paragraph_) -> "option_repository_paragraph_"
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_option_report_section_) -> "option_report_section_"
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_option_read_direction_) -> "option_read_direction_"
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_option_raising_exception_) -> "option_raising_exception_"
@@ -1509,22 +1506,29 @@ let print_symbol = function
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_option_or__LINE_LINES__) -> "option_or__LINE_LINES__"
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_option_or__IS_ARE__) -> "option_or__IS_ARE__"
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_option_or__AREA_AREAS__) -> "option_or__AREA_AREAS__"
-  | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_option_options_paragraph_) -> "option_options_paragraph_"
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_option_object_reference_kind_) -> "option_object_reference_kind_"
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_option_object_procedure_division_) -> "option_object_procedure_division_"
-  | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_option_object_computer_paragraph_) -> "option_object_computer_paragraph_"
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_option_name_) -> "option_name_"
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_option_mr___anonymous_0__) -> "option_mr___anonymous_0__"
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_option_lock_or_retry_) -> "option_lock_or_retry_"
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_option_locale_phrase_) -> "option_locale_phrase_"
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_option_local_storage_section_) -> "option_local_storage_section_"
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_option_loc_upon__) -> "option_loc_upon__"
+  | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_option_loc_special_names_paragraph__) -> "option_loc_special_names_paragraph__"
+  | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_option_loc_source_computer_paragraph__) -> "option_loc_source_computer_paragraph__"
+  | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_option_loc_repository_paragraph__) -> "option_loc_repository_paragraph__"
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_option_loc_program_procedure_division__) -> "option_loc_program_procedure_division__"
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_option_loc_program_definition_no_end__) -> "option_loc_program_definition_no_end__"
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_option_loc_procedure_division__) -> "option_loc_procedure_division__"
+  | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_option_loc_options_paragraph__) -> "option_loc_options_paragraph__"
+  | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_option_loc_object_computer_paragraph__) -> "option_loc_object_computer_paragraph__"
+  | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_option_loc_io_control_paragraph__) -> "option_loc_io_control_paragraph__"
+  | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_option_loc_input_output_section__) -> "option_loc_input_output_section__"
+  | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_option_loc_file_control_paragraph__) -> "option_loc_file_control_paragraph__"
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_option_loc_environment_division__) -> "option_loc_environment_division__"
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_option_loc_entry_name_clause__) -> "option_loc_entry_name_clause__"
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_option_loc_data_division__) -> "option_loc_data_division__"
+  | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_option_loc_configuration_section__) -> "option_loc_configuration_section__"
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_option_loc_SECURITY__) -> "option_loc_SECURITY__"
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_option_loc_INSTALLATION__) -> "option_loc_INSTALLATION__"
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_option_loc_DATE_WRITTEN__) -> "option_loc_DATE_WRITTEN__"
@@ -1532,14 +1536,11 @@ let print_symbol = function
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_option_loc_AUTHOR__) -> "option_loc_AUTHOR__"
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_option_linkage_section_) -> "option_linkage_section_"
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_option_limit_is__) -> "option_limit_is__"
-  | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_option_io_control_paragraph_) -> "option_io_control_paragraph_"
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_option_io_control_entry_) -> "option_io_control_entry_"
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_option_integer_) -> "option_integer_"
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_option_instance_definition_) -> "option_instance_definition_"
-  | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_option_input_output_section_) -> "option_input_output_section_"
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_option_identification_division_) -> "option_identification_division_"
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_option_file_section_) -> "option_file_section_"
-  | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_option_file_control_paragraph_) -> "option_file_control_paragraph_"
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_option_expression_no_all_) -> "option_expression_no_all_"
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_option_expands_phrase_) -> "option_expands_phrase_"
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_option_endianness_mode_) -> "option_endianness_mode_"
@@ -1548,7 +1549,6 @@ let print_symbol = function
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_option_default_display_clause_) -> "option_default_display_clause_"
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_option_default_accept_clause_) -> "option_default_accept_clause_"
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_option_control_division_) -> "option_control_division_"
-  | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_option_configuration_section_) -> "option_configuration_section_"
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_option_communication_section_) -> "option_communication_section_"
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_option_collating_sequence_phrase_) -> "option_collating_sequence_phrase_"
   | MenhirInterpreter.X (MenhirInterpreter.N MenhirInterpreter.N_option_close_format_) -> "option_close_format_"
@@ -3304,8 +3304,6 @@ let print_value (type a) : a MenhirInterpreter.symbol -> a -> string = function
   | MenhirInterpreter.N MenhirInterpreter.N_ro_with_test_ -> (fun _ -> "")
   | MenhirInterpreter.N MenhirInterpreter.N_ro_with_status_ -> (fun _ -> "")
   | MenhirInterpreter.N MenhirInterpreter.N_ro_step_phrase_ -> (fun _ -> "")
-  | MenhirInterpreter.N MenhirInterpreter.N_ro_special_names_paragraph_ -> (fun _ -> "")
-  | MenhirInterpreter.N MenhirInterpreter.N_ro_source_computer_paragraph_ -> (fun _ -> "")
   | MenhirInterpreter.N MenhirInterpreter.N_ro_signedness_ -> (fun _ -> "")
   | MenhirInterpreter.N MenhirInterpreter.N_ro_sign_ -> (fun _ -> "")
   | MenhirInterpreter.N MenhirInterpreter.N_ro_sharing_phrase_ -> (fun _ -> "")
@@ -3313,7 +3311,6 @@ let print_value (type a) : a MenhirInterpreter.symbol -> a -> string = function
   | MenhirInterpreter.N MenhirInterpreter.N_ro_s_delimited_by_ -> (fun _ -> "")
   | MenhirInterpreter.N MenhirInterpreter.N_ro_returning_ -> (fun _ -> "")
   | MenhirInterpreter.N MenhirInterpreter.N_ro_retry_phrase_ -> (fun _ -> "")
-  | MenhirInterpreter.N MenhirInterpreter.N_ro_repository_paragraph_ -> (fun _ -> "")
   | MenhirInterpreter.N MenhirInterpreter.N_ro_report_section_ -> (fun _ -> "")
   | MenhirInterpreter.N MenhirInterpreter.N_ro_read_direction_ -> (fun _ -> "")
   | MenhirInterpreter.N MenhirInterpreter.N_ro_raising_exception_ -> (fun _ -> "")
@@ -3351,33 +3348,36 @@ let print_value (type a) : a MenhirInterpreter.symbol -> a -> string = function
   | MenhirInterpreter.N MenhirInterpreter.N_ro_pf_BY_expression__ -> (fun _ -> "")
   | MenhirInterpreter.N MenhirInterpreter.N_ro_pf_AS_string_literal__ -> (fun _ -> "")
   | MenhirInterpreter.N MenhirInterpreter.N_ro_perform_phrase_ -> (fun _ -> "")
-  | MenhirInterpreter.N MenhirInterpreter.N_ro_options_paragraph_ -> (fun _ -> "")
   | MenhirInterpreter.N MenhirInterpreter.N_ro_object_reference_kind_ -> (fun _ -> "")
   | MenhirInterpreter.N MenhirInterpreter.N_ro_object_procedure_division_ -> (fun _ -> "")
-  | MenhirInterpreter.N MenhirInterpreter.N_ro_object_computer_paragraph_ -> (fun _ -> "")
   | MenhirInterpreter.N MenhirInterpreter.N_ro_name_ -> (fun _ -> "")
   | MenhirInterpreter.N MenhirInterpreter.N_ro_lock_or_retry_ -> (fun _ -> "")
   | MenhirInterpreter.N MenhirInterpreter.N_ro_locale_phrase_ -> (fun _ -> "")
   | MenhirInterpreter.N MenhirInterpreter.N_ro_local_storage_section_ -> (fun _ -> "")
   | MenhirInterpreter.N MenhirInterpreter.N_ro_loc_upon__ -> (fun _ -> "")
+  | MenhirInterpreter.N MenhirInterpreter.N_ro_loc_special_names_paragraph__ -> (fun _ -> "")
+  | MenhirInterpreter.N MenhirInterpreter.N_ro_loc_source_computer_paragraph__ -> (fun _ -> "")
+  | MenhirInterpreter.N MenhirInterpreter.N_ro_loc_repository_paragraph__ -> (fun _ -> "")
   | MenhirInterpreter.N MenhirInterpreter.N_ro_loc_program_procedure_division__ -> (fun _ -> "")
   | MenhirInterpreter.N MenhirInterpreter.N_ro_loc_procedure_division__ -> (fun _ -> "")
+  | MenhirInterpreter.N MenhirInterpreter.N_ro_loc_options_paragraph__ -> (fun _ -> "")
+  | MenhirInterpreter.N MenhirInterpreter.N_ro_loc_object_computer_paragraph__ -> (fun _ -> "")
+  | MenhirInterpreter.N MenhirInterpreter.N_ro_loc_io_control_paragraph__ -> (fun _ -> "")
+  | MenhirInterpreter.N MenhirInterpreter.N_ro_loc_input_output_section__ -> (fun _ -> "")
+  | MenhirInterpreter.N MenhirInterpreter.N_ro_loc_file_control_paragraph__ -> (fun _ -> "")
   | MenhirInterpreter.N MenhirInterpreter.N_ro_loc_environment_division__ -> (fun _ -> "")
   | MenhirInterpreter.N MenhirInterpreter.N_ro_loc_entry_name_clause__ -> (fun _ -> "")
   | MenhirInterpreter.N MenhirInterpreter.N_ro_loc_data_division__ -> (fun _ -> "")
+  | MenhirInterpreter.N MenhirInterpreter.N_ro_loc_configuration_section__ -> (fun _ -> "")
   | MenhirInterpreter.N MenhirInterpreter.N_ro_linkage_section_ -> (fun _ -> "")
-  | MenhirInterpreter.N MenhirInterpreter.N_ro_io_control_paragraph_ -> (fun _ -> "")
   | MenhirInterpreter.N MenhirInterpreter.N_ro_integer_ -> (fun _ -> "")
   | MenhirInterpreter.N MenhirInterpreter.N_ro_instance_definition_ -> (fun _ -> "")
-  | MenhirInterpreter.N MenhirInterpreter.N_ro_input_output_section_ -> (fun _ -> "")
   | MenhirInterpreter.N MenhirInterpreter.N_ro_identification_division_ -> (fun _ -> "")
   | MenhirInterpreter.N MenhirInterpreter.N_ro_file_section_ -> (fun _ -> "")
-  | MenhirInterpreter.N MenhirInterpreter.N_ro_file_control_paragraph_ -> (fun _ -> "")
   | MenhirInterpreter.N MenhirInterpreter.N_ro_expression_no_all_ -> (fun _ -> "")
   | MenhirInterpreter.N MenhirInterpreter.N_ro_expands_phrase_ -> (fun _ -> "")
   | MenhirInterpreter.N MenhirInterpreter.N_ro_endianness_mode_ -> (fun _ -> "")
   | MenhirInterpreter.N MenhirInterpreter.N_ro_depending_phrase_ -> (fun _ -> "")
-  | MenhirInterpreter.N MenhirInterpreter.N_ro_configuration_section_ -> (fun _ -> "")
   | MenhirInterpreter.N MenhirInterpreter.N_ro_communication_section_ -> (fun _ -> "")
   | MenhirInterpreter.N MenhirInterpreter.N_ro_collating_sequence_phrase_ -> (fun _ -> "")
   | MenhirInterpreter.N MenhirInterpreter.N_ro_close_format_ -> (fun _ -> "")
@@ -3535,8 +3535,6 @@ let print_value (type a) : a MenhirInterpreter.symbol -> a -> string = function
   | MenhirInterpreter.N MenhirInterpreter.N_option_with_test_ -> (fun _ -> "option_with_test_")
   | MenhirInterpreter.N MenhirInterpreter.N_option_with_status_ -> (fun _ -> "option_with_status_")
   | MenhirInterpreter.N MenhirInterpreter.N_option_step_phrase_ -> (fun _ -> "option_step_phrase_")
-  | MenhirInterpreter.N MenhirInterpreter.N_option_special_names_paragraph_ -> (fun _ -> "option_special_names_paragraph_")
-  | MenhirInterpreter.N MenhirInterpreter.N_option_source_computer_paragraph_ -> (fun _ -> "option_source_computer_paragraph_")
   | MenhirInterpreter.N MenhirInterpreter.N_option_signedness_ -> (fun _ -> "option_signedness_")
   | MenhirInterpreter.N MenhirInterpreter.N_option_sign_ -> (fun _ -> "option_sign_")
   | MenhirInterpreter.N MenhirInterpreter.N_option_sharing_phrase_ -> (fun _ -> "option_sharing_phrase_")
@@ -3544,7 +3542,6 @@ let print_value (type a) : a MenhirInterpreter.symbol -> a -> string = function
   | MenhirInterpreter.N MenhirInterpreter.N_option_s_delimited_by_ -> (fun _ -> "option_s_delimited_by_")
   | MenhirInterpreter.N MenhirInterpreter.N_option_returning_ -> (fun _ -> "option_returning_")
   | MenhirInterpreter.N MenhirInterpreter.N_option_retry_phrase_ -> (fun _ -> "option_retry_phrase_")
-  | MenhirInterpreter.N MenhirInterpreter.N_option_repository_paragraph_ -> (fun _ -> "option_repository_paragraph_")
   | MenhirInterpreter.N MenhirInterpreter.N_option_report_section_ -> (fun _ -> "option_report_section_")
   | MenhirInterpreter.N MenhirInterpreter.N_option_read_direction_ -> (fun _ -> "option_read_direction_")
   | MenhirInterpreter.N MenhirInterpreter.N_option_raising_exception_ -> (fun _ -> "option_raising_exception_")
@@ -3587,22 +3584,29 @@ let print_value (type a) : a MenhirInterpreter.symbol -> a -> string = function
   | MenhirInterpreter.N MenhirInterpreter.N_option_or__LINE_LINES__ -> (fun _ -> "option_or__LINE_LINES__")
   | MenhirInterpreter.N MenhirInterpreter.N_option_or__IS_ARE__ -> (fun _ -> "option_or__IS_ARE__")
   | MenhirInterpreter.N MenhirInterpreter.N_option_or__AREA_AREAS__ -> (fun _ -> "option_or__AREA_AREAS__")
-  | MenhirInterpreter.N MenhirInterpreter.N_option_options_paragraph_ -> (fun _ -> "option_options_paragraph_")
   | MenhirInterpreter.N MenhirInterpreter.N_option_object_reference_kind_ -> (fun _ -> "option_object_reference_kind_")
   | MenhirInterpreter.N MenhirInterpreter.N_option_object_procedure_division_ -> (fun _ -> "option_object_procedure_division_")
-  | MenhirInterpreter.N MenhirInterpreter.N_option_object_computer_paragraph_ -> (fun _ -> "option_object_computer_paragraph_")
   | MenhirInterpreter.N MenhirInterpreter.N_option_name_ -> (fun _ -> "option_name_")
   | MenhirInterpreter.N MenhirInterpreter.N_option_mr___anonymous_0__ -> (fun _ -> "option_mr___anonymous_0__")
   | MenhirInterpreter.N MenhirInterpreter.N_option_lock_or_retry_ -> (fun _ -> "option_lock_or_retry_")
   | MenhirInterpreter.N MenhirInterpreter.N_option_locale_phrase_ -> (fun _ -> "option_locale_phrase_")
   | MenhirInterpreter.N MenhirInterpreter.N_option_local_storage_section_ -> (fun _ -> "option_local_storage_section_")
   | MenhirInterpreter.N MenhirInterpreter.N_option_loc_upon__ -> (fun _ -> "option_loc_upon__")
+  | MenhirInterpreter.N MenhirInterpreter.N_option_loc_special_names_paragraph__ -> (fun _ -> "option_loc_special_names_paragraph__")
+  | MenhirInterpreter.N MenhirInterpreter.N_option_loc_source_computer_paragraph__ -> (fun _ -> "option_loc_source_computer_paragraph__")
+  | MenhirInterpreter.N MenhirInterpreter.N_option_loc_repository_paragraph__ -> (fun _ -> "option_loc_repository_paragraph__")
   | MenhirInterpreter.N MenhirInterpreter.N_option_loc_program_procedure_division__ -> (fun _ -> "option_loc_program_procedure_division__")
   | MenhirInterpreter.N MenhirInterpreter.N_option_loc_program_definition_no_end__ -> (fun _ -> "option_loc_program_definition_no_end__")
   | MenhirInterpreter.N MenhirInterpreter.N_option_loc_procedure_division__ -> (fun _ -> "option_loc_procedure_division__")
+  | MenhirInterpreter.N MenhirInterpreter.N_option_loc_options_paragraph__ -> (fun _ -> "option_loc_options_paragraph__")
+  | MenhirInterpreter.N MenhirInterpreter.N_option_loc_object_computer_paragraph__ -> (fun _ -> "option_loc_object_computer_paragraph__")
+  | MenhirInterpreter.N MenhirInterpreter.N_option_loc_io_control_paragraph__ -> (fun _ -> "option_loc_io_control_paragraph__")
+  | MenhirInterpreter.N MenhirInterpreter.N_option_loc_input_output_section__ -> (fun _ -> "option_loc_input_output_section__")
+  | MenhirInterpreter.N MenhirInterpreter.N_option_loc_file_control_paragraph__ -> (fun _ -> "option_loc_file_control_paragraph__")
   | MenhirInterpreter.N MenhirInterpreter.N_option_loc_environment_division__ -> (fun _ -> "option_loc_environment_division__")
   | MenhirInterpreter.N MenhirInterpreter.N_option_loc_entry_name_clause__ -> (fun _ -> "option_loc_entry_name_clause__")
   | MenhirInterpreter.N MenhirInterpreter.N_option_loc_data_division__ -> (fun _ -> "option_loc_data_division__")
+  | MenhirInterpreter.N MenhirInterpreter.N_option_loc_configuration_section__ -> (fun _ -> "option_loc_configuration_section__")
   | MenhirInterpreter.N MenhirInterpreter.N_option_loc_SECURITY__ -> (fun _ -> "option_loc_SECURITY__")
   | MenhirInterpreter.N MenhirInterpreter.N_option_loc_INSTALLATION__ -> (fun _ -> "option_loc_INSTALLATION__")
   | MenhirInterpreter.N MenhirInterpreter.N_option_loc_DATE_WRITTEN__ -> (fun _ -> "option_loc_DATE_WRITTEN__")
@@ -3610,14 +3614,11 @@ let print_value (type a) : a MenhirInterpreter.symbol -> a -> string = function
   | MenhirInterpreter.N MenhirInterpreter.N_option_loc_AUTHOR__ -> (fun _ -> "option_loc_AUTHOR__")
   | MenhirInterpreter.N MenhirInterpreter.N_option_linkage_section_ -> (fun _ -> "option_linkage_section_")
   | MenhirInterpreter.N MenhirInterpreter.N_option_limit_is__ -> (fun _ -> "option_limit_is__")
-  | MenhirInterpreter.N MenhirInterpreter.N_option_io_control_paragraph_ -> (fun _ -> "option_io_control_paragraph_")
   | MenhirInterpreter.N MenhirInterpreter.N_option_io_control_entry_ -> (fun _ -> "option_io_control_entry_")
   | MenhirInterpreter.N MenhirInterpreter.N_option_integer_ -> (fun _ -> "option_integer_")
   | MenhirInterpreter.N MenhirInterpreter.N_option_instance_definition_ -> (fun _ -> "option_instance_definition_")
-  | MenhirInterpreter.N MenhirInterpreter.N_option_input_output_section_ -> (fun _ -> "option_input_output_section_")
   | MenhirInterpreter.N MenhirInterpreter.N_option_identification_division_ -> (fun _ -> "option_identification_division_")
   | MenhirInterpreter.N MenhirInterpreter.N_option_file_section_ -> (fun _ -> "option_file_section_")
-  | MenhirInterpreter.N MenhirInterpreter.N_option_file_control_paragraph_ -> (fun _ -> "option_file_control_paragraph_")
   | MenhirInterpreter.N MenhirInterpreter.N_option_expression_no_all_ -> (fun _ -> "option_expression_no_all_")
   | MenhirInterpreter.N MenhirInterpreter.N_option_expands_phrase_ -> (fun _ -> "option_expands_phrase_")
   | MenhirInterpreter.N MenhirInterpreter.N_option_endianness_mode_ -> (fun _ -> "option_endianness_mode_")
@@ -3626,7 +3627,6 @@ let print_value (type a) : a MenhirInterpreter.symbol -> a -> string = function
   | MenhirInterpreter.N MenhirInterpreter.N_option_default_display_clause_ -> (fun _ -> "option_default_display_clause_")
   | MenhirInterpreter.N MenhirInterpreter.N_option_default_accept_clause_ -> (fun _ -> "option_default_accept_clause_")
   | MenhirInterpreter.N MenhirInterpreter.N_option_control_division_ -> (fun _ -> "option_control_division_")
-  | MenhirInterpreter.N MenhirInterpreter.N_option_configuration_section_ -> (fun _ -> "option_configuration_section_")
   | MenhirInterpreter.N MenhirInterpreter.N_option_communication_section_ -> (fun _ -> "option_communication_section_")
   | MenhirInterpreter.N MenhirInterpreter.N_option_collating_sequence_phrase_ -> (fun _ -> "option_collating_sequence_phrase_")
   | MenhirInterpreter.N MenhirInterpreter.N_option_close_format_ -> (fun _ -> "option_close_format_")
diff --git a/src/lsp/cobol_parser/grammar_recover.ml b/src/lsp/cobol_parser/grammar_recover.ml
index a49557781..68d1b10b8 100644
--- a/src/lsp/cobol_parser/grammar_recover.ml
+++ b/src/lsp/cobol_parser/grammar_recover.ml
@@ -1262,8 +1262,6 @@ module Default = struct
     | MenhirInterpreter.N MenhirInterpreter.N_ro_with_test_ -> None
     | MenhirInterpreter.N MenhirInterpreter.N_ro_with_status_ -> None
     | MenhirInterpreter.N MenhirInterpreter.N_ro_step_phrase_ -> None
-    | MenhirInterpreter.N MenhirInterpreter.N_ro_special_names_paragraph_ -> None
-    | MenhirInterpreter.N MenhirInterpreter.N_ro_source_computer_paragraph_ -> None
     | MenhirInterpreter.N MenhirInterpreter.N_ro_signedness_ -> None
     | MenhirInterpreter.N MenhirInterpreter.N_ro_sign_ -> None
     | MenhirInterpreter.N MenhirInterpreter.N_ro_sharing_phrase_ -> None
@@ -1271,7 +1269,6 @@ module Default = struct
     | MenhirInterpreter.N MenhirInterpreter.N_ro_s_delimited_by_ -> None
     | MenhirInterpreter.N MenhirInterpreter.N_ro_returning_ -> None
     | MenhirInterpreter.N MenhirInterpreter.N_ro_retry_phrase_ -> None
-    | MenhirInterpreter.N MenhirInterpreter.N_ro_repository_paragraph_ -> None
     | MenhirInterpreter.N MenhirInterpreter.N_ro_report_section_ -> None
     | MenhirInterpreter.N MenhirInterpreter.N_ro_read_direction_ -> None
     | MenhirInterpreter.N MenhirInterpreter.N_ro_raising_exception_ -> None
@@ -1309,33 +1306,36 @@ module Default = struct
     | MenhirInterpreter.N MenhirInterpreter.N_ro_pf_BY_expression__ -> None
     | MenhirInterpreter.N MenhirInterpreter.N_ro_pf_AS_string_literal__ -> None
     | MenhirInterpreter.N MenhirInterpreter.N_ro_perform_phrase_ -> None
-    | MenhirInterpreter.N MenhirInterpreter.N_ro_options_paragraph_ -> None
     | MenhirInterpreter.N MenhirInterpreter.N_ro_object_reference_kind_ -> None
     | MenhirInterpreter.N MenhirInterpreter.N_ro_object_procedure_division_ -> None
-    | MenhirInterpreter.N MenhirInterpreter.N_ro_object_computer_paragraph_ -> None
     | MenhirInterpreter.N MenhirInterpreter.N_ro_name_ -> None
     | MenhirInterpreter.N MenhirInterpreter.N_ro_lock_or_retry_ -> None
     | MenhirInterpreter.N MenhirInterpreter.N_ro_locale_phrase_ -> None
     | MenhirInterpreter.N MenhirInterpreter.N_ro_local_storage_section_ -> None
     | MenhirInterpreter.N MenhirInterpreter.N_ro_loc_upon__ -> None
+    | MenhirInterpreter.N MenhirInterpreter.N_ro_loc_special_names_paragraph__ -> None
+    | MenhirInterpreter.N MenhirInterpreter.N_ro_loc_source_computer_paragraph__ -> None
+    | MenhirInterpreter.N MenhirInterpreter.N_ro_loc_repository_paragraph__ -> None
     | MenhirInterpreter.N MenhirInterpreter.N_ro_loc_program_procedure_division__ -> None
     | MenhirInterpreter.N MenhirInterpreter.N_ro_loc_procedure_division__ -> None
+    | MenhirInterpreter.N MenhirInterpreter.N_ro_loc_options_paragraph__ -> None
+    | MenhirInterpreter.N MenhirInterpreter.N_ro_loc_object_computer_paragraph__ -> None
+    | MenhirInterpreter.N MenhirInterpreter.N_ro_loc_io_control_paragraph__ -> None
+    | MenhirInterpreter.N MenhirInterpreter.N_ro_loc_input_output_section__ -> None
+    | MenhirInterpreter.N MenhirInterpreter.N_ro_loc_file_control_paragraph__ -> None
     | MenhirInterpreter.N MenhirInterpreter.N_ro_loc_environment_division__ -> None
     | MenhirInterpreter.N MenhirInterpreter.N_ro_loc_entry_name_clause__ -> None
     | MenhirInterpreter.N MenhirInterpreter.N_ro_loc_data_division__ -> None
+    | MenhirInterpreter.N MenhirInterpreter.N_ro_loc_configuration_section__ -> None
     | MenhirInterpreter.N MenhirInterpreter.N_ro_linkage_section_ -> None
-    | MenhirInterpreter.N MenhirInterpreter.N_ro_io_control_paragraph_ -> None
     | MenhirInterpreter.N MenhirInterpreter.N_ro_integer_ -> None
     | MenhirInterpreter.N MenhirInterpreter.N_ro_instance_definition_ -> None
-    | MenhirInterpreter.N MenhirInterpreter.N_ro_input_output_section_ -> None
     | MenhirInterpreter.N MenhirInterpreter.N_ro_identification_division_ -> None
     | MenhirInterpreter.N MenhirInterpreter.N_ro_file_section_ -> None
-    | MenhirInterpreter.N MenhirInterpreter.N_ro_file_control_paragraph_ -> None
     | MenhirInterpreter.N MenhirInterpreter.N_ro_expression_no_all_ -> None
     | MenhirInterpreter.N MenhirInterpreter.N_ro_expands_phrase_ -> None
     | MenhirInterpreter.N MenhirInterpreter.N_ro_endianness_mode_ -> None
     | MenhirInterpreter.N MenhirInterpreter.N_ro_depending_phrase_ -> None
-    | MenhirInterpreter.N MenhirInterpreter.N_ro_configuration_section_ -> None
     | MenhirInterpreter.N MenhirInterpreter.N_ro_communication_section_ -> None
     | MenhirInterpreter.N MenhirInterpreter.N_ro_collating_sequence_phrase_ -> None
     | MenhirInterpreter.N MenhirInterpreter.N_ro_close_format_ -> None
@@ -1493,8 +1493,6 @@ module Default = struct
     | MenhirInterpreter.N MenhirInterpreter.N_option_with_test_ -> raise Not_found
     | MenhirInterpreter.N MenhirInterpreter.N_option_with_status_ -> raise Not_found
     | MenhirInterpreter.N MenhirInterpreter.N_option_step_phrase_ -> raise Not_found
-    | MenhirInterpreter.N MenhirInterpreter.N_option_special_names_paragraph_ -> raise Not_found
-    | MenhirInterpreter.N MenhirInterpreter.N_option_source_computer_paragraph_ -> raise Not_found
     | MenhirInterpreter.N MenhirInterpreter.N_option_signedness_ -> raise Not_found
     | MenhirInterpreter.N MenhirInterpreter.N_option_sign_ -> raise Not_found
     | MenhirInterpreter.N MenhirInterpreter.N_option_sharing_phrase_ -> raise Not_found
@@ -1502,7 +1500,6 @@ module Default = struct
     | MenhirInterpreter.N MenhirInterpreter.N_option_s_delimited_by_ -> raise Not_found
     | MenhirInterpreter.N MenhirInterpreter.N_option_returning_ -> raise Not_found
     | MenhirInterpreter.N MenhirInterpreter.N_option_retry_phrase_ -> raise Not_found
-    | MenhirInterpreter.N MenhirInterpreter.N_option_repository_paragraph_ -> raise Not_found
     | MenhirInterpreter.N MenhirInterpreter.N_option_report_section_ -> raise Not_found
     | MenhirInterpreter.N MenhirInterpreter.N_option_read_direction_ -> raise Not_found
     | MenhirInterpreter.N MenhirInterpreter.N_option_raising_exception_ -> raise Not_found
@@ -1545,22 +1542,29 @@ module Default = struct
     | MenhirInterpreter.N MenhirInterpreter.N_option_or__LINE_LINES__ -> raise Not_found
     | MenhirInterpreter.N MenhirInterpreter.N_option_or__IS_ARE__ -> raise Not_found
     | MenhirInterpreter.N MenhirInterpreter.N_option_or__AREA_AREAS__ -> raise Not_found
-    | MenhirInterpreter.N MenhirInterpreter.N_option_options_paragraph_ -> raise Not_found
     | MenhirInterpreter.N MenhirInterpreter.N_option_object_reference_kind_ -> raise Not_found
     | MenhirInterpreter.N MenhirInterpreter.N_option_object_procedure_division_ -> raise Not_found
-    | MenhirInterpreter.N MenhirInterpreter.N_option_object_computer_paragraph_ -> raise Not_found
     | MenhirInterpreter.N MenhirInterpreter.N_option_name_ -> raise Not_found
     | MenhirInterpreter.N MenhirInterpreter.N_option_mr___anonymous_0__ -> raise Not_found
     | MenhirInterpreter.N MenhirInterpreter.N_option_lock_or_retry_ -> raise Not_found
     | MenhirInterpreter.N MenhirInterpreter.N_option_locale_phrase_ -> raise Not_found
     | MenhirInterpreter.N MenhirInterpreter.N_option_local_storage_section_ -> raise Not_found
     | MenhirInterpreter.N MenhirInterpreter.N_option_loc_upon__ -> raise Not_found
+    | MenhirInterpreter.N MenhirInterpreter.N_option_loc_special_names_paragraph__ -> raise Not_found
+    | MenhirInterpreter.N MenhirInterpreter.N_option_loc_source_computer_paragraph__ -> raise Not_found
+    | MenhirInterpreter.N MenhirInterpreter.N_option_loc_repository_paragraph__ -> raise Not_found
     | MenhirInterpreter.N MenhirInterpreter.N_option_loc_program_procedure_division__ -> raise Not_found
     | MenhirInterpreter.N MenhirInterpreter.N_option_loc_program_definition_no_end__ -> raise Not_found
     | MenhirInterpreter.N MenhirInterpreter.N_option_loc_procedure_division__ -> raise Not_found
+    | MenhirInterpreter.N MenhirInterpreter.N_option_loc_options_paragraph__ -> raise Not_found
+    | MenhirInterpreter.N MenhirInterpreter.N_option_loc_object_computer_paragraph__ -> raise Not_found
+    | MenhirInterpreter.N MenhirInterpreter.N_option_loc_io_control_paragraph__ -> raise Not_found
+    | MenhirInterpreter.N MenhirInterpreter.N_option_loc_input_output_section__ -> raise Not_found
+    | MenhirInterpreter.N MenhirInterpreter.N_option_loc_file_control_paragraph__ -> raise Not_found
     | MenhirInterpreter.N MenhirInterpreter.N_option_loc_environment_division__ -> raise Not_found
     | MenhirInterpreter.N MenhirInterpreter.N_option_loc_entry_name_clause__ -> raise Not_found
     | MenhirInterpreter.N MenhirInterpreter.N_option_loc_data_division__ -> raise Not_found
+    | MenhirInterpreter.N MenhirInterpreter.N_option_loc_configuration_section__ -> raise Not_found
     | MenhirInterpreter.N MenhirInterpreter.N_option_loc_SECURITY__ -> raise Not_found
     | MenhirInterpreter.N MenhirInterpreter.N_option_loc_INSTALLATION__ -> raise Not_found
     | MenhirInterpreter.N MenhirInterpreter.N_option_loc_DATE_WRITTEN__ -> raise Not_found
@@ -1568,14 +1572,11 @@ module Default = struct
     | MenhirInterpreter.N MenhirInterpreter.N_option_loc_AUTHOR__ -> raise Not_found
     | MenhirInterpreter.N MenhirInterpreter.N_option_linkage_section_ -> raise Not_found
     | MenhirInterpreter.N MenhirInterpreter.N_option_limit_is__ -> raise Not_found
-    | MenhirInterpreter.N MenhirInterpreter.N_option_io_control_paragraph_ -> raise Not_found
     | MenhirInterpreter.N MenhirInterpreter.N_option_io_control_entry_ -> raise Not_found
     | MenhirInterpreter.N MenhirInterpreter.N_option_integer_ -> raise Not_found
     | MenhirInterpreter.N MenhirInterpreter.N_option_instance_definition_ -> raise Not_found
-    | MenhirInterpreter.N MenhirInterpreter.N_option_input_output_section_ -> raise Not_found
     | MenhirInterpreter.N MenhirInterpreter.N_option_identification_division_ -> raise Not_found
     | MenhirInterpreter.N MenhirInterpreter.N_option_file_section_ -> raise Not_found
-    | MenhirInterpreter.N MenhirInterpreter.N_option_file_control_paragraph_ -> raise Not_found
     | MenhirInterpreter.N MenhirInterpreter.N_option_expression_no_all_ -> raise Not_found
     | MenhirInterpreter.N MenhirInterpreter.N_option_expands_phrase_ -> raise Not_found
     | MenhirInterpreter.N MenhirInterpreter.N_option_endianness_mode_ -> raise Not_found
@@ -1584,7 +1585,6 @@ module Default = struct
     | MenhirInterpreter.N MenhirInterpreter.N_option_default_display_clause_ -> raise Not_found
     | MenhirInterpreter.N MenhirInterpreter.N_option_default_accept_clause_ -> raise Not_found
     | MenhirInterpreter.N MenhirInterpreter.N_option_control_division_ -> raise Not_found
-    | MenhirInterpreter.N MenhirInterpreter.N_option_configuration_section_ -> raise Not_found
     | MenhirInterpreter.N MenhirInterpreter.N_option_communication_section_ -> raise Not_found
     | MenhirInterpreter.N MenhirInterpreter.N_option_collating_sequence_phrase_ -> raise Not_found
     | MenhirInterpreter.N MenhirInterpreter.N_option_close_format_ -> raise Not_found
@@ -3220,10 +3220,10 @@ let can_pop (type a) : a terminal -> bool = function
 
 let recover =
   let r0 = [R 335] in
-  let r1 = R 1336 :: r0 in
+  let r1 = R 1334 :: r0 in
   let r2 = S (T T_PERIOD) :: r1 in
   let r3 = [R 396] in
-  let r4 = R 1397 :: r3 in
+  let r4 = R 1407 :: r3 in
   let r5 = [R 395] in
   let r6 = Sub (r4) :: r5 in
   let r7 = S (T T_PERIOD) :: r6 in
@@ -3237,7 +3237,7 @@ let recover =
   let r15 = Sub (r9) :: r14 in
   let r16 = [R 287] in
   let r17 = S (T T_EOF) :: r16 in
-  let r18 = R 1385 :: r17 in
+  let r18 = R 1389 :: r17 in
   let r19 = [R 664] in
   let r20 = S (T T_PERIOD) :: r19 in
   let r21 = [R 90] in
@@ -3256,7 +3256,7 @@ let recover =
   let r34 = S (N N_ro_procedure_division_) :: r33 in
   let r35 = S (N N_ro_loc_data_division__) :: r34 in
   let r36 = S (N N_ro_loc_environment_division__) :: r35 in
-  let r37 = S (N N_ro_options_paragraph_) :: r36 in
+  let r37 = S (N N_ro_loc_options_paragraph__) :: r36 in
   let r38 = [R 734] in
   let r39 = S (T T_PERIOD) :: r38 in
   let r40 = R 887 :: r39 in
@@ -3265,7 +3265,7 @@ let recover =
   let r43 = S (N N_name) :: r42 in
   let r44 = [R 2162] in
   let r45 = S (N N_figurative_constant) :: r44 in
-  let r46 = [R 1424] in
+  let r46 = [R 1430] in
   let r47 = [R 1131] in
   let r48 = S (T T_HIGH_VALUE) :: r47 in
   let r49 = [R 553] in
@@ -3331,14 +3331,14 @@ let recover =
   let r109 = Sub (r107) :: r108 in
   let r110 = [R 906] in
   let r111 = [R 479] in
-  let r112 = S (N N_ro_input_output_section_) :: r111 in
-  let r113 = S (N N_ro_configuration_section_) :: r112 in
+  let r112 = S (N N_ro_loc_input_output_section__) :: r111 in
+  let r113 = S (N N_ro_loc_configuration_section__) :: r112 in
   let r114 = S (T T_PERIOD) :: r113 in
   let r115 = [R 311] in
-  let r116 = S (N N_ro_repository_paragraph_) :: r115 in
-  let r117 = S (N N_ro_special_names_paragraph_) :: r116 in
-  let r118 = S (N N_ro_object_computer_paragraph_) :: r117 in
-  let r119 = S (N N_ro_source_computer_paragraph_) :: r118 in
+  let r116 = S (N N_ro_loc_repository_paragraph__) :: r115 in
+  let r117 = S (N N_ro_loc_special_names_paragraph__) :: r116 in
+  let r118 = S (N N_ro_loc_object_computer_paragraph__) :: r117 in
+  let r119 = S (N N_ro_loc_source_computer_paragraph__) :: r118 in
   let r120 = S (T T_PERIOD) :: r119 in
   let r121 = [R 2082] in
   let r122 = R 1248 :: r121 in
@@ -3392,7 +3392,7 @@ let recover =
   let r170 = S (N N_nel___anonymous_16_) :: r169 in
   let r171 = R 591 :: r170 in
   let r172 = [R 592] in
-  let r173 = [R 1436] in
+  let r173 = [R 1442] in
   let r174 = [R 732] in
   let r175 = S (N N_rnel_integer_) :: r174 in
   let r176 = [R 1003] in
@@ -3423,7 +3423,7 @@ let recover =
   let r201 = S (N N_ro_pf___anonymous_14_string_literal__) :: r200 in
   let r202 = Sub (r45) :: r201 in
   let r203 = R 1222 :: r202 in
-  let r204 = [R 1464] in
+  let r204 = [R 1470] in
   let r205 = Sub (r45) :: r204 in
   let r206 = S (T T_SYMBOL) :: r205 in
   let r207 = S (T T_PICTURE_STRING) :: r206 in
@@ -3439,7 +3439,7 @@ let recover =
   let r217 = [R 1001] in
   let r218 = [R 2174] in
   let r219 = S (N N_figurative_constant) :: r218 in
-  let r220 = [R 1452] in
+  let r220 = [R 1458] in
   let r221 = [R 2175] in
   let r222 = Sub (r52) :: r221 in
   let r223 = [R 220] in
@@ -3487,8 +3487,8 @@ let recover =
   let r265 = Sub (r22) :: r264 in
   let r266 = [R 1744] in
   let r267 = [R 720] in
-  let r268 = S (N N_ro_io_control_paragraph_) :: r267 in
-  let r269 = S (N N_ro_file_control_paragraph_) :: r268 in
+  let r268 = S (N N_ro_loc_io_control_paragraph__) :: r267 in
+  let r269 = S (N N_ro_loc_file_control_paragraph__) :: r268 in
   let r270 = S (T T_PERIOD) :: r269 in
   let r271 = [R 554] in
   let r272 = S (N N_rl_select_) :: r271 in
@@ -3504,7 +3504,7 @@ let recover =
   let r282 = [R 2056] in
   let r283 = [R 2055] in
   let r284 = [R 1751] in
-  let r285 = R 1409 :: r284 in
+  let r285 = R 1415 :: r284 in
   let r286 = [R 1651] in
   let r287 = S (N N_name) :: r286 in
   let r288 = R 1222 :: r287 in
@@ -3544,7 +3544,7 @@ let recover =
   let r322 = [R 91] in
   let r323 = S (N N_ro_pf_USING_name__) :: r322 in
   let r324 = S (N N_rnel_name_or_alphanum_) :: r323 in
-  let r325 = [R 1456] in
+  let r325 = [R 1462] in
   let r326 = [R 56] in
   let r327 = R 154 :: r326 in
   let r328 = R 899 :: r327 in
@@ -3570,13 +3570,13 @@ let recover =
   let r348 = [R 1141] in
   let r349 = [R 828] in
   let r350 = [R 745] in
-  let r351 = R 1358 :: r350 in
+  let r351 = R 1352 :: r350 in
   let r352 = [R 1750] in
   let r353 = S (N N_name) :: r352 in
   let r354 = [R 1745] in
   let r355 = Sub (r353) :: r354 in
   let r356 = R 1208 :: r355 in
-  let r357 = [R 1442] in
+  let r357 = [R 1448] in
   let r358 = [R 1746] in
   let r359 = S (N N_name) :: r358 in
   let r360 = R 1240 :: r359 in
@@ -3600,7 +3600,7 @@ let recover =
   let r378 = R 1200 :: r377 in
   let r379 = R 1274 :: r378 in
   let r380 = [R 1005] in
-  let r381 = [R 1444] in
+  let r381 = [R 1450] in
   let r382 = [R 798] in
   let r383 = [R 810] in
   let r384 = [R 1154] in
@@ -3621,7 +3621,7 @@ let recover =
   let r399 = S (N N_ro_procedure_division_) :: r398 in
   let r400 = S (N N_ro_loc_data_division__) :: r399 in
   let r401 = S (N N_ro_loc_environment_division__) :: r400 in
-  let r402 = S (N N_ro_options_paragraph_) :: r401 in
+  let r402 = S (N N_ro_loc_options_paragraph__) :: r401 in
   let r403 = [R 922] in
   let r404 = R 150 :: r403 in
   let r405 = R 134 :: r404 in
@@ -3680,7 +3680,7 @@ let recover =
   let r458 = [R 2413] in
   let r459 = [R 1009] in
   let r460 = S (N N_ro_pf_BY_expression__) :: r459 in
-  let r461 = [R 1430] in
+  let r461 = [R 1436] in
   let r462 = [R 526] in
   let r463 = [R 340] in
   let r464 = [R 99] in
@@ -3794,7 +3794,7 @@ let recover =
   let r572 = S (N N_ro_expression_no_all_) :: r571 in
   let r573 = [R 529] in
   let r574 = [R 530] in
-  let r575 = [R 1426] in
+  let r575 = [R 1432] in
   let r576 = [R 379] in
   let r577 = S (N N_literal) :: r576 in
   let r578 = [R 1013] in
@@ -3819,7 +3819,7 @@ let recover =
   let r597 = [R 2366] in
   let r598 = Sub (r596) :: r597 in
   let r599 = [R 2352] in
-  let r600 = [R 1487] in
+  let r600 = [R 1493] in
   let r601 = [R 2351] in
   let r602 = [R 2349] in
   let r603 = S (N N_ro_object_reference_kind_) :: r602 in
@@ -3854,7 +3854,7 @@ let recover =
   let r632 = [R 1595] in
   let r633 = R 160 :: r632 in
   let r634 = [R 161] in
-  let r635 = [R 1480] in
+  let r635 = [R 1486] in
   let r636 = S (T T_GET) :: r635 in
   let r637 = [R 1133] in
   let r638 = S (N N_expression) :: r637 in
@@ -3928,7 +3928,7 @@ let recover =
   let r706 = S (N N_integer) :: r705 in
   let r707 = R 1222 :: r706 in
   let r708 = S (T T_SIZE) :: r707 in
-  let r709 = [R 1485] in
+  let r709 = [R 1491] in
   let r710 = [R 1169] in
   let r711 = R 891 :: r710 in
   let r712 = S (N N_rl_key_is_) :: r711 in
@@ -3941,8 +3941,8 @@ let recover =
   let r719 = S (N N_ro_pf_FROM_integer__) :: r718 in
   let r720 = [R 201] in
   let r721 = S (N N_name) :: r720 in
-  let r722 = [R 1434] in
-  let r723 = [R 1454] in
+  let r722 = [R 1440] in
+  let r723 = [R 1460] in
   let r724 = [R 1609] in
   let r725 = S (N N_rnel_qualname_) :: r724 in
   let r726 = [R 748] in
@@ -3971,7 +3971,7 @@ let recover =
   let r749 = [R 433] in
   let r750 = S (N N_ro_pf___anonymous_43_integer__) :: r749 in
   let r751 = S (N N_ro_name_) :: r750 in
-  let r752 = [R 1478] in
+  let r752 = [R 1484] in
   let r753 = S (N N_integer) :: r752 in
   let r754 = [R 406] in
   let r755 = S (N N_idents) :: r754 in
@@ -4066,10 +4066,10 @@ let recover =
   let r844 = S (N N_ro_pf___anonymous_32_qualname_or_integer__) :: r843 in
   let r845 = Sub (r823) :: r844 in
   let r846 = S (T T_TOP) :: r845 in
-  let r847 = [R 1468] in
+  let r847 = [R 1474] in
   let r848 = Sub (r823) :: r847 in
   let r849 = S (T T_BOTTOM) :: r848 in
-  let r850 = [R 1466] in
+  let r850 = [R 1472] in
   let r851 = Sub (r823) :: r850 in
   let r852 = R 1190 :: r851 in
   let r853 = [R 792] in
@@ -4167,14 +4167,14 @@ let recover =
   let r945 = S (N N_ro_pf___anonymous_34_integer__) :: r944 in
   let r946 = S (N N_ro_pf___anonymous_33_integer__) :: r945 in
   let r947 = Sub (r941) :: r946 in
-  let r948 = [R 1364] in
-  let r949 = [R 1363] in
-  let r950 = [R 1470] in
+  let r948 = [R 1356] in
+  let r949 = [R 1355] in
+  let r950 = [R 1476] in
   let r951 = S (N N_integer) :: r950 in
-  let r952 = [R 1472] in
+  let r952 = [R 1478] in
   let r953 = S (N N_integer) :: r952 in
   let r954 = R 1222 :: r953 in
-  let r955 = [R 1474] in
+  let r955 = [R 1480] in
   let r956 = S (N N_integer) :: r955 in
   let r957 = R 1222 :: r956 in
   let r958 = [R 931] in
@@ -4182,7 +4182,7 @@ let recover =
   let r960 = S (N N_ro_pf___anonymous_38_integer__) :: r959 in
   let r961 = S (N N_ro_pf___anonymous_37_integer__) :: r960 in
   let r962 = S (N N_integer) :: r961 in
-  let r963 = [R 1476] in
+  let r963 = [R 1482] in
   let r964 = S (N N_integer) :: r963 in
   let r965 = [R 1551] in
   let r966 = [R 1550] in
@@ -4246,7 +4246,7 @@ let recover =
   let r1024 = [R 169] in
   let r1025 = [R 764] in
   let r1026 = [R 948] in
-  let r1027 = R 1412 :: r1026 in
+  let r1027 = R 1418 :: r1026 in
   let r1028 = [R 763] in
   let r1029 = [R 947] in
   let r1030 = [R 946] in
@@ -4447,7 +4447,7 @@ let recover =
   let r1225 = S (N N_ro_advancing_phrase_) :: r1224 in
   let r1226 = S (N N_ro_pf_FROM_ident_or_literal__) :: r1225 in
   let r1227 = [R 2454] in
-  let r1228 = [R 1432] in
+  let r1228 = [R 1438] in
   let r1229 = [R 42] in
   let r1230 = [R 1756] in
   let r1231 = [R 1755] in
@@ -4473,9 +4473,9 @@ let recover =
   let r1251 = Sub (r1244) :: r1250 in
   let r1252 = [R 2323] in
   let r1253 = S (N N_ro_pf___anonymous_101_ident__) :: r1252 in
-  let r1254 = [R 1460] in
+  let r1254 = [R 1466] in
   let r1255 = S (N N_ident) :: r1254 in
-  let r1256 = [R 1462] in
+  let r1256 = [R 1468] in
   let r1257 = S (N N_ident) :: r1256 in
   let r1258 = [R 2300] in
   let r1259 = S (N N_ident) :: r1258 in
@@ -4538,7 +4538,7 @@ let recover =
   let r1316 = S (N N_ro_pf_THROUGH_procedure_name__) :: r1315 in
   let r1317 = Sub (r1314) :: r1316 in
   let r1318 = R 1222 :: r1317 in
-  let r1319 = [R 1448] in
+  let r1319 = [R 1454] in
   let r1320 = [R 1544] in
   let r1321 = Sub (r57) :: r1320 in
   let r1322 = S (T T_GIVING) :: r1321 in
@@ -4665,7 +4665,7 @@ let recover =
   let r1443 = Sub (r1440) :: r1442 in
   let r1444 = S (N N_ro_pf_INTO_loc_ident___) :: r1443 in
   let r1445 = R 1256 :: r1444 in
-  let r1446 = [R 1440] in
+  let r1446 = [R 1446] in
   let r1447 = [R 1752] in
   let r1448 = S (T T_STATEMENT) :: r1447 in
   let r1449 = S (T T_NEXT) :: r1448 in
@@ -4685,11 +4685,11 @@ let recover =
   let r1463 = S (N N_ro_pf_INTO_ident__) :: r1462 in
   let r1464 = R 1256 :: r1463 in
   let r1465 = S (N N_ro_read_direction_) :: r1464 in
-  let r1466 = [R 1438] in
+  let r1466 = [R 1444] in
   let r1467 = [R 873] in
   let r1468 = [R 872] in
   let r1469 = S (T T_LOCK) :: r1468 in
-  let r1470 = [R 1483] in
+  let r1470 = [R 1489] in
   let r1471 = S (N N_qualname) :: r1470 in
   let r1472 = [R 1632] in
   let r1473 = [R 1611] in
@@ -4712,7 +4712,7 @@ let recover =
   let r1490 = S (N N_l_pf_AFTER_loc_varying_phrase___) :: r1489 in
   let r1491 = [R 754] in
   let r1492 = S (N N_l_pf_AFTER_loc_varying_phrase___) :: r1491 in
-  let r1493 = [R 1428] in
+  let r1493 = [R 1434] in
   let r1494 = [R 1564] in
   let r1495 = S (T T_END_PERFORM) :: r1494 in
   let r1496 = [R 1183] in
@@ -5048,7 +5048,7 @@ let recover =
   let r1826 = R 461 :: r1825 in
   let r1827 = S (N N_ro_pf_REMAINDER_ident__) :: r1826 in
   let r1828 = S (N N_rnel_rounded_ident_) :: r1827 in
-  let r1829 = [R 1446] in
+  let r1829 = [R 1452] in
   let r1830 = [R 426] in
   let r1831 = R 461 :: r1830 in
   let r1832 = [R 427] in
@@ -5078,7 +5078,7 @@ let recover =
   let r1856 = [R 990] in
   let r1857 = R 463 :: r1856 in
   let r1858 = [R 991] in
-  let r1859 = [R 1450] in
+  let r1859 = [R 1456] in
   let r1860 = S (T T_AFTER) :: r1229 in
   let r1861 = [R 2435] in
   let r1862 = Sub (r1860) :: r1861 in
@@ -5122,7 +5122,7 @@ let recover =
   let r1900 = [R 1997] in
   let r1901 = R 465 :: r1900 in
   let r1902 = Sub (r1899) :: r1901 in
-  let r1903 = [R 1458] in
+  let r1903 = [R 1464] in
   let r1904 = [R 2416] in
   let r1905 = [R 1998] in
   let r1906 = R 465 :: r1905 in
@@ -5214,7 +5214,7 @@ let recover =
   let r1992 = S (N N_ro_object_procedure_division_) :: r1991 in
   let r1993 = S (N N_ro_loc_data_division__) :: r1992 in
   let r1994 = S (N N_ro_loc_environment_division__) :: r1993 in
-  let r1995 = S (N N_ro_options_paragraph_) :: r1994 in
+  let r1995 = S (N N_ro_loc_options_paragraph__) :: r1994 in
   let r1996 = [R 1153] in
   let r1997 = R 883 :: r1996 in
   let r1998 = S (T T_PERIOD) :: r1997 in
@@ -5229,7 +5229,7 @@ let recover =
   let r2007 = S (N N_ro_object_procedure_division_) :: r2006 in
   let r2008 = S (N N_ro_loc_data_division__) :: r2007 in
   let r2009 = S (N N_ro_loc_environment_division__) :: r2008 in
-  let r2010 = S (N N_ro_options_paragraph_) :: r2009 in
+  let r2010 = S (N N_ro_loc_options_paragraph__) :: r2009 in
   let r2011 = [R 243] in
   let r2012 = S (T T_PERIOD) :: r2011 in
   let r2013 = S (N N_name) :: r2012 in
@@ -5250,16 +5250,16 @@ let recover =
   let r2028 = S (T T_PERIOD) :: r2027 in
   let r2029 = S (T T_PROGRAM_ID) :: r2028 in
   let r2030 = [R 679] in
-  let r2031 = R 1375 :: r2030 in
-  let r2032 = R 1369 :: r2031 in
-  let r2033 = R 1371 :: r2032 in
-  let r2034 = R 1373 :: r2033 in
-  let r2035 = R 1367 :: r2034 in
+  let r2031 = R 1367 :: r2030 in
+  let r2032 = R 1361 :: r2031 in
+  let r2033 = R 1363 :: r2032 in
+  let r2034 = R 1365 :: r2033 in
+  let r2035 = R 1359 :: r2034 in
   let r2036 = [R 1584] in
   let r2037 = S (N N_ro_loc_program_procedure_division__) :: r2036 in
   let r2038 = S (N N_ro_loc_data_division__) :: r2037 in
   let r2039 = S (N N_ro_loc_environment_division__) :: r2038 in
-  let r2040 = S (N N_ro_options_paragraph_) :: r2039 in
+  let r2040 = S (N N_ro_loc_options_paragraph__) :: r2039 in
   let r2041 = Sub (r2035) :: r2040 in
   let r2042 = Sub (r2029) :: r2041 in
   let r2043 = [R 1586] in
@@ -6106,78 +6106,78 @@ let recover =
   | 3138 -> One ([R 1323])
   | 2524 -> One ([R 1325])
   | 2182 -> One ([R 1327])
-  | 704 -> One ([R 1329])
-  | 4041 -> One ([R 1331])
-  | 23 -> One ([R 1333])
-  | 14 -> One (R 1334 :: r13)
-  | 20 -> One ([R 1335])
-  | 25 -> One ([R 1337])
-  | 765 -> One ([R 1339])
-  | 1147 -> One ([R 1341])
-  | 451 -> One ([R 1343])
-  | 904 -> One ([R 1345])
-  | 699 -> One ([R 1347])
-  | 2189 -> One ([R 1349])
-  | 3879 -> One ([R 1351])
-  | 702 -> One ([R 1353])
-  | 3935 -> One ([R 1355])
-  | 2363 -> One ([R 1357])
-  | 694 -> One ([R 1359])
-  | 697 -> One ([R 1361])
-  | 1805 -> One (R 1362 :: r947)
-  | 2184 -> One ([R 1366])
-  | 3963 -> One ([R 1368])
-  | 3969 -> One ([R 1370])
-  | 3967 -> One ([R 1372])
-  | 3965 -> One ([R 1374])
-  | 3971 -> One ([R 1376])
-  | 3870 -> One ([R 1378])
-  | 1553 -> One ([R 1380])
-  | 3872 -> One ([R 1382])
-  | 4039 -> One ([R 1384])
-  | 3944 -> One ([R 1386])
-  | 4007 -> One ([R 1388])
-  | 3429 -> One ([R 1390])
-  | 2186 -> One ([R 1392])
-  | 258 -> One ([R 1394])
-  | 3558 -> One ([R 1396])
-  | 21 -> One ([R 1398])
-  | 232 -> One ([R 1400])
-  | 476 -> One ([R 1402])
-  | 3887 -> One ([R 1404])
-  | 1123 -> One ([R 1406])
-  | 3873 -> One ([R 1408])
-  | 501 -> One ([R 1410])
-  | 500 -> One ([R 1411])
-  | 287 -> One (R 1412 :: r177)
-  | 2044 -> One (R 1412 :: r1057)
-  | 288 -> One ([R 1413])
-  | 289 -> One ([R 1414])
-  | 1847 -> One ([R 1416])
-  | 1844 -> One ([R 1417])
-  | 1982 -> One (R 1418 :: r1036)
-  | 1987 -> One (R 1418 :: r1038)
-  | 1984 -> One ([R 1419])
-  | 1983 -> One ([R 1420])
-  | 3533 -> One ([R 1422])
-  | 1209 -> One ([R 1481])
-  | 1370 -> One (R 1484 :: r708)
-  | 1379 -> One ([R 1489])
-  | 3867 -> One ([R 1491])
-  | 3011 -> One ([R 1493])
-  | 3560 -> One ([R 1495])
-  | 2179 -> One ([R 1497])
-  | 472 -> One ([R 1499])
-  | 2801 -> One ([R 1501])
-  | 2849 -> One ([R 1503])
-  | 3723 -> One ([R 1505])
-  | 2176 -> One ([R 1507])
-  | 2785 -> One ([R 1509])
-  | 2591 -> One ([R 1511])
-  | 1169 -> One ([R 1513])
-  | 1168 -> One ([R 1514])
-  | 191 -> One ([R 1516])
-  | 432 -> One ([R 1518])
+  | 4041 -> One ([R 1329])
+  | 23 -> One ([R 1331])
+  | 14 -> One (R 1332 :: r13)
+  | 20 -> One ([R 1333])
+  | 25 -> One ([R 1335])
+  | 765 -> One ([R 1337])
+  | 1147 -> One ([R 1339])
+  | 451 -> One ([R 1341])
+  | 904 -> One ([R 1343])
+  | 2189 -> One ([R 1345])
+  | 3879 -> One ([R 1347])
+  | 3935 -> One ([R 1349])
+  | 2363 -> One ([R 1351])
+  | 694 -> One ([R 1353])
+  | 1805 -> One (R 1354 :: r947)
+  | 2184 -> One ([R 1358])
+  | 3963 -> One ([R 1360])
+  | 3969 -> One ([R 1362])
+  | 3967 -> One ([R 1364])
+  | 3965 -> One ([R 1366])
+  | 3971 -> One ([R 1368])
+  | 704 -> One ([R 1370])
+  | 3870 -> One ([R 1372])
+  | 1553 -> One ([R 1374])
+  | 3872 -> One ([R 1376])
+  | 699 -> One ([R 1378])
+  | 702 -> One ([R 1380])
+  | 697 -> One ([R 1382])
+  | 476 -> One ([R 1384])
+  | 3873 -> One ([R 1386])
+  | 4039 -> One ([R 1388])
+  | 3944 -> One ([R 1390])
+  | 4007 -> One ([R 1392])
+  | 472 -> One ([R 1394])
+  | 191 -> One ([R 1396])
+  | 432 -> One ([R 1398])
+  | 3429 -> One ([R 1400])
+  | 2186 -> One ([R 1402])
+  | 258 -> One ([R 1404])
+  | 3558 -> One ([R 1406])
+  | 21 -> One ([R 1408])
+  | 232 -> One ([R 1410])
+  | 3887 -> One ([R 1412])
+  | 1123 -> One ([R 1414])
+  | 501 -> One ([R 1416])
+  | 500 -> One ([R 1417])
+  | 287 -> One (R 1418 :: r177)
+  | 2044 -> One (R 1418 :: r1057)
+  | 288 -> One ([R 1419])
+  | 289 -> One ([R 1420])
+  | 1847 -> One ([R 1422])
+  | 1844 -> One ([R 1423])
+  | 1982 -> One (R 1424 :: r1036)
+  | 1987 -> One (R 1424 :: r1038)
+  | 1984 -> One ([R 1425])
+  | 1983 -> One ([R 1426])
+  | 3533 -> One ([R 1428])
+  | 1209 -> One ([R 1487])
+  | 1370 -> One (R 1490 :: r708)
+  | 1379 -> One ([R 1495])
+  | 3867 -> One ([R 1497])
+  | 3011 -> One ([R 1499])
+  | 3560 -> One ([R 1501])
+  | 2179 -> One ([R 1503])
+  | 2801 -> One ([R 1505])
+  | 2849 -> One ([R 1507])
+  | 3723 -> One ([R 1509])
+  | 2176 -> One ([R 1511])
+  | 2785 -> One ([R 1513])
+  | 2591 -> One ([R 1515])
+  | 1169 -> One ([R 1517])
+  | 1168 -> One ([R 1518])
   | 1944 -> One ([R 1520])
   | 2478 -> One ([R 1522])
   | 2753 -> One ([R 1524])
@@ -6365,80 +6365,80 @@ let recover =
   | 3133 -> One ([R 1851])
   | 2512 -> One ([R 1852])
   | 2181 -> One ([R 1853])
-  | 703 -> One ([R 1854])
-  | 764 -> One ([R 1855])
-  | 1145 -> One ([R 1856])
-  | 450 -> One ([R 1857])
-  | 903 -> One ([R 1858])
-  | 698 -> One ([R 1859])
-  | 2188 -> One ([R 1860])
-  | 3876 -> One ([R 1861])
-  | 701 -> One ([R 1862])
-  | 3934 -> One ([R 1863])
-  | 2362 -> One ([R 1864])
-  | 696 -> One ([R 1865])
-  | 2183 -> One ([R 1866])
-  | 3869 -> One ([R 1867])
-  | 1545 -> One ([R 1868])
-  | 3871 -> One ([R 1869])
-  | 4040 -> One ([R 1870])
-  | 4008 -> One ([R 1871])
-  | 3434 -> One ([R 1872])
-  | 2185 -> One ([R 1873])
-  | 257 -> One ([R 1874])
-  | 3557 -> One ([R 1875])
-  | 231 -> One ([R 1876])
-  | 475 -> One ([R 1877])
-  | 3886 -> One ([R 1878])
-  | 1122 -> One ([R 1879])
-  | 3874 -> One ([R 1880])
-  | 3534 -> One ([R 1881])
-  | 75 -> One ([R 1882])
-  | 1061 -> One ([R 1883])
-  | 2773 -> One ([R 1884])
-  | 1062 -> One ([R 1885])
-  | 2713 -> One ([R 1886])
-  | 1418 -> One ([R 1887])
-  | 286 -> One ([R 1888])
-  | 3559 -> One ([R 1889])
-  | 3577 -> One ([R 1890])
-  | 656 -> One ([R 1891])
-  | 683 -> One ([R 1892])
-  | 3463 -> One ([R 1893])
-  | 2502 -> One ([R 1894])
-  | 3532 -> One ([R 1895])
-  | 363 -> One ([R 1896])
-  | 1417 -> One ([R 1897])
-  | 568 -> One ([R 1898])
-  | 3639 -> One ([R 1899])
-  | 2423 -> One ([R 1900])
-  | 2422 -> One ([R 1901])
-  | 334 -> One ([R 1902])
-  | 1663 -> One ([R 1903])
-  | 1652 -> One ([R 1904])
-  | 1842 -> One ([R 1905])
-  | 1841 -> One ([R 1906])
-  | 1838 -> One ([R 1907])
-  | 1837 -> One ([R 1908])
-  | 1457 -> One ([R 1909])
-  | 1206 -> One ([R 1910])
-  | 3555 -> One ([R 1911])
-  | 1111 -> One ([R 1912])
-  | 1380 -> One ([R 1913])
-  | 3868 -> One ([R 1914])
-  | 3012 -> One ([R 1915])
-  | 3561 -> One ([R 1916])
-  | 2180 -> One ([R 1917])
-  | 473 -> One ([R 1918])
-  | 2802 -> One ([R 1919])
-  | 2850 -> One ([R 1920])
-  | 3725 -> One ([R 1921])
-  | 2178 -> One ([R 1922])
-  | 2803 -> One ([R 1923])
-  | 2593 -> One ([R 1924])
-  | 1172 -> One ([R 1925])
-  | 477 -> One ([R 1926])
-  | 474 -> One ([R 1927])
+  | 764 -> One ([R 1854])
+  | 1145 -> One ([R 1855])
+  | 450 -> One ([R 1856])
+  | 903 -> One ([R 1857])
+  | 2188 -> One ([R 1858])
+  | 3876 -> One ([R 1859])
+  | 3934 -> One ([R 1860])
+  | 2362 -> One ([R 1861])
+  | 2183 -> One ([R 1862])
+  | 703 -> One ([R 1863])
+  | 3869 -> One ([R 1864])
+  | 1545 -> One ([R 1865])
+  | 3871 -> One ([R 1866])
+  | 698 -> One ([R 1867])
+  | 701 -> One ([R 1868])
+  | 696 -> One ([R 1869])
+  | 475 -> One ([R 1870])
+  | 3874 -> One ([R 1871])
+  | 4040 -> One ([R 1872])
+  | 4008 -> One ([R 1873])
+  | 473 -> One ([R 1874])
+  | 477 -> One ([R 1875])
+  | 474 -> One ([R 1876])
+  | 3434 -> One ([R 1877])
+  | 2185 -> One ([R 1878])
+  | 257 -> One ([R 1879])
+  | 3557 -> One ([R 1880])
+  | 231 -> One ([R 1881])
+  | 3886 -> One ([R 1882])
+  | 1122 -> One ([R 1883])
+  | 3534 -> One ([R 1884])
+  | 75 -> One ([R 1885])
+  | 1061 -> One ([R 1886])
+  | 2773 -> One ([R 1887])
+  | 1062 -> One ([R 1888])
+  | 2713 -> One ([R 1889])
+  | 1418 -> One ([R 1890])
+  | 286 -> One ([R 1891])
+  | 3559 -> One ([R 1892])
+  | 3577 -> One ([R 1893])
+  | 656 -> One ([R 1894])
+  | 683 -> One ([R 1895])
+  | 3463 -> One ([R 1896])
+  | 2502 -> One ([R 1897])
+  | 3532 -> One ([R 1898])
+  | 363 -> One ([R 1899])
+  | 1417 -> One ([R 1900])
+  | 568 -> One ([R 1901])
+  | 3639 -> One ([R 1902])
+  | 2423 -> One ([R 1903])
+  | 2422 -> One ([R 1904])
+  | 334 -> One ([R 1905])
+  | 1663 -> One ([R 1906])
+  | 1652 -> One ([R 1907])
+  | 1842 -> One ([R 1908])
+  | 1841 -> One ([R 1909])
+  | 1838 -> One ([R 1910])
+  | 1837 -> One ([R 1911])
+  | 1457 -> One ([R 1912])
+  | 1206 -> One ([R 1913])
+  | 3555 -> One ([R 1914])
+  | 1111 -> One ([R 1915])
+  | 1380 -> One ([R 1916])
+  | 3868 -> One ([R 1917])
+  | 3012 -> One ([R 1918])
+  | 3561 -> One ([R 1919])
+  | 2180 -> One ([R 1920])
+  | 2802 -> One ([R 1921])
+  | 2850 -> One ([R 1922])
+  | 3725 -> One ([R 1923])
+  | 2178 -> One ([R 1924])
+  | 2803 -> One ([R 1925])
+  | 2593 -> One ([R 1926])
+  | 1172 -> One ([R 1927])
   | 1946 -> One ([R 1928])
   | 2480 -> One ([R 1929])
   | 3526 -> One ([R 1930])
@@ -6947,10 +6947,10 @@ let recover =
   | 678 -> One (S (N N_ro_pf_POSITION_integer__) :: r380)
   | 634 -> One (S (N N_ro_pf_ON_name__) :: r356)
   | 794 -> One (S (N N_ro_pf_FROM_expression__) :: r460)
-  | 113 -> One (S (N N_ro_options_paragraph_) :: r80)
-  | 3897 -> One (S (N N_ro_options_paragraph_) :: r1983)
-  | 4030 -> One (S (N N_ro_options_paragraph_) :: r2073)
   | 3428 -> One (S (N N_ro_loc_upon__) :: r1820)
+  | 113 -> One (S (N N_ro_loc_options_paragraph__) :: r80)
+  | 3897 -> One (S (N N_ro_loc_options_paragraph__) :: r1983)
+  | 4030 -> One (S (N N_ro_loc_options_paragraph__) :: r2073)
   | 789 -> One (S (N N_ro_loc_entry_name_clause__) :: r457)
   | 1867 -> One (S (N N_ro_loc_entry_name_clause__) :: r977)
   | 2078 -> One (S (N N_ro_loc_entry_name_clause__) :: r1068)
diff --git a/src/lsp/cobol_typeck/cobol_typeck.ml b/src/lsp/cobol_typeck/cobol_typeck.ml
index 600fa77b8..0a7d9c87d 100644
--- a/src/lsp/cobol_typeck/cobol_typeck.ml
+++ b/src/lsp/cobol_typeck/cobol_typeck.ml
@@ -307,7 +307,7 @@ struct
             Visitor.do_children_and_then acc (fun (_, progs) -> parents, progs)
 
       (* skip some divisions *)
-      method! fold_environment_division _ = Visitor.skip
+      method! fold_environment_division' _ = Visitor.skip
       method! fold_data_division' _ = Visitor.skip
       method! fold_procedure_division' _ = Visitor.skip
     end in

From 953b351b98bd437048dd7458ed211f20840eb4af Mon Sep 17 00:00:00 2001
From: Nicolas Berthier <nicolas.berthier@ocamlpro.com>
Date: Tue, 26 Sep 2023 11:48:07 +0200
Subject: [PATCH 15/17] Refactor code for LSP folding-range requests

---
 src/lsp/cobol_lsp/lsp_folding.ml | 203 ++++++++++++++++---------------
 src/lsp/cobol_lsp/lsp_request.ml |   7 +-
 2 files changed, 108 insertions(+), 102 deletions(-)

diff --git a/src/lsp/cobol_lsp/lsp_folding.ml b/src/lsp/cobol_lsp/lsp_folding.ml
index 5759e7606..6f6fb5e4d 100644
--- a/src/lsp/cobol_lsp/lsp_folding.ml
+++ b/src/lsp/cobol_lsp/lsp_folding.ml
@@ -8,113 +8,126 @@
 (*                                                                            *)
 (******************************************************************************)
 
-open Cobol_common
+open Lsp.Types
+
+open Cobol_common                                                  (* Visitor *)
 open Cobol_common.Srcloc.INFIX
 
-type folding_range = {
-  startLine:int;
-  endLine:int;
-  startCharacter:int; (*not really used *)
-  endCharacter:int;   (*not really used *)
-  (* kind:Lsp.Types.FoldingRangeKind.t option *)
-  (* collapsedText:string option*)
-}
-
-let folding_range_of_loc loc =
-  match Srcloc.as_lexloc loc with
-  | (* None -> None *)
-  (* | Some *) (p1, p2) ->
-      Some {
-        startLine = p1.pos_lnum - 1;
-        startCharacter = p1.pos_cnum - p1.pos_bol;
-        endLine = p2.pos_lnum - 1;
-        endCharacter = p2.pos_cnum - p2.pos_bol
+type range = FoldingRange.t
+
+let range_of_loc_in ~filename ?kind loc =
+  try
+    let p1, p2 = Srcloc.lexloc_in ~filename loc in
+    Option.some @@ FoldingRange.create ()
+      ~startLine:(p1.pos_lnum - 1)
+      ~startCharacter:(p1.pos_cnum - p1.pos_bol)
+      ~endLine:(p2.pos_lnum - 1)
+      ~endCharacter:(p2.pos_cnum - p2.pos_bol)
+      ?kind
+  with Invalid_argument _ ->
+    (* Filename did not take part in the construction of loc.  This may happen
+       on dummy locations inserted during recovery. *)
+    Option.none
+
+let acc_range = function
+  | None -> Fun.id
+  | Some r -> List.cons r
+
+let extend_range (range: range option as 's) (new_range: 's) =
+  match range, new_range with
+  | None, _ | _, None ->
+      None
+  | Some range, Some new_range ->
+      Some { range with
+             endLine = new_range.endLine;
+             endCharacter = new_range.endCharacter }
+
+let acc_ranges_in ~filename ptree acc =
+  let open struct
+    type acc =
+      {
+        section_range: range option;
+        ranges: range list;
       }
+  end in
 
-let add_folding_range r l =
-  match r with
-  | None -> l
-  | Some r -> r :: l
-
-let add_folding_range_of_loc loc l =
-  add_folding_range (folding_range_of_loc loc) l
-
-(*Define the folding_range of program/division/statement...
-  We do not need to do any analyze here.
-  However, we need to refine the code of parser/visitor first.*)
-let folding_range_simple ast =
-  let add_node n acc =
-    Visitor.do_children @@ add_folding_range_of_loc ~@n acc
+  let register_range ?kind { loc; _ } acc =
+    let range = range_of_loc_in ~filename ?kind loc in
+    { acc with ranges = acc_range range acc.ranges }
   in
-  let visitor = Cobol_parser.PTree_visitor.fold_compilation_group (object
-    inherit [folding_range list] Cobol_parser.PTree_visitor.folder
 
-    method! fold_program_unit' = add_node
-    method! fold_data_division' = add_node
-    method! fold_procedure_division' = add_node
-    method! fold_statement' = add_node
-
-    (*TODO:
-      - add location for some nodes in the ast
-        so that we can define folding_range for
-        environment division, file section... (predefined section)
+  let with_subranges ?kind n acc =
+    Visitor.do_children @@ register_range ?kind n acc
+  and leaf_range ?kind n acc =
+    Visitor.skip_children @@ register_range ?kind n acc
+  in
 
-      - it is possible to add folding_range for
+  let wide_region n = with_subranges ~kind:FoldingRangeKind.Region n
+  and leaf_region n = leaf_range     ~kind:FoldingRangeKind.Region n in
+
+  let { section_range; ranges } =
+    Cobol_parser.PTree_visitor.fold_compilation_group (object
+      inherit [acc] Cobol_parser.PTree_visitor.folder
+
+      method! fold_compilation_unit' = wide_region
+      method! fold_options_paragraph' = leaf_region
+
+      method! fold_data_division' = wide_region
+      method! fold_file_section' = wide_region
+      method! fold_working_storage_section' = wide_region
+      method! fold_linkage_section' = wide_region
+      method! fold_communication_section' = wide_region
+      method! fold_local_storage_section' = wide_region
+      method! fold_report_section' = wide_region
+      method! fold_screen_section' = wide_region
+
+      method! fold_environment_division' = wide_region
+      method! fold_configuration_section' = wide_region
+      (* method! fold_source_computer_paragraph' = region *)
+      (* method! fold_object_computer_paragraph' = region *)
+      (* method! fold_special_names_paragraph' = region *)
+      method! fold_repository_paragraph' = leaf_region
+      method! fold_input_output_section' = leaf_region
+      method! fold_file_control_paragraph' = leaf_region
+      method! fold_io_control_paragraph' = leaf_region
+
+      method! fold_procedure_division' = wide_region
+      method! fold_statement' = wide_region
+
+      (*TODO:
+        - add location for some nodes in the ast
+          so that we can define folding_range for
+          environment division, file section... (predefined section)
+
+        - it is possible to add folding_range for
         - branch of statement(else_branch, evaluate_branch...)
         - handler(on_size_error)
         - inline_call
 
-      - add folding_range for other type of compilation_unit (not program) *)
-
-  end) in
-  visitor ast []
+        - add folding_range for other type of compilation_unit (not program) *)
 
+      method! fold_paragraph' {payload = { paragraph_is_section; _ }; loc} acc =
+        let range = range_of_loc_in ~filename loc in
+        Visitor.skip_children @@
+        if paragraph_is_section
+        then { section_range = range;
+               ranges = acc_range acc.section_range acc.ranges }
+        else { section_range = extend_range acc.section_range range;
+               ranges = acc_range range acc.ranges }
 
-let folding_range_paragraph ast =
-  let update_section_range loc (section_range, l) =
-    match folding_range_of_loc loc with
-    | None -> section_range, l
-    | Some ({endLine; endCharacter; _} as r) ->
-        Option.map (
-          fun folding_range->
-            {folding_range with endLine; endCharacter}
-        ) section_range, r :: l
+    end) ptree { section_range = None; ranges = acc }
   in
 
-  let add_section (r, l) = add_folding_range r l in
-
-  let visitor = Cobol_parser.PTree_visitor.fold_compilation_group (object
-    inherit [folding_range option *
-             folding_range list] Cobol_parser.PTree_visitor.folder
-
-    method! fold_paragraph' {payload = {paragraph_is_section; _}; loc} acc =
-      Visitor.skip_children @@
-        if not paragraph_is_section then
-          update_section_range loc acc
-        else
-          folding_range_of_loc loc,
-          add_section acc
-
-    end) in
-  add_section @@ visitor ast (None, [])
+  acc_range section_range ranges
 
 
 (*TODO:
   Now we use the type Group.t (need to be rewritten),
   which does not work for renames-item, condition-item ... *)
-let folding_range_data ({ cu_wss; _ }:Cobol_data.Types.compilation_unit) =
-  let update r group_range =
-    match r with
-    | None -> group_range
-    | Some {endLine; endCharacter; _} ->
-        Option.map (
-          fun folding_range ->
-            {folding_range with endLine; endCharacter}
-        ) group_range
-  in
+let folding_range_data_in ~filename ({ cu_wss; _ }: Cobol_data.Types.compilation_unit) =
   (*add the folding_range of grouped item *)
   let rec add group l =
-    let r = folding_range_of_loc ~@group in
+    let r = range_of_loc_in ~filename ~@group in
     match ~&group with
     | Cobol_data.Group.Elementary _
     | Constant _ | Renames _ | ConditionName _ -> None, l
@@ -132,22 +145,18 @@ let folding_range_data ({ cu_wss; _ }:Cobol_data.Types.compilation_unit) =
     match ~&group with
     | Cobol_data.Group.Elementary _
     | Constant _ | Renames _ | ConditionName _ ->
-        update (folding_range_of_loc ~@group) r, l
+        extend_range r (range_of_loc_in ~filename ~@group), l
     | Group _ ->
         let r', l = add group l in
-        update r' r, l
+        extend_range r r', l
   in
   List.fold_left
     (fun acc group -> snd @@ add group acc) [] cu_wss
 
 
-let folding_range ptree cus =
-  let folding_range_cus =
-    Cobol_data.Compilation_unit.SET.to_seq cus
-    |> Seq.map (fun cu -> folding_range_data cu)
-    |> List.of_seq
-    |> List.flatten
-  in
-  folding_range_paragraph ptree @
-  folding_range_simple ptree @
-  folding_range_cus
+let ranges_in ~filename ptree cus =
+  Cobol_data.Compilation_unit.SET.to_seq cus
+  |> Seq.map (fun cu -> folding_range_data_in ~filename cu)
+  |> List.of_seq
+  |> List.flatten
+  |> acc_ranges_in ~filename ptree
diff --git a/src/lsp/cobol_lsp/lsp_request.ml b/src/lsp/cobol_lsp/lsp_request.ml
index 3af5ebbe8..3fe6a9e8a 100644
--- a/src/lsp/cobol_lsp/lsp_request.ml
+++ b/src/lsp/cobol_lsp/lsp_request.ml
@@ -284,11 +284,8 @@ let handle_completion registry (params: CompletionParams.t) =
 let handle_folding_range registry (params: FoldingRangeParams.t) =
   try_with_document_data registry params.textDocument
     ~f:begin fun ~doc:_ { ast; cus; _ } ->
-      Some (List.map
-              (fun Lsp_folding.{startLine; endLine; _} ->
-                 FoldingRange.create ~startLine ~endLine ())
-              (Lsp_folding.folding_range ast cus)
-            )
+      let filename = Lsp.Uri.to_path params.textDocument.uri in
+      Some (Lsp_folding.ranges_in ~filename ast cus)
     end
 
 let handle_shutdown registry =

From b15c5511aaaf10e7910d34a573f4baf4b14744d5 Mon Sep 17 00:00:00 2001
From: Nicolas Berthier <nicolas.berthier@ocamlpro.com>
Date: Wed, 27 Sep 2023 14:41:47 +0200
Subject: [PATCH 16/17] Mention LSP's support for folding range requests in
 `README.md`

---
 README.md | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/README.md b/README.md
index 2cb58f35e..47c0ed807 100644
--- a/README.md
+++ b/README.md
@@ -5,11 +5,12 @@
 
 ## Features
 
-* LSP (`superbol-free`) with following capabilities:
+* LSP (`superbol-free`) with the following capabilities:
     * Syntax diagnostics
     * Go to definitions
     * Find references
     * Peek on copybook and source text replacements
+    * Folding of whole divisions, sections, and paragraphs
     * Semantic highlighting
     * File and range indentation
 

From 72ad995d148d0a89d143337dbda689a2cd0d6bbf Mon Sep 17 00:00:00 2001
From: Nicolas Berthier <nicolas.berthier@ocamlpro.com>
Date: Fri, 29 Sep 2023 15:36:58 +0200
Subject: [PATCH 17/17] Add some bits of documentation for
 `Cobol_common.Srcloc`

---
 src/lsp/cobol_common/srcloc.ml | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/src/lsp/cobol_common/srcloc.ml b/src/lsp/cobol_common/srcloc.ml
index 2042b844b..7295f9d26 100644
--- a/src/lsp/cobol_common/srcloc.ml
+++ b/src/lsp/cobol_common/srcloc.ml
@@ -102,6 +102,9 @@ let rec start_pos: type t. t slt -> Lexing.position = function
   | Rpl { old; _ } -> start_pos old
   | Cat { left; _ } -> start_pos left
 
+(** [shallow_multiline_lexloc_in ~filename loc] retrieves a lexical location in
+    [filename] from [loc], iff [loc] directly originates from [filename] and was
+    not subject to any replacement or copy.  Returns [None] otherwise. *)
 let shallow_multiline_lexloc_in ~filename loc =
   let rec aux: type t. t slt -> lexloc option = function
     | Raw (s, e, _) when s.pos_fname = filename -> Some (s, e)
@@ -114,6 +117,9 @@ let shallow_multiline_lexloc_in ~filename loc =
   in
   aux loc
 
+(** [shallow_single_line_lexloc_in ~filename loc] is similar to
+    {!shallow_multiline_lexloc_in}, except that any returned lexical location is
+    guaranteed to span a single line. *)
 let shallow_single_line_lexloc_in ~filename = function
   | Raw (s, e, _) when s.pos_fname = filename -> Some (s, e)
   | Raw _ | Cpy _ | Rpl _ | Cat _ -> None