Better indications for the user :

- We're able to say from the parser what the user could have written. It may not be complete due to the acceptable function of Menhir : it is only an indication given to the user (and not intended to be an adaptive documentation)
- .mli file added : module interface for suggestions
- Add a test that provides a typographical or a logical error.
- Documentation and type / name changes for suggestions
This commit is contained in:
Aminata-Dev 2023-07-12 16:32:55 +02:00
parent c96c6e187f
commit 94f8eac858
7 changed files with 115 additions and 53 deletions

View File

@ -165,7 +165,7 @@ module Content = struct
| MainMessage msg -> msg ppf
| Result msg -> msg ppf
| Suggestion suggestions_list ->
Suggestions.display ppf suggestions_list)
Suggestions.format ppf suggestions_list)
ppf message_elements)
content
| Cli.GNU ->
@ -177,31 +177,36 @@ module Content = struct
let ppf = get_ppf target in
Format.pp_print_list ~pp_sep:Format.pp_print_newline
(fun ppf elt ->
let pos, message = match elt with
let pos, message =
match elt with
| MainMessage m ->
let pos =
List.find_map (function
| Position {pos_message = None; pos} -> Some pos
| _ -> None) content
List.find_map
(function
| Position { pos_message = None; pos } -> Some pos
| _ -> None)
content
|> function
| None ->
List.find_map (function
| Position {pos_message = _; pos} -> Some pos
| _ -> None) content
List.find_map
(function
| Position { pos_message = _; pos } -> Some pos
| _ -> None)
content
| some -> some
in
pos, m
| Position { pos_message; pos } ->
let message = match pos_message with
| Some m -> m
| None -> fun _ -> ()
let message =
match pos_message with Some m -> m | None -> fun _ -> ()
in
(Some pos), message
Some pos, message
| Result m -> None, m
| Suggestion sl -> None, fun ppf -> Suggestions.display ppf sl
| Suggestion sl -> None, fun ppf -> Suggestions.format ppf sl
in
Option.iter (fun pos -> Format.fprintf ppf "@{<blue>%s@}: "
(Pos.to_string_short pos))
Option.iter
(fun pos ->
Format.fprintf ppf "@{<blue>%s@}: " (Pos.to_string_short pos))
pos;
pp_marker target ppf;
Format.pp_print_char ppf ' ';
@ -220,19 +225,19 @@ exception CompilerError of Content.t
let raise_spanned_error
?(span_msg : Content.message option)
?(suggestion : string list option)
?(suggestion = ([] : string list))
(span : Pos.t)
format =
let continuation (message : Format.formatter -> unit) =
raise
(CompilerError
([MainMessage message; Position { pos_message = span_msg; pos = span }]
@ match suggestion with None -> [] | Some sugg -> [Suggestion sugg]))
@ match suggestion with [] -> [] | sugg -> [Suggestion sugg]))
in
Format.kdprintf continuation format
let raise_multispanned_error_full
?(suggestion : string list option)
?(suggestion = ([] : string list))
(spans : (Content.message option * Pos.t) list)
format =
Format.kdprintf
@ -243,14 +248,14 @@ let raise_multispanned_error_full
:: List.map
(fun (pos_message, pos) -> Position { pos_message; pos })
spans
@ match suggestion with None -> [] | Some sugg -> [Suggestion sugg])))
@ match suggestion with [] -> [] | sugg -> [Suggestion sugg])))
format
let raise_multispanned_error
?(suggestion : string list option)
?(suggestion = ([] : string list))
(spans : (string option * Pos.t) list)
format =
raise_multispanned_error_full ?suggestion
raise_multispanned_error_full ~suggestion
(List.map
(fun (msg, pos) ->
Option.map (fun s ppf -> Format.pp_print_string ppf s) msg, pos)

View File

@ -55,7 +55,7 @@ let levenshtein_distance (s : string) (t : string) : int =
of keyword + 1, in order to get suggestions close to "keyword")*)
let suggestion_minimum_levenshtein_distance_association
(candidates : string list)
(keyword : string) : string list option =
(keyword : string) : string list =
let rec strings_minimum_levenshtein_distance
(minimum : int)
(result : string list)
@ -88,16 +88,13 @@ let suggestion_minimum_levenshtein_distance_association
(*The "result" list is returned at the end of the "candidates'" list.*)
| [] -> result
in
let suggestions =
strings_minimum_levenshtein_distance
(1 + (String.length keyword / 3))
(*In order to select suggestions that are not too far away from the
keyword*)
[] candidates
in
match suggestions with [] -> None | _ :: _ -> Some suggestions
let display (ppf : Format.formatter) (suggestions_list : string list) =
let format (ppf : Format.formatter) (suggestions_list : string list) =
match suggestions_list with
| [] -> ()
| _ :: _ ->

View File

@ -0,0 +1,23 @@
(* This file is part of the Catala compiler, a specification language for tax
and social benefits computation rules. Copyright (C) 2023 Inria, contributor:
Aminata Boiguillé <aminata.boiguille@etu.sorbonne-universite.fr>, Emile
Rolley <emile.rolley@tuta.io>
Licensed under the Apache License, Version 2.0 (the "License"); you may not
use this file except in compliance with the License. You may obtain a copy of
the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
License for the specific language governing permissions and limitations under
the License. *)
val suggestion_minimum_levenshtein_distance_association :
string list -> string -> string list
(**Returns a list of the closest words into {!name:candidates} to the keyword
{!name:keyword}*)
val format : Format.formatter -> string list -> unit

View File

@ -130,7 +130,7 @@ let raise_error_cons_not_found
in
Message.raise_spanned_error
~span_msg:(fun ppf -> Format.fprintf ppf "Here is your code :")
?suggestion:closest_constructors (Mark.get constructor)
~suggestion:closest_constructors (Mark.get constructor)
"The name of this constructor has not been defined before@ (it's probably \
a typographical error)."

View File

@ -138,14 +138,14 @@ module ParserAux (LocalisedLexer : Lexer_common.LocalisedLexer) = struct
Format.fprintf ppf "Message: @{<yellow>%s@}@,%t"
(String.trim (String.uncapitalize_ascii msg)))
(fun (ppf : Format.formatter) ->
Format.fprintf ppf "You can only write : ";
Format.fprintf ppf "You could have written : ";
Format.pp_print_list
~pp_sep:(fun ppf () -> Format.fprintf ppf ",@ or ")
(fun ppf string -> Format.fprintf ppf "@{<yellow>\"%s\"@}" string)
ppf
(List.map (fun (s, _) -> s) acceptable_tokens))
in
raise_parser_error ?suggestion:similar_acceptable_tokens
raise_parser_error ~suggestion:similar_acceptable_tokens
(Pos.from_lpos (lexing_positions lexbuf))
(Option.map Pos.from_lpos last_positions)
(Utf8.lexeme lexbuf) custom_menhir_message

View File

@ -31,7 +31,7 @@ $ catala Interpret -s Test1
[ERROR]
Syntax error at token "scope"
Message: expected either 'condition', or 'content' followed by the expected variable type
You can only write : "condition",
You could have written : "condition",
or "content"
Error token:
@ -75,7 +75,7 @@ $ catala Interpret -s Test2
[ERROR]
Syntax error at token "scope"
Message: expected either 'condition', or 'content' followed by the expected variable type
You can only write : "condition",
You could have written : "condition",
or "content"
Error token:
@ -119,7 +119,7 @@ $ catala Interpret -s Test3
[ERROR]
Syntax error at token "scope"
Message: expected either 'condition', or 'content' followed by the expected variable type
You can only write : "condition",
You could have written : "condition",
or "content"
Error token:
@ -165,7 +165,7 @@ $ catala Interpret -s Test4
[ERROR]
Syntax error at token "scope"
Message: expected either 'condition', or 'content' followed by the expected variable type
You can only write : "condition",
You could have written : "condition",
or "content"
Error token:

View File

@ -0,0 +1,37 @@
###Article
```catala
declaration scope A:
output wrong_definition content integer
scope A:
definition wrong_definition = 1
```
```catala-test-inline
$ catala Interpret -s A
[ERROR]
Syntax error at token "="
Message: expected 'under condition' followed by a condition, 'equals' followed by the definition body, or the rest of the variable qualified name
You could have written : "of",
or "state",
or "equals",
or "under condition",
or "."
Error token:
┌─⯈ tests/test_default/bad/typing_or_logical_error.catala_en:8.30-8.31:
└─┐
8 │ definition wrong_definition = 1
│ ‾
Last good token:
┌─⯈ tests/test_default/bad/typing_or_logical_error.catala_en:8.13-8.29:
└─┐
8 │ definition wrong_definition = 1
│ ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
Maybe you wanted to write : "."
#return code 123#
```