Какова цель переменной _loc при определении правил грамматики в camlp4?
_loc
переменная появляется здесь в правиле грамматики для match ... with
выражение в качестве аргумента, переданного mk_sequence
функция.
| "match"; e = sequence; "with"; a = match_case ->
<:expr< match $mksequence' _loc e$ with [ $a$ ] >>
Но это не используется в mksequence
Функциональное тело.
value mksequence _loc =
fun
[ <:expr< $_$; $_$ >> | <:expr< $anti:_$ >> as e -> <:expr< do { $e$ } >>
| e -> e ]
;
_loc
переменная также появляется в других местах в правилах грамматики.
В руководстве по генерации кода camlp4 говорится, что _loc
обозначает место. Но я не совсем понимаю объяснение там. Может кто-нибудь объяснить мне цель передачи неиспользованного _loc
переменная вокруг?
1 ответ
Грубо говоря, _loc
это "текущая позиция". Обычно это указывается на местоположение соответствующего AST в правилах синтаксического анализа.
_loc
это обычная переменная OCaml, и фактически вездесущая в коде CamlP4, но синтаксический сахар P4 приятно скрывает большую часть их существования. Вы можете узнать, как _loc вводится и используется в P4, предварительно обработав ваш модуль P4 с помощью P4. Например,
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
используется в <:expr< match ... >>
который расширяется в Ast.ExMat (_loc, ...)
в дополнение к его второму использованию в mksequence' _loc e
, который написан от руки.
<:expr<...>>
и другие <:XXX<...>>
конструкции в р4 использует это _loc
переменная, так что вы можете создать свой AST, не задумываясь о его местонахождении. Автоматически использует _loc
, "текущее проанализированное местоположение". Если вы не хотите использовать _loc
за <:expr<...>>
ты можешь использовать <:expr@myloc<...>>
явно указать местоположение вашего AST.
Иногда вы хотите использовать <:expr<...>>
вне правил синтаксического анализа, и в этом случае _loc
не связан. Вы должны использовать <:expr@myloc<...>>
или используйте <:expr<...>
после связывания _loc
чем-то другим. Как правило, let _loc = Loc.ghost
что означает "не где".
P4 очень сложен, и в сети не так много документации. Иногда расширение кода P4 на P4 помогает понять, как он работает.