Much better syntax error messages

This commit is contained in:
Denis Merigoux 2020-10-05 00:39:29 +02:00
parent ce3829fc77
commit 899679b86c
3 changed files with 39 additions and 22 deletions

View File

@ -1191,7 +1191,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION
## In state 109, spurious reduction of production expression -> logical_expression
##
unbalanced parenthesis
unmatched parenthesis that should have been closed by here
source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION LPAREN YEAR
##
@ -1538,7 +1538,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION
## base_expression mult_op
##
expected an expression on the right side of the multiplication operator
expected an expression on the right side of the multiplication or division operator
source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE NOT_EQUAL YEAR
##
@ -1586,7 +1586,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION
## mult_expression sum_op
##
expected an expression on the right side of the sum operator
expected an expression on the right side of the sum or minus operator
source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE WE_HAVE
##
@ -1607,7 +1607,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION
## In state 45, spurious reduction of production primitive_expression -> small_expression
##
expected an operator to compose the expression with
expected an operator to compose the expression on the left with
source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE WITH YEAR
##
@ -1633,7 +1633,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION
## small_expression
##
expected an operator to compose the expression with
expected an operator to compose the expression on the left with
source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION VERTICAL INT_LITERAL DIV INT_LITERAL DIV INT_LITERAL YEAR
##

View File

@ -50,20 +50,31 @@ let levenshtein_distance (s : string) (t : string) : int =
d.(m).(n)
let raise_parser_error (loc : Pos.t) (token : string) (msg : string) =
Errors.raise_spanned_error (Printf.sprintf "Syntax error at token \"%s\"\n%s" token msg) loc
let syntax_hints_style = [ ANSITerminal.yellow ]
let raise_parser_error (error_loc : Pos.t) (last_good_loc : Pos.t option) (token : string)
(msg : string) : 'a =
Errors.raise_multispanned_error
(Printf.sprintf "Syntax error at token %s\n%s"
(Cli.print_with_style syntax_hints_style "\"%s\"" token)
msg)
( ( match last_good_loc with
| None -> []
| Some last_good_loc -> [ (Some "Last good token:", last_good_loc) ] )
@ [ (Some "Error token:", error_loc) ] )
let fail (lexbuf : lexbuf) (env : 'semantic_value I.env) (token_list : (string * Parser.token) list)
(last_input_needed : 'semantic_value I.env option) : 'a =
let wrong_token = Utf8.lexeme lexbuf in
let acceptable_tokens =
let acceptable_tokens, last_positions =
match last_input_needed with
| Some last_input_needed ->
List.filter
(fun (_, t) ->
I.acceptable (I.input_needed last_input_needed) t (fst (lexing_positions lexbuf)))
token_list
| None -> token_list
( List.filter
(fun (_, t) ->
I.acceptable (I.input_needed last_input_needed) t (fst (lexing_positions lexbuf)))
token_list,
Some (I.positions last_input_needed) )
| None -> (token_list, None)
in
let similar_acceptable_tokens =
List.sort
@ -83,19 +94,25 @@ let fail (lexbuf : lexbuf) (env : 'semantic_value I.env) (token_list : (string *
if levx = levy then String.length x - String.length y else levx - levy)
acceptable_tokens
in
let similar_token_msg =
if List.length similar_acceptable_tokens = 0 then None
else
Some
(Printf.sprintf "did you mean %s?"
(String.concat ", or maybe "
(List.map (fun (ts, _) -> Printf.sprintf "\"%s\"" ts) similar_acceptable_tokens)))
(List.map
(fun (ts, _) -> Cli.print_with_style syntax_hints_style "\"%s\"" ts)
similar_acceptable_tokens)))
in
(* The parser has suspended itself because of a syntax error. Stop. *)
let custom_menhir_message =
match Parser_errors.message (state env) with
| exception Not_found -> "Message: unexpected token"
| msg -> "Message: " ^ String.trim (String.uncapitalize_ascii msg)
| exception Not_found ->
"Message: " ^ Cli.print_with_style syntax_hints_style "%s" "unexpected token"
| msg ->
"Message: "
^ Cli.print_with_style syntax_hints_style "%s" (String.trim (String.uncapitalize_ascii msg))
in
let msg =
match similar_token_msg with
@ -103,7 +120,7 @@ let fail (lexbuf : lexbuf) (env : 'semantic_value I.env) (token_list : (string *
| Some similar_token_msg ->
Printf.sprintf "%s\nAutosuggestion: %s" custom_menhir_message similar_token_msg
in
raise_parser_error (lexing_positions lexbuf) (Utf8.lexeme lexbuf) msg
raise_parser_error (lexing_positions lexbuf) last_positions (Utf8.lexeme lexbuf) msg
let rec loop (next_token : unit -> Parser.token * Lexing.position * Lexing.position)
(token_list : (string * Parser.token) list) (lexbuf : lexbuf)

View File

@ -24,14 +24,14 @@ let message s =
| 21 -> "expected a \"/\"\n"
| 22 -> "expected the third component of the date literal\n"
| 23 -> "expected a delimiter to finish the date literal\n"
| 45 -> "expected an operator to compose the expression with\n"
| 45 -> "expected an operator to compose the expression on the left with\n"
| 51 -> "expected an enum constructor to test if the expression on the left\n"
| 50 -> "expected an operator to compose the expression with\n"
| 81 -> "expected an expression on the right side of the sum operator\n"
| 50 -> "expected an operator to compose the expression on the left with\n"
| 81 -> "expected an expression on the right side of the sum or minus operator\n"
| 105 -> "expected an expression on the right side of the logical operator\n"
| 53 -> "expected an expression for the argument of this function call\n"
| 77 -> "expected an expression on the right side of the comparison operator\n"
| 86 -> "expected an expression on the right side of the multiplication operator\n"
| 86 -> "expected an expression on the right side of the multiplication or division operator\n"
| 83 -> "expected an operator to compose the expression on the left\n"
| 132 -> "expected an expression standing for the set you want to test for membership\n"
| 46 -> "expected an identifier standing for a struct field or a subscope name\n"
@ -60,7 +60,7 @@ let message s =
complete\n"
| 139 -> "expected the \"with patter\" keyword to complete the pattern matching expression\n"
| 32 -> "expected an expression inside the parenthesis\n"
| 125 -> "unbalanced parenthesis\n"
| 125 -> "unmatched parenthesis that should have been closed by here\n"
| 54 -> "expected a unit for this literal, or a valid operator to complete the expression \n"
| 34 -> "expected an expression for the test of the conditional\n"
| 135 -> "expected an expression the for the \"then\" branch of the conditiona\n"