ディレクティブ

パーサディレクティブは次の形式を持つ: directive[expression]

ディレクティブはその内側の式の振る舞いを修正する。本質的にはそれを '修飾' する。 フレームワークはいくつかのディレクティブをあらかじめ定義している。 フレームワークの利用者は必要に応じて独自のディレクティブを自由に定義できる。 どうやって定義するかという話は後で述べることにして、この段階では 定義済みディレクティブのみ扱うことにしよう。

lexeme_d

空白のスキップを停止する。字句レベルの構文解析では、パーサは空白および空白と見なされるものをすべて無視する。 ここでいう空白には、パーサの parse メンバ関数へ渡されたスキャナによってパラメータ化されたコメントも含まれる。

しかし字句レベルでなく文字レベルで動作させたいような状況では、特別な構成物を持ち込む必要がある。 ルールは、文法の適当な一部を lexeme_d ディレクティブの内側に囲むことで、文字レベルで働くようにし向けることができる。 例として、はじめにで与えられた例を完成させてみよう。 あちらでは integer ルールの定義は飛ばした。 その定義は非常に明白であるが、フレームワークのコンテキストで実際にはどのように定義されていたかをここで示そう:

    integer = lexeme_d[ !(ch_p('+') | '-') >> +digit ];

lexeme_d ディレクティブはパーサが文字レベルで動作するよう強制する。 これを用いない場合、 integer ルールは入力に間違って埋め込まれた空白を許してしまう。 例えば、 "1 2 345""12345" として構文解析されるだろう。

as_lower_d

大文字小文字の区別を抑制したいことがある。 as_lower_d ディレクティブは入力したすべての文字を小文字へと変換する。

as_lower_d の振る舞い

重要なことは、入力だけが小文字へ変換されるという点に注意することだ。 大文字を期待しているあらゆるパーサは、 as_lower_d ディレクティブの内側に囲い込まれると構文解析に失敗する。 例えば: as_lower_d['X'] は決して成功しない。 なぜならこのパーサは as_lower_d ディレクティブが絶対に提供しないはずの大文字の 'X' を期待しているからである。

例えば、パスカルでは、キーワードと識別子は大文字小文字で区別されない。 パスカルは識別子やキーワードにおいては文字の大小を無視する。 従ってパスカルの識別子 Id 、 ID および id はは同じものである。 大文字小文字の区別をしないディレクティブを用いない場合、これを認識するルールの定義は厄介だ:

    r = str_p("id") | "Id" | "iD" | "ID";

さて、大文字小文字の区別をしないパスカルのキーワード "BEGIN" にこれを試してみよう。 as_lower_d ディレクティブはこれを単純にしてくれる:

    r = as_lower_d["begin"];
Primitive arguments

賢明な読者はお気づきだろうが、我々は str_p の内部の "begin" を明示的にラップしなかった。 いつでも適切なときに、ディレクティブは charintwchar_tchar const*wchar_t const* などのプリミティブな型を許すことができる。例えば:

as_lower_d["hello"] // as_lower_d[str_p("hello")] と等価
as_lower_d
['x'] // as_lower_d[ch_p('x')] と等価

longest_d

Spirit パーサコンパイラでは、選択肢は短絡される(演算子を参照)。 時として、これは望まれている動作ではない。 longest_d ディレクティブは、パーサがこのディレクティブの内側に囲まれた選択肢を短絡しないよう指示する。 しかしその替わり、パーサはすべての可能な選択しを試し、入力ストリームの最も長い部分にマッチしたものを選ぶ。

まだ問題がある。つまり、入力 "123.456" は小数点の前までに整数として部分的一致するだろうが、これは望んでいる動作ではない。 ここでの解決策は、実数と整数に共通するプリフィクスを整理することによって曖昧性を解決するか、 それが不可能かあるいは望まないなら、 longest_d ディレクティブを使うことだ:

    number = longest_d[ integer | real ];

shortest_d

longest_d ディレクティブの逆である。

多重選択

longest_dshortest_d ディレクティブは二つ以上の選択肢を受け付けることができる。例えば:

longest[ a | b | c ];
shortest
[ a | b | c | d ];

limit_d

パーサの結果が与えられた最小値〜最大値の範囲(その値を含む)に抑制されるよう保証する。 もしそうでないならパーサは失敗し、一致なし(no-match)を返す。

使い方:

    limit_d(min, max)[expression]

このディレクティブは、 具体的なスカラー値を構文解析するパーサ(例えば数値パーサ)と接続するときに、とりわけ役に立つ。 現実的な例を示そう。 数値パーサは限定された文字数の数字(例えば、 0 〜 2 )のみを受け付けるように設定できるが、 これは結果をある範囲(例えば -1.0 〜 1.0)に制限するということを意味しない。 この設計は意図的なものだ。 もしそうしてしまったら、 "利用者は、利用しない機能の代価を払うべきではない" という Spirit の設計規則の土台を揺るがすことになりかねない。 最小値や最大値を、それが使われるかどうかに関わらず、数値パーサ自身に格納することもできた。そのためには非型テンプレートパラメータによって設定された静的な定数を使うことになるが、しかしそれは受け入れられなかった。なぜならその方法では、整数にしか適応することしかできないからである。 実数やユーザが定義した無限精度整数のような数についてはどうすればよいのだろう?

例えばHH:MM:SS という形式の時間を構文解析するなら次のようになる:

    uint_parser<int, 10, 2, 2> uint2_p;

    r = lexeme_d
        [
                limit_d(0u, 23u)[uint2_p] >> ':'    //  時 00 〜 23
            >>  limit_d(0u, 59u)[uint2_p] >> ':'    //  分 00 〜 59
            >>  limit_d(0u, 59u)[uint2_p]           //  秒 00 〜 59
        ];

min_limit_d

時々、上限だけ制約しないことが便利な場合がある。 これは一方向に無限な区間を許す。 min_limit_d ディレクティブはパーサの結果が最小値より小さくならないことを保証する。 もしそうでないなら、パーサは失敗し、一致なしを返す。

使い方:

    min_limit_d(min)[expression]

、日付が 1900 以下でないことを保証する

    min_limit_d(1900u)[int_p]

max_limit_d

min_limit_d の逆。そのため、 limit_d は以下と等しくなる:

    min_limit_d(min)[max_limit_d(max)[p]]


このドキュメントの対象: Boost Version 1.30.0
最新版ドキュメント(英語)