123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172(* There are three main categories of error:
- _lexer errors_, thrown by Reason_lexer when the source **text is malformed**
and no token can be produced
- _concrete parsing errors_, thrown by the menhir parser / parsing loop
when a **token is unexpected**
- _abstract parsing errors_, thrown by hand-written semantic actions or
further AST checks, when the source text was incorrect but this restriction
was too fine to be captured by the grammar rules
A fourth case is when unknown / unexpected error occurs.
*)openPpxlibopenFormattypelexing_error=|Illegal_characterofchar|Illegal_escapeofstring|Unterminated_commentofLocation.t|Unterminated_string|Unterminated_string_in_commentofLocation.t*Location.t|Keyword_as_labelofstring|Literal_overflowofstring|Invalid_literalofstringtypeast_error=|Not_expectingofLocation.t*string|Other_syntax_errorofstring|Variable_in_scopeofLocation.t*string|Applicative_pathofLocation.ttypeparsing_error=stringtypereason_error=|Lexing_erroroflexing_error|Parsing_errorofparsing_error|Ast_errorofast_errorexceptionReason_errorofreason_error*Location.tletcatch_errors:(reason_error*Location.t)listrefoptionref=refNoneletraise_errorerrorloc=match!catch_errorswith|None->raise(Reason_error(error,loc))|Somecaught->caught:=(error,loc)::!caughtletraise_fatal_errorerrorloc=raise(Reason_error(error,loc))letrecover_non_fatal_errorsf=letcatch_errors0=!catch_errorsinleterrors=ref[]incatch_errors:=Someerrors;letresult=matchf()with|x->Okx|exceptionexn->Errorexnincatch_errors:=catch_errors0;(result,List.rev!errors)(* Report lexing errors *)letformat_lexing_errorppf=function|Illegal_characterc->fprintfppf"Illegal character (%s)"(Char.escapedc)|Illegal_escapes->fprintfppf"Illegal backslash escape in string or character (%s)"s|Unterminated_comment_->fprintfppf"Comment not terminated"|Unterminated_string->fprintfppf"String literal not terminated"|Unterminated_string_in_comment(_,loc)->fprintfppf"This comment contains an unterminated string literal@.\
%aString literal begins here"Ocaml_util.print_locloc|Keyword_as_labelkwd->fprintfppf"`%s' is a keyword, it cannot be used as label name"kwd|Literal_overflowty->fprintfppf"Integer literal exceeds the range of representable \
integers of type %s"ty|Invalid_literals->fprintfppf"Invalid literal %s"sletformat_parsing_errorppfmsg=fprintfppf"%s"msgletformat_ast_errorppf=function|Not_expecting(loc,nonterm)->fprintfppf"Syntax error: %a%s not expected."Ocaml_util.print_loclocnonterm|Applicative_pathloc->fprintfppf"Syntax error: %aapplicative paths of the form F(X).t \
are not supported when the option -no-app-func is set."Ocaml_util.print_locloc|Variable_in_scope(loc,var)->fprintfppf"%aIn this scoped type, variable '%s \
is reserved for the local type %s."Ocaml_util.print_loclocvarvar|Other_syntax_errormsg->fprintfppf"%s"msgletformat_errorppf=function|Lexing_errorerr->format_lexing_errorppferr|Parsing_errorerr->format_parsing_errorppferr|Ast_errorerr->format_ast_errorppferrletreport_errorppf~locerr=Format.fprintfppf"@[%a@]@."(Ocaml_util.print_errorlocformat_error)errletrecover_parser_errorflocmsg=if!Reason_config.recoverablethenflocmsgelseraise_fatal_error(Parsing_errormsg)loclet()=Printexc.register_printer(function|Reason_error(err,loc)->let_=Format.flush_str_formatter()inreport_errorFormat.str_formatter~locerr;Some(Format.flush_str_formatter())|_->None)letstr_eval_messagetext={Parsetree.pstr_loc=Location.none;pstr_desc=Pstr_eval({pexp_loc=Location.none;pexp_desc=Pexp_constant(Parsetree.Pconst_string(text,Location.none,None));pexp_attributes=[];pexp_loc_stack=[];},[]);}(** Generate a suitable extension node for Merlin's consumption,
for the purposes of reporting a parse error - only used
in recovery mode.
Parse error will prevent Merlin from reporting subsequent errors, as they
might be due wrong recovery decisions and will confuse the user.
*)leterror_extension_node_from_recoverylocmsg=recover_parser_error(funlocmsg->letstr={Location.loc;txt="merlin.syntax-error"}inletpayload=[str_eval_messagemsg]in(str,Parsetree.PStrpayload))locmsg(** Generate a suitable extension node for OCaml consumption,
for the purposes of reporting a syntax error.
Contrary to [error_extension_node_from_recovery], these work both with
OCaml and with Merlin.
*)leterror_extension_nodelocmsg=recover_parser_error(funlocmsg->letstr={Location.loc;txt="ocaml.error"}inletpayload=[str_eval_messagemsg;(* if_highlight *)str_eval_messagemsg;]in(str,Parsetree.PStrpayload))locmsg