The _loc
variable appears in here in the grammar rule for the match ... with
expression as an argument passed to the mk_sequence
function.
| "match"; e = sequence; "with"; a = match_case ->
<:expr< match $mksequence' _loc e$ with [ $a$ ] >>
But it is not used in the mksequence
's function body.
value mksequence _loc =
fun
[ <:expr< $_$; $_$ >> | <:expr< $anti:_$ >> as e -> <:expr< do { $e$ } >>
| e -> e ]
;
The _loc
variable also appears in other places in the grammar rules.
In the camlp4 code generation tutorial, it says that _loc
stands for location. But I don't quite understand the explanation there. Can someone explain to me the purpose for passing an unused _loc
variable around?
Roughly speaking, _loc
is "the current position". Normally it is bould to the location of the matched AST in parsing rules.
_loc
is an ordinary OCaml variable, and actually omnipresent in CamlP4 code, but P4's syntax sugar nicely hide most of their existence. You can learn how '_loc' is introduced and used in P4 by preprocess your P4 module by P4. For example,
EXTEND Gram
my_syntax:
[ [ "match"; e = sequence; "with"; a = match_case ->
<:expr< match $mksequence' _loc e$ with [ $a$ ] >>
] ];
END;
If you preprocess the above by camlp4rf
, you got what it really means:
Gram.extend (my_syntax : 'my_syntax Gram.Entry.t)
((fun () ->
(None,
[ (None, None,
[ ([ Gram.Skeyword "match";
Gram.Snterm
(Gram.Entry.obj (sequence : 'sequence Gram.Entry.t));
Gram.Skeyword "with";
Gram.Snterm
(Gram.Entry.obj (match_case : 'match_case Gram.Entry.t)) ],
(Gram.Action.mk
(fun (a : 'match_case) _ (e : 'sequence) _
(_loc : Gram.Loc.t) ->
(Ast.ExMat (_loc, (mksequence' _loc e), a) : 'my_syntax)))) ]) ]))
())
It is bit hard but you can find Gram.Action.mk
takes a function introducing an argument _loc
. It is bound to the location of an AST which matches with the specification starts with [ Gram.Skeyword "match"...
. Then _loc
is used at <:expr< match ... >>
which is expanded into Ast.ExMat (_loc, ...)
, in addition to its second use at mksequence' _loc e
, which is written by hand.
<:expr<...>>
and the other <:XXX<...>>
constructs in p4 uses this _loc
variable so that you can create your AST without considering much about the location of it. It automatically uses _loc
, "the current parsed location". If you do not want to use _loc
for <:expr<...>>
you can use <:expr@myloc<...>>
to explicitly specify the location of your AST.
Sometimes you want to use <:expr<...>>
outside of parsing rules, and in that case _loc
is unbound. You must use <:expr@myloc<...>>
, or use <:expr<...>
after binding _loc
by something else. Typically, let _loc = Loc.ghost
which means "no where".
P4 is very complex, and there are not much documentations available in the net. Sometimes expanding your P4 code by P4 helps understanding how it works.