00001 #ifndef FISPIRIT_H
00002 #define FISPIRIT_H
00003
00004
00005
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
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
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
00064 typedef boost::spirit::scanner<PhraseScannerT::iterator_t, policies_t> SkipperScannerT;
00065
00066
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
00071 template <class T>
00072 FISkipParser(const T& p){
00073 ptr_.reset(new impl::concrete_parser<T, SkipperScannerT, Result>(p));
00074 }
00075
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
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& ) { 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& ) { 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
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
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
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
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
00334 typedef boost::spirit::scanner<FIIteratorT, policies_t> SkipperScannerT;
00335
00336
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
00341 template <class T>
00342 FIPTSkipParser(const T& p){
00343 ptr_.reset(new boost::spirit::impl::concrete_parser<T, SkipperScannerT, Result>(p));
00344 }
00345
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
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
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
00407
00408
00409
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
00424
00425
00426
00427
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
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
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 }
00468
00469
00470 #undef BOOST_SPIRIT_IT_NS
00471
00472 #if defined(__BORLANDC__)
00473 # pragma option pop
00474 #endif
00475
00476 #endif