Remove Comment variant and old comment-mode parser — CST handles all
Delete from sx_types.ml: - Comment of string variant (no longer needed) Delete from sx_parser.ml: - _preserve_comments mutable ref - collect_comment_node function - comment-mode branches in read_value, read_list - ~comments parameter from parse_all and parse_file - skip_whitespace and read_comment (only used by old comment mode) Delete from mcp_tree.ml: - has_interior_comments function - Comment handling in pretty_print_value - pretty_print_file function (replaced by CST write-back) - ~comments parameter from local parse_file Migrate sx_pretty_print, sx_write_file, sx_doc_gen to CST path. Net: -69 lines. 24/24 CST round-trips, 2583/2583 evaluator tests. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -30,23 +30,6 @@ let skip_whitespace_and_comments s =
|
||||
| _ -> ()
|
||||
in go ()
|
||||
|
||||
(* Skip whitespace only — leaves comments for capture *)
|
||||
let skip_whitespace s =
|
||||
let rec go () =
|
||||
if at_end s then ()
|
||||
else match s.src.[s.pos] with
|
||||
| ' ' | '\t' | '\n' | '\r' -> advance s; go ()
|
||||
| _ -> ()
|
||||
in go ()
|
||||
|
||||
(* Read a comment line starting at ';', returns text after ";;" (or ";") *)
|
||||
let read_comment s =
|
||||
let start = s.pos in
|
||||
while s.pos < s.len && s.src.[s.pos] <> '\n' do advance s done;
|
||||
let text = String.sub s.src start (s.pos - start) in
|
||||
if s.pos < s.len then advance s;
|
||||
text
|
||||
|
||||
(* Character classification — matches spec/parser.sx ident-start/ident-char.
|
||||
ident-start: a-z A-Z _ ~ * + - > < = / ! ? &
|
||||
ident-char: ident-start plus 0-9 . : / # , *)
|
||||
@@ -110,35 +93,7 @@ let try_number str =
|
||||
| Some n -> Some (Number n)
|
||||
| None -> None
|
||||
|
||||
(* Module-level flag — when true, comments are captured as Comment nodes.
|
||||
Set by parse_all ~comments:true, reset after. *)
|
||||
let _preserve_comments = ref false
|
||||
|
||||
(* Collect consecutive comment lines into a Comment node *)
|
||||
let collect_comment_node s =
|
||||
let lines = ref [] in
|
||||
let rec go () =
|
||||
skip_whitespace s;
|
||||
if not (at_end s) && s.src.[s.pos] = ';' then begin
|
||||
lines := read_comment s :: !lines;
|
||||
go ()
|
||||
end
|
||||
in
|
||||
go ();
|
||||
Comment (String.concat "\n" (List.rev !lines))
|
||||
|
||||
let rec read_value s : value =
|
||||
(* In comment-preserving mode, check for comments first *)
|
||||
if !_preserve_comments then begin
|
||||
skip_whitespace s;
|
||||
if not (at_end s) && s.src.[s.pos] = ';' then
|
||||
collect_comment_node s
|
||||
else
|
||||
read_value_core s
|
||||
end else
|
||||
read_value_core s
|
||||
|
||||
and read_value_core s : value =
|
||||
skip_whitespace_and_comments s;
|
||||
if at_end s then begin
|
||||
let line = ref 1 in
|
||||
@@ -212,29 +167,14 @@ and read_list s close_char =
|
||||
advance s; (* skip opening paren/bracket *)
|
||||
let items = ref [] in
|
||||
let rec go () =
|
||||
if !_preserve_comments then begin
|
||||
skip_whitespace s;
|
||||
if at_end s then raise (Parse_error "Unterminated list");
|
||||
if s.src.[s.pos] = close_char then begin
|
||||
advance s;
|
||||
List (List.rev !items)
|
||||
end else if s.src.[s.pos] = ';' then begin
|
||||
items := collect_comment_node s :: !items;
|
||||
go ()
|
||||
end else begin
|
||||
items := read_value_core s :: !items;
|
||||
go ()
|
||||
end
|
||||
skip_whitespace_and_comments s;
|
||||
if at_end s then raise (Parse_error "Unterminated list");
|
||||
if s.src.[s.pos] = close_char then begin
|
||||
advance s;
|
||||
List (List.rev !items)
|
||||
end else begin
|
||||
skip_whitespace_and_comments s;
|
||||
if at_end s then raise (Parse_error "Unterminated list");
|
||||
if s.src.[s.pos] = close_char then begin
|
||||
advance s;
|
||||
List (List.rev !items)
|
||||
end else begin
|
||||
items := read_value s :: !items;
|
||||
go ()
|
||||
end
|
||||
items := read_value s :: !items;
|
||||
go ()
|
||||
end
|
||||
in go ()
|
||||
|
||||
@@ -262,34 +202,26 @@ and read_dict s =
|
||||
in go ()
|
||||
|
||||
|
||||
(** Parse a string into a list of SX values.
|
||||
When [~comments:true], comments are preserved as [Comment] nodes —
|
||||
both at top level and inside lists. Default is [false] (strip). *)
|
||||
let parse_all ?(comments=false) src =
|
||||
_preserve_comments := comments;
|
||||
(** Parse a string into a list of SX values (AST — comments stripped). *)
|
||||
let parse_all src =
|
||||
let s = make_state src in
|
||||
let results = ref [] in
|
||||
let rec go () =
|
||||
if !_preserve_comments then skip_whitespace s
|
||||
else skip_whitespace_and_comments s;
|
||||
if at_end s then (
|
||||
_preserve_comments := false;
|
||||
List.rev !results
|
||||
) else begin
|
||||
skip_whitespace_and_comments s;
|
||||
if at_end s then List.rev !results
|
||||
else begin
|
||||
results := read_value s :: !results;
|
||||
go ()
|
||||
end
|
||||
in
|
||||
try go ()
|
||||
with e -> _preserve_comments := false; raise e
|
||||
in go ()
|
||||
|
||||
(** Parse a file into a list of SX values. *)
|
||||
let parse_file ?(comments=false) path =
|
||||
(** Parse a file into a list of SX values (AST — comments stripped). *)
|
||||
let parse_file path =
|
||||
let ic = open_in path in
|
||||
let n = in_channel_length ic in
|
||||
let src = really_input_string ic n in
|
||||
close_in ic;
|
||||
parse_all ~comments src
|
||||
parse_all src
|
||||
|
||||
|
||||
(* ================================================================== *)
|
||||
|
||||
@@ -67,7 +67,6 @@ and value =
|
||||
| CekState of cek_state (** Optimized CEK machine state — avoids Dict allocation. *)
|
||||
| CekFrame of cek_frame (** Optimized CEK continuation frame. *)
|
||||
| VmClosure of vm_closure (** VM-compiled closure — callable within the VM without allocating a new VM. *)
|
||||
| Comment of string (** Source comment — preserved through parse/edit/pretty-print round-trips. *)
|
||||
|
||||
(** CEK machine state — record instead of Dict for performance.
|
||||
5 fields × 55K steps/sec = 275K Hashtbl allocations/sec eliminated. *)
|
||||
@@ -348,7 +347,6 @@ let type_of = function
|
||||
| CekState _ -> "dict" (* CEK state behaves as a dict for type checks *)
|
||||
| CekFrame _ -> "dict"
|
||||
| VmClosure _ -> "function"
|
||||
| Comment _ -> "comment"
|
||||
|
||||
let is_nil = function Nil -> true | _ -> false
|
||||
let is_lambda = function Lambda _ -> true | _ -> false
|
||||
@@ -543,4 +541,3 @@ let rec inspect = function
|
||||
| CekState _ -> "<cek-state>"
|
||||
| CekFrame f -> Printf.sprintf "<frame:%s>" f.cf_type
|
||||
| VmClosure cl -> Printf.sprintf "<vm:%s>" (match cl.vm_name with Some n -> n | None -> "anon")
|
||||
| Comment text -> ";;" ^ text
|
||||
|
||||
Reference in New Issue
Block a user