Skip to content

Commit 05b4e53

Browse files
committed
refactor(cram): lex locations in cram tests
We add support for lexing locations in cram tests. Signed-off-by: Ali Caglayan <[email protected]>
1 parent 328ee24 commit 05b4e53

File tree

4 files changed

+273
-83
lines changed

4 files changed

+273
-83
lines changed

src/dune_rules/cram/cram_exec.ml

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,8 @@ module For_tests = struct
5454

5555
let dyn_of_block = function
5656
| Cram_lexer.Comment lines -> Dyn.variant "Comment" [ Dyn.list Dyn.string lines ]
57-
| Command lines -> Dyn.variant "Command" [ Dyn.list Dyn.string lines ]
57+
| Command (loc, lines) ->
58+
Dyn.variant "Command" [ Loc.to_dyn loc; Dyn.list Dyn.string lines ]
5859
;;
5960
end
6061

@@ -178,10 +179,10 @@ let read_and_attach_exit_codes (sh_script : sh_script)
178179
| [], [] -> List.rev acc
179180
| (Cram_lexer.Comment _ as comment) :: blocks, _ ->
180181
loop (comment :: acc) entries blocks
181-
| Command block_result :: blocks, metadata_entry :: entries ->
182-
loop (Command (block_result, Present metadata_entry) :: acc) entries blocks
183-
| Cram_lexer.Command block_result :: blocks, [] ->
184-
loop (Command (block_result, Missing_unreachable) :: acc) entries blocks
182+
| Command (loc, block_result) :: blocks, metadata_entry :: entries ->
183+
loop (Command (loc, (block_result, Present metadata_entry)) :: acc) entries blocks
184+
| Cram_lexer.Command (loc, block_result) :: blocks, [] ->
185+
loop (Command (loc, (block_result, Missing_unreachable)) :: acc) entries blocks
185186
| [], _ :: _ -> Code_error.raise "more blocks than metadata" []
186187
in
187188
loop [] metadata_entries sh_script.cram_to_output
@@ -238,7 +239,7 @@ let sanitize ~parent_script cram_to_output : command_out Cram_lexer.block list =
238239
List.map cram_to_output ~f:(fun (t : (block_result * _) Cram_lexer.block) ->
239240
match t with
240241
| Cram_lexer.Comment t -> Cram_lexer.Comment t
241-
| Command (block_result, metadata) ->
242+
| Command (loc, (block_result, metadata)) ->
242243
let output =
243244
match metadata with
244245
| Missing_unreachable -> "***** UNREACHABLE *****"
@@ -250,7 +251,7 @@ let sanitize ~parent_script cram_to_output : command_out Cram_lexer.block list =
250251
~command_script:block_result.script
251252
build_path_prefix_map
252253
in
253-
Command { command = block_result.command; metadata; output })
254+
Command (loc, { command = block_result.command; metadata; output }))
254255
;;
255256

256257
(* Compose user written cram stanzas to output *)
@@ -267,7 +268,7 @@ let compose_cram_output (cram_to_output : _ Cram_lexer.block list) =
267268
List.iter cram_to_output ~f:(fun block ->
268269
match (block : _ Cram_lexer.block) with
269270
| Comment lines -> List.iter lines ~f:add_line
270-
| Command { command; metadata; output } ->
271+
| Command (_loc, { command; metadata; output }) ->
271272
List.iteri command ~f:(fun i line ->
272273
let line = sprintf "%c %s" (if i = 0 then '$' else '>') line in
273274
add_line_prefixed_with_two_space line);
@@ -314,7 +315,7 @@ let create_sh_script cram_stanzas ~temp_dir : sh_script Fiber.t =
314315
let loop block =
315316
match (block : _ Cram_lexer.block) with
316317
| Comment _ as comment -> Fiber.return comment
317-
| Command lines ->
318+
| Command (loc, lines) ->
318319
incr i;
319320
let i = !i in
320321
let file ~ext = file (sprintf "%d%s" i ext) in
@@ -340,10 +341,11 @@ let create_sh_script cram_stanzas ~temp_dir : sh_script Fiber.t =
340341
Dune_util.Build_path_prefix_map._BUILD_PATH_PREFIX_MAP
341342
metadata_file_sh_path;
342343
Cram_lexer.Command
343-
{ command = lines
344-
; output_file = user_shell_code_output_file
345-
; script = user_shell_code_file
346-
}
344+
( loc
345+
, { command = lines
346+
; output_file = user_shell_code_output_file
347+
; script = user_shell_code_file
348+
} )
347349
in
348350
fprln oc "trap 'exit 0' EXIT";
349351
let+ cram_to_output = Fiber.sequential_map ~f:loop cram_stanzas in
@@ -433,7 +435,7 @@ let run_cram_test env ~src ~script ~cram_stanzas ~temp_dir ~cwd ~timeout =
433435
let command_blocks_only =
434436
List.filter_map sh_script.cram_to_output ~f:(function
435437
| Cram_lexer.Comment _ -> None
436-
| Cram_lexer.Command block_result -> Some block_result)
438+
| Cram_lexer.Command (_, block_result) -> Some block_result)
437439
in
438440
let total_commands = List.length command_blocks_only in
439441
if completed_count < total_commands
@@ -486,7 +488,7 @@ let run_and_produce_output ~src ~env ~dir:cwd ~script ~dst ~timeout =
486488
let+ commands =
487489
run_cram_test env ~src ~script ~cram_stanzas ~temp_dir ~cwd ~timeout
488490
>>| List.filter_map ~f:(function
489-
| Cram_lexer.Command c -> Some c
491+
| Cram_lexer.Command (_, c) -> Some c
490492
| Comment _ -> None)
491493
in
492494
let dst = Path.build dst in
@@ -552,7 +554,7 @@ module Make_script = struct
552554
|> cram_stanzas
553555
|> List.filter_map ~f:(function
554556
| Cram_lexer.Comment _ -> None
555-
| Command s -> Some s)
557+
| Command (_, s) -> Some s)
556558
|> cram_commmands
557559
in
558560
Io.write_file ~binary:false (Path.build dst) commands;
@@ -596,10 +598,11 @@ module Diff = struct
596598
| [] -> acc
597599
| Cram_lexer.Comment x :: current ->
598600
loop (Cram_lexer.Comment x :: acc) current expected
599-
| Command _ :: current ->
601+
| Command (loc, _) :: current ->
600602
(match expected with
601603
| [] -> acc
602-
| out :: expected -> loop (Cram_lexer.Command out :: acc) current expected)
604+
| out :: expected ->
605+
loop (Cram_lexer.Command (loc, out) :: acc) current expected)
603606
in
604607
loop [] current_stanzas out |> List.rev
605608
in

src/dune_rules/cram/cram_lexer.mli

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1+
open Import
2+
13
(** .t file parser *)
24

35
(** A command or comment. Output blocks are skipped *)
46
type 'command block =
5-
| Command of 'command
7+
| Command of Loc.t * 'command
68
| Comment of string list
79

810
val block : Lexing.lexbuf -> string list block option

src/dune_rules/cram/cram_lexer.mll

Lines changed: 87 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,67 +1,107 @@
11
{
2+
open Import
3+
24
type 'command block =
3-
| Command of 'command
5+
| Command of Loc.t * 'command
46
| Comment of string list
57
}
68

7-
let eol = '\n' | eof
9+
let nonspace = [^' ' '\n']
10+
let not_nl = [^'\n']
811

9-
let blank = [' ' '\t' '\r' '\012']
12+
rule eol = parse
13+
| '\n' { Lexing.new_line lexbuf; true }
14+
| eof { false }
1015

11-
rule block = parse
16+
and block = parse
1217
| eof { None }
13-
| " $ " ([^'\n']* as str) eol
14-
{ Some (command_cont [str] lexbuf) }
15-
| " " [^'\n']* eol
16-
{ output [] lexbuf }
17-
| ' '? as str eol
18-
{ comment [str] lexbuf }
19-
| ' '? [^' ' '\n'] [^'\n']* as str eol
20-
{ comment [str] lexbuf }
18+
| " $ " ([^'\n']* as str)
19+
{ let start = Lexing.lexeme_start_p lexbuf in
20+
let start = { start with pos_cnum = start.pos_cnum + 2 } in
21+
let stop0 = Lexing.lexeme_end_p lexbuf in
22+
match eol lexbuf with
23+
| true -> Some (command_cont start stop0 [ str ] lexbuf)
24+
| false -> Some (Command (Loc.create ~start ~stop:stop0, [ str ])) }
25+
| " > " ([^'\n']* as str)
26+
{ ignore (eol lexbuf);
27+
comment [ " > " ^ str ] lexbuf }
28+
| " >"
29+
{ ignore (eol lexbuf);
30+
comment [ " >" ] lexbuf }
31+
| " " [^'\n']*
32+
{ ignore (eol lexbuf);
33+
output [] lexbuf }
34+
| ' ' ((nonspace not_nl*) as rest)
35+
{ ignore (eol lexbuf);
36+
comment [ " " ^ rest ] lexbuf }
37+
| ' ' '\n'
38+
{ Lexing.new_line lexbuf;
39+
comment [ " " ] lexbuf }
40+
| ' '
41+
{ comment [ " " ] lexbuf }
42+
| '\n'
43+
{ Lexing.new_line lexbuf;
44+
comment [ "" ] lexbuf }
45+
| nonspace not_nl* as str
46+
{ ignore (eol lexbuf);
47+
comment [str] lexbuf }
2148

2249
and comment acc = parse
2350
| eof
2451
{ match acc with
25-
| [] -> None
26-
| _ -> Some (Comment (List.rev acc))
27-
}
28-
| ' '? as str eol
29-
{ comment (str :: acc) lexbuf }
30-
| ' '? [^' ' '\n'] [^'\n']* as str eol
31-
{ comment (str :: acc) lexbuf }
32-
| ""
33-
{ Some (Comment (List.rev acc)) }
52+
| [] -> None
53+
| _ -> Some (Comment (List.rev acc)) }
54+
| ' ' ((nonspace not_nl*) as rest)
55+
{ ignore (eol lexbuf);
56+
comment ((" " ^ rest) :: acc) lexbuf }
57+
| ' ' '\n'
58+
{ Lexing.new_line lexbuf;
59+
comment (" " :: acc) lexbuf }
60+
| '\n'
61+
{ Lexing.new_line lexbuf;
62+
comment ("" :: acc) lexbuf }
63+
| nonspace not_nl* as str
64+
{ ignore (eol lexbuf);
65+
comment (str :: acc) lexbuf }
66+
| "" { Some (Comment (List.rev acc)) }
3467

3568
and output maybe_comment = parse
3669
| eof
3770
{ match maybe_comment with
38-
| [] -> None
39-
| l -> Some (Comment (List.rev l))
40-
}
41-
| ' ' eof
42-
{ Some (Comment (List.rev (" " :: maybe_comment))) }
43-
| " "? eof
44-
{ None }
45-
| " " eol
46-
{ output [] lexbuf }
47-
| ' '? as s eol
48-
{ output (s :: maybe_comment) lexbuf }
49-
| " $" eol
50-
{ output [] lexbuf }
51-
| " " '$' [^' ' '\n'] [^'\n']* eol
52-
{ output [] lexbuf }
53-
| " " [^'$' '\n'] [^'\n']* eol
54-
{ output [] lexbuf }
71+
| [] -> None
72+
| l -> Some (Comment (List.rev l)) }
73+
| " $ " ([^'\n']* as str)
74+
{ let start = Lexing.lexeme_start_p lexbuf in
75+
let start = { start with pos_cnum = start.pos_cnum + 2 } in
76+
let stop0 = Lexing.lexeme_end_p lexbuf in
77+
match eol lexbuf with
78+
| true -> Some (command_cont start stop0 [ str ] lexbuf)
79+
| false -> Some (Command (Loc.create ~start ~stop:stop0, [ str ])) }
80+
| ' ' ((nonspace not_nl*) as rest)
81+
{ match eol lexbuf with
82+
| true -> output ((" " ^ rest) :: maybe_comment) lexbuf
83+
| false -> Some (Comment (List.rev ((" " ^ rest) :: maybe_comment))) }
84+
| ' ' '\n'
85+
{ Lexing.new_line lexbuf;
86+
output (" " :: maybe_comment) lexbuf }
87+
| " " [^'\n']*
88+
{ ignore (eol lexbuf);
89+
output maybe_comment lexbuf }
5590
| ""
5691
{ match maybe_comment with
57-
| [] -> block lexbuf
58-
| l -> comment l lexbuf
59-
}
92+
| [] -> block lexbuf
93+
| l -> comment l lexbuf }
6094

61-
and command_cont acc = parse
62-
| " > " ([^'\n']* as str) eol
63-
{ command_cont (str :: acc) lexbuf }
64-
| " >" eol
65-
{ command_cont ("" :: acc) lexbuf }
95+
and command_cont start last_stop acc = parse
96+
| " > " ([^'\n']* as str)
97+
{ let stop0 = Lexing.lexeme_end_p lexbuf in
98+
match eol lexbuf with
99+
| true -> command_cont start stop0 (str :: acc) lexbuf
100+
| false -> Command (Loc.create ~start ~stop:stop0, List.rev (str :: acc)) }
101+
| " >"
102+
{ let stop0 = Lexing.lexeme_end_p lexbuf in
103+
match eol lexbuf with
104+
| true -> command_cont start stop0 ("" :: acc) lexbuf
105+
| false -> Command (Loc.create ~start ~stop:stop0, List.rev ("" :: acc)) }
66106
| ""
67-
{ Command (List.rev acc) }
107+
{ Command (Loc.create ~start ~stop:last_stop, List.rev acc) }

0 commit comments

Comments
 (0)