From 6dc8d7789aa165663d135c62a9f766b6b26c4920 Mon Sep 17 00:00:00 2001
From: Chimrod <>
Date: Fri, 8 Dec 2023 15:03:22 +0100
Subject: Better error recovery after an error in one source file

---
 lib/qparser/lexer.ml  | 33 +++++++++++++++++++++++++--------
 lib/qparser/lexer.mli |  1 +
 2 files changed, 26 insertions(+), 8 deletions(-)

(limited to 'lib/qparser')

diff --git a/lib/qparser/lexer.ml b/lib/qparser/lexer.ml
index a1dbba1..5741b7a 100644
--- a/lib/qparser/lexer.ml
+++ b/lib/qparser/lexer.ml
@@ -106,7 +106,14 @@ let rec read_long_string ?(nested = false) level buf buffer =
       read_long_string ~nested level buf buffer
   | _ -> raise Not_found
 
-(** Read the text inside a ['] *)
+(** Read the text inside a ['] or ['"']
+
+    The function return the parsed string, but the closing token has been
+    rollbacked, leaving the state in [Lexbuf.EndString _].
+
+    The next call to [main] will call the associated function, effectively
+    leaving the string mode in the parser.
+ *)
 let rec read_quoted_string : Lexbuf.stringWraper -> Lexbuf.buffer_builder =
  fun f ?(nested = false) buf buffer ->
   let lexbuf = Lexbuf.buffer buffer in
@@ -264,24 +271,33 @@ let rec discard buffer =
   match%sedlex lexbuf with
   | '\'' -> (
       match Lexbuf.state buffer with
-      | Some (Lexbuf.String _) ->
-          (* If we are inside a string, close it. *)
+      | Some (Lexbuf.String _) | Some (Lexbuf.EndString _) ->
+          (* If we are inside a string, or just beforce closing it, close it.
+           *)
           Lexbuf.leave_state buffer;
           discard buffer
       | _ ->
           (* Otherwise wait skip until the end of the starting one *)
-          ignore
-            (read_quoted_string Lex_state.quotedStringWraper (Buffer.create 16)
-               buffer);
+          Lexbuf.enter_state buffer (Lexbuf.String Lex_state.quotedStringWraper);
+          (try
+             ignore
+               (read_quoted_string Lex_state.quotedStringWraper
+                  (Buffer.create 16) buffer)
+           with e ->
+             Printexc.print_backtrace stdout;
+
+             raise e);
           discard buffer)
   | '"' -> (
       match Lexbuf.state buffer with
-      | Some (Lexbuf.String _) ->
+      | Some (Lexbuf.String _) | Some (Lexbuf.EndString _) ->
           Lexbuf.leave_state buffer;
           discard buffer
       | _ ->
+          Lexbuf.enter_state buffer
+            (Lexbuf.String Lex_state.dQuotedStringWraper);
           ignore
-            (read_quoted_string Lex_state.quotedStringWraper (Buffer.create 16)
+            (read_quoted_string Lex_state.dQuotedStringWraper (Buffer.create 16)
                buffer);
           discard buffer)
   | '}' -> (
@@ -294,6 +310,7 @@ let rec discard buffer =
           discard buffer)
   | '{' ->
       ignore (read_long_string 0 (Buffer.create 16) buffer);
+      Lexbuf.leave_state buffer;
       discard buffer
   | '-', Plus '-', Star (Sub (any, ('\r' | '\n'))) ->
       leave_expression buffer;
diff --git a/lib/qparser/lexer.mli b/lib/qparser/lexer.mli
index be10ddb..299fa46 100644
--- a/lib/qparser/lexer.mli
+++ b/lib/qparser/lexer.mli
@@ -14,3 +14,4 @@ val discard : Lexbuf.t -> unit
     Used in case of unrecoverable error *)
 
 val main : Lexbuf.t -> Tokens.token
+(** Main entry point. This function is called after each token returned *)
-- 
cgit v1.2.3