メインページ | ネームスペース一覧 | クラス階層 | 構成 | Directories | ファイル一覧 | ネームスペースメンバ | 構成メンバ | ファイルメンバ | 関連ページ

FISpirit.h

00001 #ifndef FISPIRIT_H
00002 #define FISPIRIT_H
00003 /** @File   boost::spirit を使うときに,
00004     パーサの実装ファイル(.cpp)だけでインクルードして使うヘッダ.
00005     FIPhraseParser と FISkipParserを定義する.
00006 */
00007 
00008 
00009 #include <Base/BaseUtility.h>
00010 #include <FileIO/FIDocNode.h>
00011 
00012 #if defined(__BORLANDC__)
00013 # pragma option push -pc
00014 # pragma warn -8026
00015 # pragma warn -8027
00016 #endif
00017 
00018 #if defined _MSC_VER && _MSC_VER <= 0x1200
00019 #pragma warning (disable:4761 4786 4096)
00020 #endif
00021 
00022 #include <boost/spirit/core.hpp>
00023 #include <boost/spirit/utility/chset.hpp>
00024 #include <boost/shared_ptr.hpp>
00025 
00026 #if defined(BOOST_MSVC) && (BOOST_MSVC <= 1300)
00027 #define BOOST_SPIRIT_IT_NS boost::spirit::impl
00028 #else
00029 #define BOOST_SPIRIT_IT_NS std
00030 #endif
00031 
00032 #undef BOOST_SPIRIT_SAFE_BOOL
00033 #if !defined(__BORLANDC__)
00034 #define BOOST_SPIRIT_SAFE_BOOL(cond)  ((cond) ? &boost::spirit::impl::dummy::nonnull : 0)
00035 #else
00036 #define BOOST_SPIRIT_SAFE_BOOL(cond)  (cond)
00037 #endif
00038 
00039 namespace Spr{;
00040 
00041 /// FISpiritで使用する入力文字列のイタレータの型
00042 typedef const char* FIIteratorT;
00043 
00044 
00045 
00046 //----------------------------------------------------------------------------
00047 //  アクションによる,パースツリーを作らないパーサ
00048 
00049 /// スキャナを固定するためのスキップ用パーサ.他のパーサを代入できる
00050 struct FISkipParser: boost::spirit::parser<FISkipParser>{
00051     typedef FISkipParser          self_t;
00052     typedef FISkipParser const&   embed_t;
00053     typedef boost::spirit::skip_parser_iteration_policy<FISkipParser> iter_policy_t;
00054     typedef boost::spirit::scanner_policies<iter_policy_t> scanner_policies_t;
00055     /// 本文(Phrase)のためのスキャナ型
00056     typedef boost::spirit::scanner<FIIteratorT, scanner_policies_t> PhraseScannerT;
00057 
00058     typedef boost::spirit::scanner_policies<
00059         boost::spirit::no_skipper_iteration_policy<PhraseScannerT::iteration_policy_t>,
00060         PhraseScannerT::match_policy_t,
00061         PhraseScannerT::action_policy_t
00062     > policies_t;
00063     /// スペース読み飛ばし(Skipper)のためのスキャナ型
00064     typedef boost::spirit::scanner<PhraseScannerT::iterator_t, policies_t> SkipperScannerT;
00065 
00066     //  SkipperScannerTでパーサを定義していく.
00067     typedef boost::spirit::match_result<SkipperScannerT, boost::spirit::parser_context::context_linker_t::attr_t>::type Result;
00068     FISkipParser(){}
00069     FISkipParser(const FISkipParser& wp): ptr_(wp.ptr_? wp.ptr_->clone() : NULL){}
00070     /// Scannerがテンプレートのパーサを受け取って,コンクリートなパーサに変換して保存.
00071     template <class T>
00072     FISkipParser(const T& p){
00073         ptr_.reset(new impl::concrete_parser<T, SkipperScannerT, Result>(p));
00074     }
00075     /// Scannerがテンプレートのパーサを受け取って,コンクリートなパーサに変換して保存.
00076     template <class T>
00077     FISkipParser& operator=(const T& p){
00078         ptr_.reset(new boost::spirit::impl::concrete_parser<T, SkipperScannerT, Result>(p));
00079         return *this;
00080     }
00081     /// スキップのためのパース
00082     Result parse(const SkipperScannerT& scan)const{
00083         if (ptr_) return ptr_->do_parse_virtual(scan);
00084         else return scan.no_match();
00085     }
00086     /// コンクリートなパーサ
00087     boost::scoped_ptr<boost::spirit::impl::abstract_parser<SkipperScannerT, Result> > ptr_;
00088 };
00089 
00090 /// スキャナを固定するための本文用パーサ.他のパーサを代入できる
00091 struct FIPhraseParser: public boost::spirit::rule<FISkipParser::PhraseScannerT>{
00092     typedef boost::spirit::rule<FISkipParser::PhraseScannerT> base_type;
00093     FIPhraseParser(){}
00094     template <typename ParserT>
00095         FIPhraseParser(ParserT const& p){ *this=p; }
00096     template <typename ParserT>
00097     FIPhraseParser& operator=(ParserT const& p){
00098         base_type::operator=(p);
00099         return *this;
00100     }
00101     FIPhraseParser& operator=(FIPhraseParser const& p){
00102         base_type::operator=(p);
00103         return *this;
00104     }
00105 
00106 };
00107 
00108 
00109 
00110 
00111 //----------------------------------------------------------------------------
00112 //  パースツリーのためのクラス
00113 
00114 template <typename ValueT = boost::spirit::nil_t>
00115 class FIPTNodeValData {
00116 public:
00117     typedef typename BOOST_SPIRIT_IT_NS::iterator_traits<FIIteratorT>::value_type value_type;
00118     typedef std::vector<value_type> container_t;
00119     typedef typename container_t::iterator iterator_t;
00120     typedef typename container_t::const_iterator const_iterator_t;
00121 
00122 private:
00123     container_t text;
00124     bool is_root_;
00125     boost::spirit::parser_id parser_id_;
00126 //    ValueT value_;
00127 
00128 public:
00129     FIPTNodeValData() : text(), is_root_(false){}
00130     FIPTNodeValData(FIIteratorT const& _first, FIIteratorT const& _last)
00131         : text(_first, _last), is_root_(false){}
00132     FIPTNodeValData(FIIteratorT const& _first, FIIteratorT const& _last, bool is_r, boost::spirit::parser_id i)
00133         : text(_first, _last), is_root_(is_r), parser_id_(i){}
00134     void swap(FIPTNodeValData& x){
00135         cp_swap(text, x.text);
00136         cp_swap(is_root_, x.is_root_);
00137         cp_swap(parser_id_, x.parser_id_);
00138         cp_swap(value_, x.value_);
00139     }
00140     typename container_t::iterator begin(){ return text.begin(); }
00141     typename container_t::const_iterator begin() const{ return text.begin(); }
00142     typename container_t::iterator end(){ return text.end(); }
00143     typename container_t::const_iterator end() const{ return text.end(); }
00144     bool is_root() const{ return is_root_; }
00145     void is_root(bool b){ is_root_ = b; }
00146     boost::spirit::parser_id id() const { return parser_id_; }
00147     void id(boost::spirit::parser_id r){ parser_id_ = r; }
00148     ValueT const& value() const { return value_; }
00149     void value(ValueT const& v) { value_ = v; }
00150 };
00151 
00152 
00153 //----------------------------------------------------------------------------
00154 template <typename AttrT = boost::spirit::nil_t> struct FIPTMatch;
00155 
00156 template <typename T>
00157 struct FIPTMatchAttr
00158 {
00159     template <typename MatchT>
00160     static T get(MatchT const& m) { return T(m.value()); }
00161     static T get(FIPTMatch<boost::spirit::nil_t> const& /*m*/) { return T(); }
00162     static T get_default() { return T(); }
00163 };
00164 
00165 //////////////////////////////////
00166 template <>
00167 struct FIPTMatchAttr<boost::spirit::nil_t>{
00168     template <typename MatchT>
00169     static boost::spirit::nil_t get(MatchT const& /*m*/) { return boost::spirit::nil_t(); }
00170     static boost::spirit::nil_t get_default() { return boost::spirit::nil_t(); }
00171 };
00172 
00173 template <typename T>
00174 inline void cp_swap(T& t1, T& t2) {
00175     using std::swap;
00176     using boost::swap;
00177     swap(t1, t2);
00178 }
00179 
00180 struct FIPTNode{
00181     typedef std::vector<FIPTNode> container_t;
00182     container_t children;
00183     FIString text;
00184     boost::spirit::parser_id id;
00185 
00186     FIPTNode(){}
00187     template <typename ValueT>
00188     FIPTNode(const FIPTNodeValData<ValueT>& val){
00189         id = val.id();
00190         if (!val.is_root()){
00191             text.assign(val.begin(), val.end());
00192         }
00193 //      std::cout << "FIPTNode<" << id.to_long() << "> (" << text << ")" << std::endl;
00194     }
00195     void Print(std::ostream& os) const;
00196     void GetTextR(FIString& t) const;
00197 };
00198 
00199 #if defined _MSC_VER && _MSC_VER <= 1200
00200 template <typename AttrT = boost::spirit::nil_t>
00201 #else
00202 template <typename AttrT>
00203 #endif
00204 struct FIPTMatch{
00205     typedef AttrT attr_t;
00206     typedef typename boost::call_traits<AttrT>::param_type      param_type;
00207     typedef typename boost::call_traits<AttrT>::reference       reference;
00208     typedef typename boost::call_traits<AttrT>::const_reference const_reference;
00209     typedef FIPTNode tree_t;
00210     typedef std::vector<tree_t> container_t;
00211     typedef FIPTNodeValData<AttrT> parse_node_t;
00212 
00213     int len;
00214     mutable container_t trees;
00215     AttrT   val;
00216     
00217     FIPTMatch():len(-1), trees(), val(FIPTMatchAttr<AttrT>::get_default()) {}
00218     explicit FIPTMatch(unsigned length): len(length), trees(), val(FIPTMatchAttr<AttrT>::get_default()){}
00219     FIPTMatch(unsigned length, parse_node_t const& n):len(length), trees(), val(FIPTMatchAttr<AttrT>::get_default()){
00220         trees.push_back(FIPTNode(n));
00221     }
00222     FIPTMatch(unsigned length, param_type val_, parse_node_t const& n):len(length), trees(), val(val_){
00223         trees.push_back(FIPTNode(n));
00224     }
00225     template <typename T2>
00226     FIPTMatch(FIPTMatch<T2> const& other):len(other.length()), trees(), val(FIPTMatchAttr<AttrT>::get(other)){
00227         cp_swap(trees, other.trees);
00228     }
00229     FIPTMatch(FIPTMatch const& x) : len(x.len), trees(), val(FIPTMatchAttr<AttrT>::get_default()){
00230         // use auto_ptr like ownership for the trees data member
00231         cp_swap(trees, x.trees);
00232     }
00233 
00234     template <typename T2>
00235     FIPTMatch& operator=(FIPTMatch<T2> const& other) {
00236         len = other.length();
00237         val = impl::FIPTMatchAttr<T>::get(other);
00238         cp_swap(trees, other.trees);
00239         return *this;
00240     }
00241     FIPTMatch& operator=(FIPTMatch const& x){
00242         FIPTMatch tmp(x);
00243         this->swap(tmp);
00244         return *this;
00245     }
00246 
00247     void swap(FIPTMatch& x){
00248         cp_swap(len, x.len);
00249         cp_swap(trees, x.trees);
00250     }
00251 
00252     operator boost::spirit::impl::safe_bool() const { 
00253         return BOOST_SPIRIT_SAFE_BOOL(len >= 0); 
00254     }
00255 
00256     bool operator!() const { return len < 0; }
00257 
00258     int length() const              { return len; }
00259     const_reference value() const   { return val; }
00260     reference value()               { return val; }
00261 
00262     template <typename MatchT>
00263     void concat(MatchT const& other){
00264         BOOST_SPIRIT_ASSERT(*this && other);
00265         len += other.length();
00266         std::copy(other.trees.begin(), other.trees.end(),
00267             std::back_insert_iterator<FIPTMatch::container_t>(trees));
00268     }
00269 
00270 };
00271 
00272 
00273 //  for making parse tree
00274 struct FIPTMatchPolicy{
00275     template <typename T>
00276     struct result { typedef FIPTMatch<T> type; };
00277 
00278     const FIPTMatch<boost::spirit::nil_t>
00279     no_match() const { return FIPTMatch<boost::spirit::nil_t>(); }
00280 
00281     const FIPTMatch<boost::spirit::nil_t>
00282     empty_match() const { return FIPTMatch<boost::spirit::nil_t>(0); }
00283 
00284     template <typename AttrT>
00285     FIPTMatch<AttrT>
00286     create_match(unsigned length, AttrT const& val, FIIteratorT const& first, FIIteratorT const& last) const{
00287         return FIPTMatch<AttrT>(length, val, create_node(length, val, first, last, true));
00288     }
00289     template <typename AttrT>
00290     FIPTNodeValData<AttrT> create_node(int length, AttrT const& val, FIIteratorT first, FIIteratorT last, bool leaf_node) const{
00291         if (leaf_node){
00292             return FIPTNodeValData<AttrT>(first, last);
00293         }else{
00294             return FIPTNodeValData<AttrT>(NULL, NULL);
00295         }
00296     }
00297 
00298     template <typename MatchT>
00299     void
00300     group_match(MatchT& m, boost::spirit::parser_id const& id,
00301         FIIteratorT const& first, FIIteratorT const& last) const {
00302         if (!m) return;
00303         FIPTNodeValData<MatchT::attr_t> newVal(first, last, true, id);
00304         MatchT newmatch(m.length(), newVal);
00305         std::swap(newmatch.trees.begin()->children, m.trees);
00306         m = newmatch;
00307     }
00308 
00309     template <typename Match1T, typename Match2T>
00310     void
00311     concat_match(Match1T& l, Match2T const& r) const{
00312         l.concat(r);
00313     }
00314 };
00315 
00316 /// スキャナを固定するためのツリー用スキップパーサ.他のパーサを代入できる
00317 struct FIPTSkipParser: boost::spirit::parser< FIPTSkipParser >{
00318     typedef FIPTSkipParser          self_t;
00319     typedef FIPTSkipParser const&   embed_t;
00320     typedef boost::spirit::skip_parser_iteration_policy< FIPTSkipParser >
00321         iter_policy_t;
00322     typedef boost::spirit::scanner_policies<
00323         iter_policy_t, FIPTMatchPolicy
00324     > scanner_policies_t;
00325     /// 本文(Phrase)のためのスキャナ型
00326     typedef boost::spirit::scanner<FIIteratorT, scanner_policies_t> PhraseScannerT;
00327 
00328     typedef boost::spirit::scanner_policies<
00329         boost::spirit::no_skipper_iteration_policy<PhraseScannerT::iteration_policy_t>,
00330         PhraseScannerT::match_policy_t,
00331         PhraseScannerT::action_policy_t
00332     > policies_t;
00333     /// スペース読み飛ばし(Skipper)のためのスキャナ型
00334     typedef boost::spirit::scanner<FIIteratorT, policies_t> SkipperScannerT;
00335 
00336     //  SkipperScannerTでパーサを定義していく.
00337     typedef boost::spirit::match_result<SkipperScannerT, boost::spirit::parser_context::context_linker_t::attr_t>::type Result;
00338     FIPTSkipParser(){}
00339     FIPTSkipParser(const FIPTSkipParser& wp): ptr_(wp.ptr_? wp.ptr_->clone() : NULL){}
00340     /// Scannerがテンプレートのパーサを受け取って,コンクリートなパーサに変換して保存.
00341     template <class T>
00342     FIPTSkipParser(const T& p){
00343         ptr_.reset(new boost::spirit::impl::concrete_parser<T, SkipperScannerT, Result>(p));
00344     }
00345     /// Scannerがテンプレートのパーサを受け取って,コンクリートなパーサに変換して保存.
00346     template <class T>
00347     FIPTSkipParser& operator=(const T& p){
00348         ptr_.reset(new boost::spirit::impl::concrete_parser<T, SkipperScannerT, Result>(p));
00349         return *this;
00350     }
00351     /// スキップのためのパース
00352     Result parse(const SkipperScannerT& scan)const{
00353         if (ptr_) return ptr_->do_parse_virtual(scan);
00354         else return scan.no_match();
00355     }
00356     /// コンクリートなパーサ
00357     boost::scoped_ptr<boost::spirit::impl::abstract_parser<SkipperScannerT, Result> > ptr_;
00358 };
00359 
00360 /// ツリー用本文パーサ.他のパーサを代入できる
00361 struct FIPTPhraseParser: public boost::spirit::parser< FIPTPhraseParser >{
00362     typedef FIPTPhraseParser          self_t;
00363     typedef FIPTPhraseParser const&   embed_t;
00364 
00365     /// 本文(Phrase)のためのスキャナ型
00366     typedef FIPTSkipParser::PhraseScannerT PhraseScannerT;
00367     typedef boost::spirit::match_result<PhraseScannerT, boost::spirit::parser_context::context_linker_t::attr_t>::type Result;
00368 
00369     FIPTPhraseParser(){}
00370     FIPTPhraseParser(FIPTPhraseParser const& fp): ptr_(fp.ptr_? fp.ptr_->clone() : NULL){}
00371     template <typename ParserT>
00372     FIPTPhraseParser& operator=(ParserT const& p){
00373         ptr_.reset(new boost::spirit::impl::concrete_parser<ParserT, PhraseScannerT, Result>(p));
00374         return *this;
00375     }
00376     /// パース
00377     Result parse(const PhraseScannerT& scan)const{
00378         Result r;
00379         if (ptr_) r=ptr_->do_parse_virtual(scan);
00380         else r=scan.no_match();
00381         return r;
00382     }
00383     /// コンクリートなパーサ
00384     boost::scoped_ptr<boost::spirit::impl::abstract_parser<PhraseScannerT, Result> > ptr_;
00385 };
00386 
00387 extern int FIPTPhraseParserWithID_indent;
00388 
00389 template <class TagT>
00390 struct FIPTPhraseParserWithID: public boost::spirit::parser< FIPTPhraseParserWithID<TagT> >{
00391     typedef FIPTPhraseParserWithID<TagT>          self_t;
00392     typedef FIPTPhraseParserWithID<TagT> const&   embed_t;
00393 
00394     /// 本文(Phrase)のためのスキャナ型
00395     typedef FIPTSkipParser::PhraseScannerT PhraseScannerT;
00396     typedef boost::spirit::match_result<PhraseScannerT, boost::spirit::parser_context::context_linker_t::attr_t>::type Result;
00397 
00398     FIPTPhraseParserWithID(){}
00399     FIPTPhraseParserWithID(FIPTPhraseParserWithID const& fp): ptr_(fp.ptr_? fp.ptr_->clone() : NULL){}
00400     template <typename ParserT>
00401     FIPTPhraseParserWithID& operator=(ParserT const& p){
00402         ptr_.reset(new boost::spirit::impl::concrete_parser<ParserT, PhraseScannerT, Result>(p));
00403         return *this;
00404     }
00405     Result parse(const PhraseScannerT& scan)const{
00406 /*      int& w = FIPTPhraseParserWithID_indent;
00407         std::cout.width(0);
00408         std::cout << UTPadding(w) << "FIPTPP with ID " << TagT::id(*this).to_long() << std::endl;
00409         w += 2;
00410 */
00411         Result r;
00412 
00413         if (ptr_){
00414             FIIteratorT f = scan.first;
00415             r = ptr_->do_parse_virtual(scan);
00416             FIIteratorT l = scan.first;
00417             scan.group_match(r, TagT::id(*this), f, l);
00418         }else{
00419             r=scan.no_match();
00420         }
00421         
00422         /*
00423         w -= 2;
00424         std::cout.width(0);
00425         std::cout << UTPadding(w) << "-";
00426         if (!r) std::cout << "failed.";
00427         std::cout << std::endl;
00428 */
00429         return r;
00430     }
00431     /// コンクリートなパーサ
00432     boost::scoped_ptr<boost::spirit::impl::abstract_parser<PhraseScannerT, Result> > ptr_;
00433 };
00434 
00435 struct FIPTInfo {
00436     typedef FIPTPhraseParser ParserT;
00437     FIIteratorT   stop;
00438     bool        match;
00439     bool        full;
00440     unsigned    length;
00441     mutable FIPTMatch<ParserT>::container_t trees;
00442 
00443     FIPTInfo(): stop(), match(false), full(false), length(0), trees(){}
00444 
00445     FIPTInfo(FIPTInfo const& pi): stop(pi.stop), match(pi.match), full(pi.full), length(pi.length), trees(){
00446         using std::swap;
00447         using boost::swap;
00448         // use auto_ptr like ownership for the trees data member
00449         swap(trees, pi.trees);
00450     }
00451 
00452     FIPTInfo(FIIteratorT stop_, bool match_, bool full_, unsigned length_,
00453         FIPTMatch<ParserT>::container_t trees_)
00454         :stop(stop_), match(match_), full(full_), length(length_), trees(){
00455         using std::swap;
00456         using boost::swap;
00457         // use auto_ptr like ownership for the trees data member
00458         swap(trees, trees_);
00459     }
00460 
00461     void Print(std::ostream& os) const;
00462 };
00463 
00464 FIPTInfo FIPTParse(FIIteratorT const& first_, FIIteratorT const& last,
00465     FIPTPhraseParser const&  p, FIPTSkipParser const& skip);
00466 
00467 }   //  namespace Spr
00468 
00469 
00470 #undef BOOST_SPIRIT_IT_NS
00471 
00472 #if defined(__BORLANDC__)
00473 # pragma option pop
00474 #endif
00475 
00476 #endif

Springheadに対してSun Apr 16 01:57:51 2006に生成されました。  doxygen 1.4.1