| リストパーサ |
![]() |
![]() |
![]() |
リストパーサは特殊な定義済みパーサ生成子オブジェクトである list_p によって生成される。 このオブジェクトは次のようなタイプのリスト構造を認識するパーサを生成する。
item >> *(delimiter >> item) >> !end
ここで item は式、 delimiter は区切り子(delimiter)、そして end は省略可能な閉じる式である。 一見して明らかなように、 list_p によって生成されたパーサは空のリストを認識できない。 すなわち、パーサがマッチ成功を返すためには、入力ストリーム中に少なくとも一つの項目を見つけなければならない。 もし空のリストにもマッチさせたい場合は operator! を用いて list_p を省略可能にできる。 このユーティリティパーサがいかに便利であるかを示すため、カンマで区切られた C/C++ 文字列を構文解析する例を挙げる。これは以下のように容易に構成できる:
rule<> list_of_c_strings_rule = list_p(confix_p('\"', *c_escape_char_p, '\"'), ',') ;
confix_p および c_escape_char_p パーサジェネレータについては ここ と ここ で述べている。
list_p パーサジェネレータオブジェクトは次の異なるタイプのリストパーサを生成するのに利用できる:
| リストパーサ | |
| list_p |
list_pは特殊な項目の書式化なしにカンマ区切りリストを構文解析する。 すなわち、二つのカンマの間のあらゆるものが item にマッチ、リストトークンの終端 end にはマッチしない。 |
| list_p(delimiter) |
指定された delimiter で区切られたリストを認識するリストパーサを生成する。 それらの間にあるあらゆるものを item として返し、リストトークンの終端 end にはマッチしない。 |
| list_p(item, delimiter) |
指定された delimiter で区切られたリストを認識しするリストパーサを生成する。 与えられた item パーサに基づいて項目をマッチし、リストトークンの終端 end にはマッチしない。 |
| list_p(item, delimiter, end) |
指定された delimiter で区切られたリストを認識しするリストパーサを生成する。 与えられた item パーサに基づいて項目をマッチし、 さらに省略可能な end 式を認識する。 |
list_p への全てのパラメータは、単一の文字、文字列を用いることが出来る。もしより複雑な構文解析ロジックが必要ならば任意のパーサを用いることも出来る。これらは全て構文解析の成功に必要な対応するパーサ型に自動的に変換される。
item パラメータが action_parser_category 型(セマンティックアクションが接続されたパーサ)であれば、特別な処理を施さなければならない。 もしユーザが次のようなコードを書いたとする:
list_p(item[func], delim)
ここで item はリストシーケンスのある一つの項目にマッチするパーサであり、 また func はある一つの項目にマッチした後に呼ばれるファンクタである。 もし特に何もしないのであれば、結果のコードはこのシーケンスを次のように構文解析する:
(item[func] - delim) >> *(delim >> (item[func] - delim))
多くの場合起こることはユーザが期待していることではない (もしこれが期待していることなら、 list_p ジェネレータ関数の一つである direct() を利用してほしい。 これは item パーサのリファクタリングを禁止する)。 リストパーサを期待通りに振る舞わせるには次のようにする:
(item - delim)[func] >> *(delim >> (item - delim)[func])
item パーサに接続されたオブジェクト(actor)は、結果のリストパーサが ’正しく動作する’ ように (item - delim) パーサの構築に際して再接続されなければならい。 このリファクタリングはリファクタリングパーサの助けによって為される。 もし item パーサが例えば次のような unary_parser_category 型のパーサであれば、さらに特殊な処置を施す必要がある:
list_p(*anychar_p, ',')
何のリファクタリングも施さなければ、その結果は
(*anychar_p - ch_p(',')) >> *( ch_p(',') >> (*anychar_p - ch_p(',')) )
となって、期待された結果は得られない (最初の *anychar_p は入力ストリームの終端にいたるまでの全ての入力を食い尽くすだろう) 従って、これを次のようにリファクタリングしなければならない:
*(anychar_p - ch_p(',')) >> *( ch_p(',') >> *(anychar_p - ch_p(',')) )
得られるものは正しい結果である。
item パーサが想定される二つの問題の組み合わせである(すなわち、 item パーサが一引数のパーサであり、かつアクションが接続されている)場合も同様に扱われ:
list_p((*anychar_p)[func], ',')
期待されたとおりに構文解析される:
(*(anychar_p - ch_p(',')))[func] >> *( ch_p(',') >> (*(anychar_p - ch_p(',')))[func] )
必要なリファクタリングはリファクタリングパーサの助けを受けて実装されている。
| リストパーサのリファクタリングのまとめ | |
| 記述したコード: | リファクタリングされたコード: |
list_p(item,
delimiter) |
(item
- delimiter)
|
list_p(item[func],
delimiter) |
(item
- delimiter)[func]
|
list_p(*item,
delimiter) |
*(item
- delimiter)
|
list_p((*item)[func],
delimiter) |
(*(item
- delimiter))[func]
|
![]() |
![]() |
![]() |
Copyright © 2001-2002 Hartmut Kaiser
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
最新版ドキュメント(英語)