@@ -607,6 +607,17 @@ module Reason_syntax = struct
607607 let offer_normalize checkpoint triple =
608608 normalize_checkpoint (I. offer checkpoint triple)
609609
610+ let offer_normalize_many checkpoint triples =
611+ let rec loop acc xs = match xs with
612+ | [] -> Some acc
613+ | triple :: xs ->
614+ begin match normalize_checkpoint (I. offer acc triple) with
615+ | I. InputNeeded _ as checkpoint' -> loop checkpoint' xs
616+ | _ -> None
617+ end
618+ in
619+ loop checkpoint triples
620+
610621 (* Insert a semicolon before submitting a token to the parser *)
611622 let try_inserting_semi_on = function
612623 | Reason_parser. LET
@@ -662,6 +673,21 @@ module Reason_syntax = struct
662673 Some (offer_normalize checkpoint' (token, pos, pos))
663674 | _ -> None
664675
676+ let try_inserting_postfix checkpoint infix ((_ , pos , _ ) as triple ) =
677+ (* we know that the infix was exclusively composed of '^' *)
678+ let rec mk_postfixes acc i =
679+ if i < 0 then
680+ acc
681+ else
682+ let triple = (Reason_parser. POSTFIXOP " ^" , pos, pos) in
683+ mk_postfixes (triple :: acc) (i - 1 )
684+ in
685+ let infixes = mk_postfixes [] (String. length infix - 1 ) in
686+ match offer_normalize_many checkpoint infixes with
687+ | Some (I. InputNeeded _ as checkpoint' ) ->
688+ Some (offer_normalize checkpoint' triple)
689+ | _ -> None
690+
665691 (* Offer and insert a semicolon in case of failure *)
666692 let offer_normalize checkpoint triple =
667693 match offer_normalize checkpoint triple with
@@ -784,6 +810,40 @@ module Reason_syntax = struct
784810 in
785811 handle_inputs_needed supplier (List. map process_checkpoint checkpoints)
786812
813+ (*
814+ * This catches the `foo^^` case (which the parser thinks is an error – infix
815+ * without 2nd operand) and inserts as many postfix ops as there are carets
816+ * in the operator. We catch the token here and don't actually fork checkpoints
817+ * because catching this in `handle_other` would be too late – we would only
818+ * see the token where the error was (e.g. semicolon).
819+ *)
820+ | Reason_parser. INFIXOP1 op, _, _ as triple
821+ when List. for_all (fun x -> x == '^' ) (Reason_syntax_util. explode_str op) ->
822+ let rec process_checkpoints inputs_needed checkpoints =
823+ match checkpoints with
824+ | [] -> handle_inputs_needed supplier inputs_needed
825+ | (invalid_docstrings , checkpoint ) :: tl ->
826+ begin match offer_normalize checkpoint triple with
827+ | I. InputNeeded _ as checkpoint' ->
828+ let next_triple = read supplier in
829+ begin match offer_normalize checkpoint' next_triple with
830+ | I. HandlingError _ ->
831+ begin match try_inserting_postfix checkpoint op next_triple with
832+ | Some (I. Accepted _ as cp ) -> handle_other supplier cp
833+ | Some cp ->
834+ process_checkpoints ((invalid_docstrings, cp) :: inputs_needed) tl
835+ | None ->
836+ process_checkpoints ((invalid_docstrings, checkpoint') :: inputs_needed) tl
837+ end
838+ | checkpoint'' ->
839+ process_checkpoints ((invalid_docstrings, checkpoint'') :: inputs_needed) tl
840+ end
841+ | checkpoint' ->
842+ process_checkpoints ((invalid_docstrings, checkpoint') :: inputs_needed) tl
843+ end
844+ in
845+ process_checkpoints [] checkpoints
846+
787847 | triple ->
788848 begin match checkpoints with
789849 | [] -> assert false
0 commit comments