大まかに言えば、_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"...
ます。次に、手で書かれたでの2番目の使用に加えて、に展開されたで_loc
使用されます。<:expr< match ... >>
Ast.ExMat (_loc, ...)
mksequence' _loc e
<:expr<...>>
<:XXX<...>>
また、 p4の他の構成ではこの_loc
変数を使用するため、ASTの場所をあまり考慮せずにASTを作成できます。自動的_loc
に「現在の解析位置」を使用します。_loc
を使用したくない場合は、を使用してASTの場所を明示的に指定<:expr<...>>
できます。<:expr@myloc<...>>
<:expr<...>>
解析ルールの外で使用したい場合があり、その場合_loc
はバインドされていません。を使用するか、他の何かによってバインドした後に<:expr@myloc<...>>
使用する必要があります。通常、これは「どこにもない」という意味です。<:expr<...>
_loc
let _loc = Loc.ghost
P4は非常に複雑であり、ネットで入手できるドキュメントはあまりありません。P4コードをP4で拡張すると、その動作を理解するのに役立つ場合があります。