Since the last time I asked a Q here, I got a great solution, I thought I’d ask another question.
I’m writing a bunch of lexers/parsers, and of course I want to test the Dickens out of them. So I have code like:
assert_equal () (ignore({|Hello, <name>!|} |> Pa_st.Template.of_string))
(and later, I will change the thing being compared-against, to something more meaningful, but for now, just knowing that the parser succeeds is useful. When the parser is driven from a file, or the string is from reading a file, this is easy: the function of_string takes a (Camlp5-style) location argument, viz:
val of_string : ?startloc:Ploc.t -> string -> t
and the lexer (underneath the parser) uses that location as the starting-point for the input; so any location within the text is offset from that start-location. But what about when (as above) the string is a constant in a file? I’d like to hand start-location of the string to of_string, but that seems not-obvious. ppx_here can get you a Position, but it’s not at the start of the string, and I don’t know of some obvious way to get that. So e.g.
{|abc def<|} |> Pa_st.Template.of_string ~startloc:(Util.ploc_of_position [%here])
works (and the string is malformed) and the error-message looks like this:
(Ploc.Exc (<"stringtemplate_test.ml":15:110-110>,
(Stream.Error "[map_expr] expected after '<' (in [expr_tag])")))
which is almost right! It’s just … offset from the string. I don’t know of an obvious way to get the location for the start of the string, short of a PPX rewriter kind of like ppx_here, which would work like this: the source phrase
[%wrap_here <expr>]
would be rewritten to
(<position of the expression>, <expr>)
So, kind of like ppx_here, but slightly different.
Does anybody have any thoughts on a way to do this without a new PPX rewriter? FTR, the problem isn’t writing the rewriter – it’s utterly trivial – but rather, I’m loath to pollute the space of PPX rewriters with yet another tiny, trivial rewriter, unless it’s actually, y’know, needed.
Your advice appreciated.