| ディレクティブ |
![]() |
![]() |
![]() |
パーサディレクティブは次の形式を持つ: directive[expression]
ディレクティブはその内側の式の振る舞いを修正する。本質的にはそれを '修飾' する。 フレームワークはいくつかのディレクティブをあらかじめ定義している。 フレームワークの利用者は必要に応じて独自のディレクティブを自由に定義できる。 どうやって定義するかという話は後で述べることにして、この段階では 定義済みディレクティブのみ扱うことにしよう。
空白のスキップを停止する。字句レベルの構文解析では、パーサは空白および空白と見なされるものをすべて無視する。 ここでいう空白には、パーサの 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['X'] は決して成功しない。 なぜならこのパーサは as_lower_d ディレクティブが絶対に提供しないはずの大文字の 'X' を期待しているからである。 |
例えば、パスカルでは、キーワードと識別子は大文字小文字で区別されない。 パスカルは識別子やキーワードにおいては文字の大小を無視する。 従ってパスカルの識別子 Id 、 ID および id はは同じものである。 大文字小文字の区別をしないディレクティブを用いない場合、これを認識するルールの定義は厄介だ:
r = str_p("id") | "Id" | "iD" | "ID";
さて、大文字小文字の区別をしないパスカルのキーワード "BEGIN" にこれを試してみよう。 as_lower_d ディレクティブはこれを単純にしてくれる:
r = as_lower_d["begin"];
賢明な読者はお気づきだろうが、我々は str_p の内部の "begin" を明示的にラップしなかった。 いつでも適切なときに、ディレクティブは char 、 int 、 wchar_t 、 char const* 、 wchar_t const* などのプリミティブな型を許すことができる。例えば: as_lower_d["hello"]
// as_lower_d[str_p("hello")] と等価 |
Spirit パーサコンパイラでは、選択肢は短絡される(演算子を参照)。 時として、これは望まれている動作ではない。 longest_d ディレクティブは、パーサがこのディレクティブの内側に囲まれた選択肢を短絡しないよう指示する。 しかしその替わり、パーサはすべての可能な選択しを試し、入力ストリームの最も長い部分にマッチしたものを選ぶ。
まだ問題がある。つまり、入力 "123.456" は小数点の前までに整数として部分的一致するだろうが、これは望んでいる動作ではない。 ここでの解決策は、実数と整数に共通するプリフィクスを整理することによって曖昧性を解決するか、 それが不可能かあるいは望まないなら、 longest_d ディレクティブを使うことだ:
number = longest_d[ integer | real ];
longest_d ディレクティブの逆である。
longest_d と shortest_d ディレクティブは二つ以上の選択肢を受け付けることができる。例えば: longest[
a | b
| c ];
|
パーサの結果が与えられた最小値〜最大値の範囲(その値を含む)に抑制されるよう保証する。 もしそうでないならパーサは失敗し、一致なし(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)[expression]
例、日付が 1900 以下でないことを保証する
min_limit_d(1900u)[int_p]
min_limit_d の逆。そのため、 limit_d は以下と等しくなる:
min_limit_d(min)[max_limit_d(max)[p]]
![]() |
![]() |
![]() |
Copyright © 1998-2003 Joel de Guzman
Permission to copy, use, modify, sell and distribute this document
is granted provided this copyright notice appears in all copies. This document
is provided "as is" without express or implied warranty, and with
no claim as to its suitability for any purpose.
Japanese Translation Copyright © 2003 Kent.N
オリジナルの、及びこの著作権表示が全ての複製の中に現れる限り、この文書の複製、利用、変更、販売そして配布を認める。このドキュメントは「あるがまま」に提供されており、いかなる明示的、暗黙的保証も行わない。また、いかなる目的に対しても、その利用が適していることを関知しない。
このドキュメントの対象: Boost Version 1.30.0
最新版ドキュメント(英語)