Fix up case for handling empty string properly

This commit is contained in:
Rijnard van Tonder 2019-10-02 01:22:00 -04:00 committed by GitHub
parent 8ffaef329e
commit 2a3164ce91
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 48 additions and 21 deletions

View File

@ -733,7 +733,19 @@ module Make (Syntax : Syntax.S) (Info : Info.S) = struct
let set_start_pos p = fun s -> p (advance_state s shift) in
let p = set_start_pos p in
match parse_string' p source (Match.create ()) with
| Success (_, result) -> Ok result
| Success (_, result) ->
if source = "" then
(* If source is empty and p succeeds, it's the trivial case. We set
the result manually. *)
Ok {
result with
range =
{ match_start = { offset = 0; line = 1; column = 1 }
; match_end = { offset = 0; line = 1; column = 1 }
}
}
else
Ok result
| Failed (msg, _) -> Or_error.error_string msg
let first ?configuration ?shift template source =
@ -756,25 +768,28 @@ module Make (Syntax : Syntax.S) (Info : Info.S) = struct
in
make_result @@ begin
to_template template >>= fun p ->
if original_source = "" || template = "" then
return []
else
let rec aux acc shift =
match first' shift p original_source with
| Ok ({range = { match_start; match_end; _ }; _} as result) ->
let shift = match_end.offset in
let matched = extract_matched_text original_source match_start match_end in
let result = { result with matched } in
if shift >= String.length original_source then
result :: acc
else
aux (result :: acc) shift
| Error _ -> acc
in
let matches = aux [] 0 |> List.rev in
(* TODO(RVT): reintroduce nested matches *)
let compute_nested_matches matches = matches in
let matches = compute_nested_matches matches in
return matches
let p =
if template = "" then
MParser.(eof >> return Unit)
else
p
in
let rec aux acc shift =
match first' shift p original_source with
| Ok ({range = { match_start; match_end; _ }; _} as result) ->
let shift = match_end.offset in
let matched = extract_matched_text original_source match_start match_end in
let result = { result with matched } in
if shift >= String.length original_source then
result :: acc
else
aux (result :: acc) shift
| Error _ -> acc
in
let matches = aux [] 0 |> List.rev in
(* TODO(RVT): reintroduce nested matches *)
let compute_nested_matches matches = matches in
let matches = compute_nested_matches matches in
return matches
end
end

View File

@ -418,3 +418,15 @@ let%expect_test "contextual_matching_with_short_hole_syntax" =
let rewrite_template = {|:[[1]]|} in
run source match_template rewrite_template;
[%expect_exact {|dst1; dst2;|}]
let%expect_test "trivial_empty_case" =
let source = "" in
let match_template = "" in
begin
Generic.all ~configuration ~template:match_template ~source
|> function
| [] -> print_string "No matches."
| hd :: _ ->
print_string (Yojson.Safe.to_string (Match.to_yojson hd))
end;
[%expect_exact {|{"range":{"start":{"offset":0,"line":1,"column":1},"end":{"offset":0,"line":1,"column":1}},"environment":[],"matched":""}|}]