2

I would like to add incremental API and error handling of menhir to my project by sedlex+menhir; I'm trying to adopt attempt2 and fail of this sample to my code. Here is the attempt2 of the sample:

let attempt2 filename text =
  (* Allocate and initialize a lexing buffer. *)
  let lexbuf = L.init filename (Lexing.from_string text) in
  (* Wrap the lexer and lexbuf together into a supplier, that is, a
     function of type [unit -> token * position * position]. *)
  let supplier = I.lexer_lexbuf_to_supplier Lexer.token lexbuf in
  (* Equip the supplier with a two-place buffer that records the positions
     of the last two tokens. This is useful when a syntax error occurs, as
     these are the token just before and just after the error. *)
  let buffer, supplier = E.wrap_supplier supplier in
  (* Fetch the parser's initial checkpoint. *)
  let checkpoint = UnitActionsParser.Incremental.main lexbuf.lex_curr_p in
  (* Run the parser. *)
  (* We do not handle [Lexer.Error] because we know that we will not
     encounter a lexical error during this second parsing run. *)
  I.loop_handle succeed (fail text buffer) supplier checkpoint

In my code, I tried:

let lexbuf : Lexing.lexbuf = MenhirLib.LexerUtil.init "filename" (Lexing.from_string s) in
let supplier = UnitActionsParser_e.MenhirInterpreter.lexer_lexbuf_to_supplier Sedlexer_e.token_ao lexbuf in

However, the compilation gave me an error:

260 |       let supplier = UnitActionsParser_e.MenhirInterpreter.lexer_lexbuf_to_supplier Sedlexer_e.token_ao lexbuf in
                                                                                          ^^^^^^^^^^^^^^^^^^^
Error: This expression has type Sedlexing.lexbuf -> Parser_e.token
       but an expression was expected of type
         Lexing.lexbuf -> UnitActionsParser_e.MenhirInterpreter.token
       Type Sedlexing.lexbuf is not compatible with type Lexing.lexbuf 
make: *** [expression/e.cmo] Error 2

Could anyone help?

(* link in GitHub *)

SoftTimur
  • 5,630
  • 38
  • 140
  • 292
  • They are indeed incompatible so you can't just drop one for another. The good news is that you can use `MenhirLib.Convert.Simplified.revised2traditional` to wrap the `Sedlexing.lexbuf` into the appropriate to menhir interface. Is the following answer https://stackoverflow.com/questions/30853159/using-menhir-with-sedlex sufficient to you or do you need a more detailed answer? If yes, then please rephrase, as, otherwise, it is a complete duplicate. – ivg Feb 18 '22 at 19:27
  • Thank you for the comment. My project has already been using Sedlex, so I think the build system and flags of menhir are fine. In this question, I am looking for code and functions to manipulate lexbuf and so to overcome the incompatibility error. For instance, could you elaborate more about the solution with `revised2traditional`? – SoftTimur Feb 18 '22 at 19:35

1 Answers1

0

The code of lexer_lexbuf_to_supplier is as follows:

  let lexer_lexbuf_to_supplier
      (lexer : Lexing.lexbuf -> token)
      (lexbuf : Lexing.lexbuf)
  : supplier =
    fun () ->
      let token = lexer lexbuf in
      let startp = lexbuf.Lexing.lex_start_p
      and endp = lexbuf.Lexing.lex_curr_p in
      token, startp, endp

So I made a lexer_lexbuf_to_supplier_sedlex:

  let lexer_lexbuf_to_supplier_sedlex
    (lexer: Sedlexing.lexbuf -> token)
    (lexbuf : Sedlexing.lexbuf) 
  : supplier =
    fun () ->
      let token = lexer lexbuf in
      let startp, endp = Sedlexing.lexing_positions lexbuf in
      token, startp, endp

It works so far.

SoftTimur
  • 5,630
  • 38
  • 140
  • 292