murmour/mparser

Interface question/suggestion: returning user state in parse result

rvantonder opened this issue · 3 comments

Hi @murmour! Thanks for writing mparser, it's really neat. I had a question about the interface here:

mparser/src/mParser.mli

Lines 273 to 285 in 71494dd

val parse: ('a, 's) t -> MParser_Char_Stream.t -> 's -> 'a result
(** [parse p s user] runs the parser [p] on the input stream [s] using the
initial user state [user]. *)
val parse_string: ('a, 's) t -> string -> 's -> 'a result
(** [parse_string p str user] runs the parser [p] on the input stream produced
from the string [str] using the initial user state [user]. The stream is
created with [MParser_Char_Stream.from_string]. *)
val parse_channel: ('a, 's) t -> in_channel -> 's -> 'a result
(** [parse_string p chn user] runs the parser [p] on the input stream produced
from the channel [chn] using the initial user state [user]. The stream is
created with [MParser_Char_Stream.from_channel]. *)

Basically, I found that if I passed the user state 's into the parse function, I could never get it out again. Is the idea to only make the user-state readonly? For a long time I've used a modified interface in comby because I was relying on user state. I could rewrite it to rely on the 'a result, but it seems like a reasonable idea to return user state somehow? For example, another monadic interface I've seen to return these parts are like so:

          val run : ('a,'s) t -> 's -> ('a * 's) result
          val eval : ('a,'s) t -> 's -> 'a result
          val exec : ('a,'s) t -> 's -> 's result

in BAP

I'm happy to make a PR-- let me know what you think. Maybe a new function that returns 'a result (non-breaking change), or update the return value of parse_string to return it (that would be a breaking change)

Hello!

Thanks for writing mparser

The author is @harnold, so thanks to him. :-)

Basically, I found that if I passed the user state 's into the parse function, I could never get it out again. Is the idea to only make the user-state readonly? For a long time I've used a modified interface in comby because I was relying on user state. I could rewrite it to rely on the 'a result, but it seems like a reasonable idea to return user state somehow?

I agree that getting user state on successful parse is quite useful. In the (yet) unreleased version of the library I've extended Success to hold state, which breaks compatibility, like some other things in this upcoming 2.0 release.

For a while, why not use the following pattern?

match parse (pair p get_user_state) stream state with
  | Success (result, state) ->
    ...

It only adds a few characters to the client code.

That's an excellent suggestion! I totally missed that I could use pair for this. Thank you. I'm fine with closing this issue from my side with the workaround, will let you decide to leave it open or close it if you want to track things :-)

Wow, you're real fast with replies! (cough-cough, 😅)

Closing, and preparing release! :-)