Step 14: source locations — pos-to-loc, error-loc, sx-parse-loc — 15 tests
Pure SX layer: pos-to-loc (offset→line/col), error-loc (parse result→loc), format-parse-error (human-readable error with source context line). OCaml platform: cst_to_ast_loc (CST spans→loc dicts), sx-parse-loc primitive (parse with locations), source-loc accessor. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -164,6 +164,24 @@ let make_test_env () =
|
||||
| [String s] -> List (parse_all s)
|
||||
| _ -> raise (Eval_error "sx-parse: expected string"));
|
||||
|
||||
bind "sx-parse-loc" (fun args ->
|
||||
match args with
|
||||
| [String s] ->
|
||||
let cst = Sx_parser.parse_all_cst s in
|
||||
List (Sx_cst.cst_to_ast_loc s cst.nodes)
|
||||
| _ -> raise (Eval_error "sx-parse-loc: expected string"));
|
||||
|
||||
bind "source-loc" (fun args ->
|
||||
match args with
|
||||
| [Dict d] ->
|
||||
let line = try Hashtbl.find d "line" with Not_found -> Nil in
|
||||
let col = try Hashtbl.find d "col" with Not_found -> Nil in
|
||||
let ld = Sx_types.make_dict () in
|
||||
Sx_types.dict_set ld "line" line;
|
||||
Sx_types.dict_set ld "col" col;
|
||||
Dict ld
|
||||
| _ -> Nil);
|
||||
|
||||
bind "sx-parse-one" (fun args ->
|
||||
match args with
|
||||
| [String s] ->
|
||||
|
||||
@@ -104,6 +104,33 @@ let rec cst_to_ast = function
|
||||
Dict d
|
||||
|
||||
|
||||
(** Convert character offset to line/col (1-based lines, 0-based cols) *)
|
||||
let offset_to_loc src offset =
|
||||
let line = ref 1 and col = ref 0 in
|
||||
for i = 0 to min (offset - 1) (String.length src - 1) do
|
||||
if src.[i] = '\n' then (incr line; col := 0)
|
||||
else col := !col + 1
|
||||
done;
|
||||
(!line, !col)
|
||||
|
||||
(** CST → AST with source location dicts ({:form value :line N :col N}) *)
|
||||
let cst_to_ast_loc src nodes =
|
||||
List.map (fun node ->
|
||||
let span = match node with
|
||||
| CstAtom { span; _ } -> span
|
||||
| CstList { span; _ } -> span
|
||||
| CstDict { span; _ } -> span
|
||||
in
|
||||
let value = cst_to_ast node in
|
||||
let (line, col) = offset_to_loc src span.start_offset in
|
||||
let d = make_dict () in
|
||||
dict_set d "form" value;
|
||||
dict_set d "line" (Number (float_of_int line));
|
||||
dict_set d "col" (Number (float_of_int col));
|
||||
Dict d
|
||||
) nodes
|
||||
|
||||
|
||||
(** {1 CST editing — apply AST-level edits back to the CST} *)
|
||||
|
||||
(** Replace the CST node at [path] with [new_source], preserving the
|
||||
|
||||
Reference in New Issue
Block a user