Skip to content

Commit

Permalink
Better represent informational paragraphs
Browse files Browse the repository at this point in the history
Additionally, use a dedicated token to avoid retokenization of program IDs
  • Loading branch information
nberth committed Oct 3, 2023
1 parent 81b21bd commit 0a3c09c
Show file tree
Hide file tree
Showing 22 changed files with 6,584 additions and 6,603 deletions.
83 changes: 56 additions & 27 deletions src/lsp/cobol_ast/misc_descr.ml
Original file line number Diff line number Diff line change
Expand Up @@ -14,25 +14,26 @@
open Terms
open Operands

let if_empty pp_el pp_nel ppf = function
| [] -> pp_el ppf ()
| xs -> pp_nel ppf xs

let elist ?prefix:(prf = Fmt.nop) ?sep pp =
if_empty Fmt.nop Fmt.(prf ++ list ?sep pp)


(* -------------------- IDENTIFICATION DIVISION (EXTRA) -------------------- *)

type informational_paragraphs =
{
author: string with_loc option;
installation: string with_loc option;
date_written: string with_loc option;
date_compiled: string with_loc option;
security: string with_loc option;
}
[@@deriving show, ord]
informational_paragraph with_loc list
[@@deriving ord]

and informational_paragraph =
informational_paragraph_header * comment_entry with_loc

and informational_paragraph_header =
| Author
| DateCompiled
| DateModified
| DateWritten
| Installation
| Remarks
| Security

and comment_entry = string list


(* ------------------------- ENVIRONMENT DIVISION -------------------------- *)
Expand Down Expand Up @@ -655,7 +656,8 @@ let pp_select_clause ppf = function
| SelectRecordKey { key; source } ->
Fmt.pf ppf "RECORD %a%a"
pp_qualname key
Fmt.(elist ~prefix:(any "SOURCE ") ~sep:sp pp_name') source
Pretty.(list ~fopen:"SOURCE " ~fsep:"@ " ~fclose:"" ~fempty:""
pp_name') source
| SelectRelativeKey n ->
Fmt.pf ppf "RELATIVE %a" pp_name' n
| SelectReserve n -> Fmt.pf ppf "RESERVE %a" pp_integer n
Expand Down Expand Up @@ -711,6 +713,8 @@ and arithmetic_mode =
and entry_convention =
| COBOL

(* --- *)

let pp_entry_convention ppf = function
| COBOL -> Fmt.pf ppf "COBOL"

Expand All @@ -721,21 +725,46 @@ let pp_arithmetic_mode ppf = function
| StandardDecimal -> Fmt.pf ppf "STANDARD-DECIMAL"

let pp_options_clause ppf = function
| Arithmetic am -> Fmt.pf ppf "ARITHMETIC %a" pp_arithmetic_mode am
| Arithmetic am ->
Fmt.pf ppf "ARITHMETIC %a" pp_arithmetic_mode am
| DefaultRoundedMode rm ->
Fmt.pf ppf "DEFAULT ROUNDED MODE %a" pp_rounding_mode rm
Fmt.pf ppf "DEFAULT ROUNDED MODE %a" pp_rounding_mode rm
| EntryConvention ec ->
Fmt.pf ppf "ENTRY-CONVENTION %a" pp_entry_convention ec
Fmt.pf ppf "ENTRY-CONVENTION %a" pp_entry_convention ec
| FloatBinaryDefault em ->
Fmt.pf ppf "FLOAT-BINARY %a" Data_descr.pp_endianness_mode em
Fmt.pf ppf "FLOAT-BINARY %a" Data_descr.pp_endianness_mode em
| FloatDecimalDefault ee ->
Fmt.pf ppf "FLOAT-DECIMAL %a" Data_descr.pp_encoding_endianness ee
Fmt.pf ppf "FLOAT-DECIMAL %a" Data_descr.pp_encoding_endianness ee
| IntermediateRounding rm ->
Fmt.pf ppf "INTERMEDIATE-ROUNDING %a" pp_rounding_mode rm
Fmt.pf ppf "INTERMEDIATE-ROUNDING %a" pp_rounding_mode rm

let pp_options_paragraph : options_paragraph Fmt.t =
Fmt.(
any "OPTIONS.@ " ++
box (list ~sep:sp (pp_with_loc pp_options_clause))
++ any "."
)
Fmt.(any "OPTIONS.@ " ++
box (list ~sep:sp (pp_with_loc pp_options_clause)) ++
any ".")


(* --- *)

let pp_informational_paragraph_header ppf = function
| Author -> Fmt.pf ppf "AUTHOR"
| DateCompiled -> Fmt.pf ppf "DATE-COMPILED"
| DateModified -> Fmt.pf ppf "DATE-MODIFIED"
| DateWritten -> Fmt.pf ppf "DATE-WRITTEN"
| Installation -> Fmt.pf ppf "INSTALLATION"
| Remarks -> Fmt.pf ppf "REMARKS"
| Security -> Fmt.pf ppf "SECURITY"

let pp_comment_entry: comment_entry Pretty.printer =
Fmt.(list ~sep:sp string)

let pp_informational_paragraph: informational_paragraph Pretty.printer =
Fmt.(any "@[<4>" ++ (* <- indent by 4 to avoid Area A *)
pair ~sep:(any ".@ ")
pp_informational_paragraph_header
(pp_with_loc pp_comment_entry) ++
any "@]")

let pp_informational_paragraphs: informational_paragraphs Pretty.printer =
Fmt.(list ~sep:(any "@\n") (* force newlines *)
(pp_with_loc pp_informational_paragraph))
84 changes: 38 additions & 46 deletions src/lsp/cobol_ast/raw.ml
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,10 @@

open Ast

module Misc_sections = struct
type informational_paragraphs = Ast.informational_paragraphs
let pp_informational_paragraphs = Ast.pp_informational_paragraphs
let compare_informational_paragraphs = Ast.compare_informational_paragraphs
type options_paragraph = Ast.options_paragraph
let pp_options_paragraph = Ast.pp_options_paragraph
let compare_options_paragraph = Ast.compare_options_paragraph
type environment_division = Ast.environment_division
let pp_environment_division = Ast.pp_environment_division
let compare_environment_division = Ast.compare_environment_division
end
module Misc_sections: Abstract.MISC_SECTIONS
with type informational_paragraphs = Ast.informational_paragraphs
and type options_paragraph = Ast.options_paragraph
and type environment_division = Ast.environment_division = Ast

module Data_sections (Picture: Abstract.PICTURE) = struct
include Picture
Expand Down Expand Up @@ -819,9 +812,13 @@ struct
| ProgramDefinition of
{ (* Note: more general than before (allows nested prototypes): *)
kind: program_kind option;
has_identification_division: bool;
informational_paragraphs: informational_paragraphs
[@compare fun _ _ -> 0]; (* ~COB85, -COB2002 *)
has_identification_division_header: bool;
preliminary_informational_paragraphs:
informational_paragraphs (* GC extension (before PROGRAM-ID) *)
[@compare fun _ _ -> 0];
supplementary_informational_paragraphs:
informational_paragraphs
[@compare fun _ _ -> 0]; (* ~COB85, -COB2002 *)
nested_programs: program_unit with_loc list;
}
| ProgramPrototype
Expand All @@ -837,42 +834,37 @@ struct
| Initial -> Fmt.pf ppf "INITIAL"
| Recursive -> Fmt.pf ppf "RECURSIVE"

let rec pp_program_unit ppf {
program_name;
program_as;
program_level;
program_options;
program_env;
program_data;
program_proc;
program_end_name;
} =
let has_identification_division =
let rec pp_program_unit ppf { program_name;
program_as;
program_level;
program_options;
program_env;
program_data;
program_proc;
program_end_name } =
let has_identification_division_header,
preliminary_info, supplementary_info,
nested_programs,
kind =
match program_level with
| ProgramDefinition { has_identification_division = true; _ } -> true
| _ -> false
| ProgramDefinition { has_identification_division_header = p;
preliminary_informational_paragraphs = ip0;
supplementary_informational_paragraphs = ip1;
nested_programs;
kind } ->
p, Some ip0, Some ip1, nested_programs, Some kind
| ProgramPrototype ->
false, None, None, [], None
in
let nested_programs =
match program_level with
| ProgramDefinition { nested_programs; _ } -> nested_programs
| ProgramPrototype -> []
in
let _informational_paragraphs =
match program_level with
| ProgramDefinition { informational_paragraphs = ip; _ } -> Some ip
| ProgramPrototype -> None
in
if has_identification_division then
Fmt.pf ppf "@[IDENTIFICATION@ DIVISION@].@ ";
if has_identification_division_header then
Fmt.pf ppf "@[IDENTIFICATION@ DIVISION@].@\n";
Fmt.(option pp_informational_paragraphs) ppf preliminary_info;
Fmt.pf ppf "@[PROGRAM-ID.@ %a" (pp_with_loc pp_name) program_name;
Fmt.(option (any "@ AS " ++ pp_strlit)) ppf program_as;
(
match program_level with
| ProgramDefinition { kind; _ } ->
Fmt.(option (sp ++ pp_program_kind)) ppf kind
| ProgramPrototype -> Fmt.pf ppf "@ PROTOTYPE"
);
Fmt.pf ppf ".@]";
Fmt.(option (option (sp ++ pp_program_kind))
~none:(any "@ PROTOTYPE")) ppf kind;
Fmt.pf ppf ".@]@\n";
Fmt.(option pp_informational_paragraphs) ppf supplementary_info;
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;
Expand Down
26 changes: 16 additions & 10 deletions src/lsp/cobol_ast/raw_compilation_group_visitor.ml
Original file line number Diff line number Diff line change
Expand Up @@ -104,21 +104,27 @@ struct
~continue:begin fun { program_name; program_as; program_level;
program_options; program_env; program_data;
program_proc; program_end_name } x -> x
>> fold_name' v program_name
>> fold_strlit_opt v program_as
>> (fun x -> match program_level with
| ProgramPrototype -> x
>> fold_name' v program_name
>> fold_strlit_opt v program_as
| ProgramDefinition { (* has_identification_division_header; *)
preliminary_informational_paragraphs = infos0;
supplementary_informational_paragraphs = infos1;
kind; _ } -> ignore kind; x
(* >> fold_bool v has_identification_division_header *)
>> v#continue_with_informational_paragraphs infos0
>> fold_name' v program_name
>> fold_strlit_opt v program_as
>> v#continue_with_informational_paragraphs infos1)
>> fold_options_paragraph'_opt v program_options
>> fold_environment_division'_opt v program_env
>> fold_data_division'_opt v program_data
>> fold_procedure_division'_opt v program_proc
>> (fun x -> match program_level with
| ProgramPrototype -> x
| ProgramDefinition { kind;
has_identification_division;
informational_paragraphs = infos;
nested_programs } -> ignore kind; x
>> fold_bool v has_identification_division
>> v#continue_with_informational_paragraphs infos
>> fold_with_loc_list v nested_programs ~fold:fold_program_unit)
>> fold_procedure_division'_opt v program_proc
| ProgramDefinition { nested_programs; _ } -> x
>> fold_with_loc_list v ~fold:fold_program_unit nested_programs)
>> fold_name'_opt v program_end_name (* XXX: useful? *)
end

Expand Down
13 changes: 5 additions & 8 deletions src/lsp/cobol_ast/raw_misc_sections_visitor.ml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ module Make = struct
class virtual ['a] folder = object
inherit ['a] Terms_visitor.folder
inherit ['a] Misc_sections_visitor.folder
method fold_informational_paragraph': (informational_paragraph with_loc, 'a) fold = default
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
Expand Down Expand Up @@ -161,16 +162,12 @@ module Make = struct

(* --- *)

let fold_informational_paragraph' (v: _ #folder) =
leaf' v#fold_informational_paragraph' v

let fold_informational_paragraphs (v: _ #folder) =
handle v#fold_informational_paragraphs
~continue:begin fun { author; installation; date_written;
date_compiled; security } x -> x
>> fold_string'_opt v author
>> fold_string'_opt v installation
>> fold_string'_opt v date_written
>> fold_string'_opt v date_compiled
>> fold_string'_opt v security
end
~continue:(fold_list ~fold:fold_informational_paragraph' v)

let fold_options_paragraph (v: _ #folder) =
handle v#fold_options_paragraph
Expand Down
6 changes: 6 additions & 0 deletions src/lsp/cobol_common/visitor.ml
Original file line number Diff line number Diff line change
Expand Up @@ -157,9 +157,15 @@ module Fold = struct

(** Helper to shorten definitions for traversal of nodes with source
locations *)
(* NOTE: we consider the traversal of `t with_loc` as a whole before the
generic traversal of `_ with_loc` via [fold']. Maybe doing it the other
way round would be more intuitive? *)
let handle' vfold ~fold (v: _ #folder) =
handle vfold ~continue:(fold' ~fold v)

let leaf' vfold =
handle' vfold ~fold:(fun _ _ -> Fun.id)

(* --- *)

(** Reports a missing folding visitor implementation {e once}. *)
Expand Down
Loading

0 comments on commit 0a3c09c

Please sign in to comment.