functional-programmingocamlocamllex

How to override a module method in Ocaml


Say I have a module A which overrides some methods from module B. I would like module A to prevent such overriding in module A by overriding B or in some other way.

I need this to get line numbers from YoJSON. I tried using other parsers but they don't have as many features as YoJSON.

The line numbers in the buffer are prevented by the following code in YoJSON's read.ml

  module Lexing =
    (*
      We override Lexing.engine in order to avoid creating a new position
      record each time a rule is matched.
      This reduces total parsing time by about 31%.
    *)
  struct
    include Lexing

    external c_engine : lex_tables -> int -> lexbuf -> int = "caml_lex_engine"

    let engine tbl state buf =
      let result = c_engine tbl state buf in
      (*
      if result >= 0 then begin
        buf.lex_start_p <- buf.lex_curr_p;
        buf.lex_curr_p <- {buf.lex_curr_p
                           with pos_cnum = buf.lex_abs_pos + buf.lex_curr_pos};
      end;
      *)
      result
  end

  open Printf
  open Lexing

Source: https://github.com/ocaml-community/yojson/blob/master/lib/read.mll

Is there a way I could reverse this behaviour? Would overriding Lexer again and then overriding all methods in YoJSON that use Lexer work?

Or is there a way to get line numbers of a json members with YoJSON or other parser some other way?


Solution

  • Module functions are not methods. More precisely, there are not subjects to late bindings and can never be overriden. The code that you are linking is shadowing the original engine function.

    Moreover, Yojson is computing line numbers for error messages, but they are never integrated into the parsed json. There is no way to get line number from the Yojson parser without rewriting the parser.