粗略地说,_loc
就是“当前位置”。通常它是在解析规则中匹配的 AST 的位置。
_loc
是一个普通的 OCaml 变量,实际上在 CamlP4 代码中无处不在,但是 P4 的语法糖很好地隐藏了它们的大部分存在。您可以通过 P4 预处理您的 P4 模块来了解如何在 P4 中引入和使用“_loc”。例如,
EXTEND Gram
my_syntax:
[ [ "match"; e = sequence; "with"; a = match_case ->
<:expr< match $mksequence' _loc e$ with [ $a$ ] >>
] ];
END;
如果你对上面的内容进行预处理camlp4rf
,你就会明白它的真正含义:
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)))) ]) ]))
())
这有点难,但你可以找到Gram.Action.mk
一个引入参数的函数_loc
。它绑定到与以 . 开头的规范匹配的 AST 的位置[ Gram.Skeyword "match"...
。然后_loc
使用 at<:expr< match ... >>
扩展为Ast.ExMat (_loc, ...)
,除了第二次使用 at mksequence' _loc e
,它是手写的。
<:expr<...>>
p4中的其他<:XXX<...>>
构造使用此_loc
变量,因此您可以创建 AST 而无需过多考虑它的位置。它自动使用_loc
“当前解析的位置”。如果你不想使用_loc
for<:expr<...>>
你可以使用<:expr@myloc<...>>
明确指定你的 AST 的位置。
有时您想<:expr<...>>
在解析规则之外使用,在这种情况下_loc
是未绑定的。您必须使用<:expr@myloc<...>>
,或在被其他东西<:expr<...>
绑定后使用。_loc
通常,let _loc = Loc.ghost
这意味着“没有地方”。
P4 非常复杂,网上没有太多可用的文档。有时,通过 P4 扩展您的 P4 代码有助于理解它是如何工作的。