Какова цель переменной _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 помогает понять, как он работает.

Другие вопросы по тегам