interpreter.ml 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. (**
  2. This module provide a way to build the syntax parser with the menhir
  3. incremental engine. This feature allow to see the state of the parser, and
  4. get detailed error message but is not intended to be used directly.
  5. Refer to the menhir manual in order to see the values.
  6. The interresting function here is [of_lexbuf] which return the error code in
  7. case of invalid syntax.
  8. *)
  9. type error_code =
  10. | UnrecoverableError
  11. | InvalidSyntax
  12. | MenhirCode of int
  13. | Custom of string
  14. module Interpreter (MI : MenhirLib.IncrementalEngine.INCREMENTAL_ENGINE) =
  15. struct
  16. type error = {
  17. code : error_code;
  18. start_pos : Lexing.position;
  19. end_pos : Lexing.position;
  20. }
  21. module E = MenhirLib.ErrorReports
  22. module L = MenhirLib.LexerUtil
  23. type step = MI.token * Lexing.position * Lexing.position
  24. let range_message (start_pos, end_pos) : error_code -> error =
  25. fun code -> { code; start_pos; end_pos }
  26. let get_parse_error : Lexbuf.t -> 'a MI.env -> error =
  27. fun buffer env ->
  28. match MI.stack env with
  29. | (lazy Nil) ->
  30. (* The parser is in its initial state. We should not get an
  31. error here *)
  32. let positions = Lexbuf.positions buffer in
  33. range_message positions UnrecoverableError
  34. | (lazy (Cons (MI.Element (state, _, start_pos, end_pos), _))) ->
  35. range_message (start_pos, end_pos) (MenhirCode (MI.number state))
  36. let rec _parse :
  37. Lexbuf.t -> (unit -> step) -> 'a MI.checkpoint -> ('a, error) Result.t =
  38. fun buffer get_token (checkpoint : 'a MI.checkpoint) ->
  39. match checkpoint with
  40. | MI.InputNeeded _env ->
  41. let token, startp, endp = get_token () in
  42. let checkpoint = MI.offer checkpoint (token, startp, endp) in
  43. _parse buffer get_token checkpoint
  44. | MI.Shifting _ | MI.AboutToReduce _ ->
  45. let checkpoint = MI.resume checkpoint in
  46. _parse buffer get_token checkpoint
  47. | MI.HandlingError _env ->
  48. let err = get_parse_error buffer _env in
  49. Error err
  50. | MI.Accepted v -> Ok v
  51. | MI.Rejected ->
  52. let positions = Lexbuf.positions buffer in
  53. let err = range_message positions InvalidSyntax in
  54. Error err
  55. type 'a builder = Lexing.position -> 'a MI.checkpoint
  56. let of_lexbuf :
  57. (unit -> step) -> Lexbuf.t -> 'a MI.checkpoint -> ('a, error) result =
  58. fun lexer buffer init -> _parse buffer lexer init
  59. end