|
||||
File indexing completed on 2025-01-31 10:02:08
0001 /*============================================================================= 0002 Copyright (c) 2002-2003 Hartmut Kaiser 0003 http://spirit.sourceforge.net/ 0004 0005 Distributed under the Boost Software License, Version 1.0. (See accompanying 0006 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 0007 =============================================================================*/ 0008 #ifndef BOOST_SPIRIT_LISTS_HPP 0009 #define BOOST_SPIRIT_LISTS_HPP 0010 0011 /////////////////////////////////////////////////////////////////////////////// 0012 #include <boost/config.hpp> 0013 #include <boost/spirit/home/classic/namespace.hpp> 0014 #include <boost/spirit/home/classic/meta/as_parser.hpp> 0015 #include <boost/spirit/home/classic/core/parser.hpp> 0016 #include <boost/spirit/home/classic/core/composite/composite.hpp> 0017 0018 #include <boost/spirit/home/classic/utility/lists_fwd.hpp> 0019 #include <boost/spirit/home/classic/utility/impl/lists.ipp> 0020 0021 /////////////////////////////////////////////////////////////////////////////// 0022 namespace boost { namespace spirit { 0023 0024 BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN 0025 0026 /////////////////////////////////////////////////////////////////////////////// 0027 // 0028 // list_parser class 0029 // 0030 // List parsers allow to parse constructs like 0031 // 0032 // item >> *(delim >> item) 0033 // 0034 // where 'item' is an auxiliary expression to parse and 'delim' is an 0035 // auxiliary delimiter to parse. 0036 // 0037 // The list_parser class also can match an optional closing delimiter 0038 // represented by the 'end' parser at the end of the list: 0039 // 0040 // item >> *(delim >> item) >> !end. 0041 // 0042 // If ItemT is an action_parser_category type (parser with an attached 0043 // semantic action) we have to do something special. This happens, if the 0044 // user wrote something like: 0045 // 0046 // list_p(item[f], delim) 0047 // 0048 // where 'item' is the parser matching one item of the list sequence and 0049 // 'f' is a functor to be called after matching one item. If we would do 0050 // nothing, the resulting code would parse the sequence as follows: 0051 // 0052 // (item[f] - delim) >> *(delim >> (item[f] - delim)) 0053 // 0054 // what in most cases is not what the user expects. 0055 // (If this _is_ what you've expected, then please use one of the list_p 0056 // generator functions 'direct()', which will inhibit re-attaching 0057 // the actor to the item parser). 0058 // 0059 // To make the list parser behave as expected: 0060 // 0061 // (item - delim)[f] >> *(delim >> (item - delim)[f]) 0062 // 0063 // the actor attached to the 'item' parser has to be re-attached to the 0064 // *(item - delim) parser construct, which will make the resulting list 0065 // parser 'do the right thing'. 0066 // 0067 // Additionally special care must be taken, if the item parser is a 0068 // unary_parser_category type parser as 0069 // 0070 // list_p(*anychar_p, ',') 0071 // 0072 // which without any refactoring would result in 0073 // 0074 // (*anychar_p - ch_p(',')) 0075 // >> *( ch_p(',') >> (*anychar_p - ch_p(',')) ) 0076 // 0077 // and will not give the expected result (the first *anychar_p will eat up 0078 // all the input up to the end of the input stream). So we have to 0079 // refactor this into: 0080 // 0081 // *(anychar_p - ch_p(',')) 0082 // >> *( ch_p(',') >> *(anychar_p - ch_p(',')) ) 0083 // 0084 // what will give the correct result. 0085 // 0086 // The case, where the item parser is a combination of the two mentioned 0087 // problems (i.e. the item parser is a unary parser with an attached 0088 // action), is handled accordingly too: 0089 // 0090 // list_p((*anychar_p)[f], ',') 0091 // 0092 // will be parsed as expected: 0093 // 0094 // (*(anychar_p - ch_p(',')))[f] 0095 // >> *( ch_p(',') >> (*(anychar_p - ch_p(',')))[f] ). 0096 // 0097 /////////////////////////////////////////////////////////////////////////////// 0098 template < 0099 typename ItemT, typename DelimT, typename EndT, typename CategoryT 0100 > 0101 struct list_parser : 0102 public parser<list_parser<ItemT, DelimT, EndT, CategoryT> > { 0103 0104 typedef list_parser<ItemT, DelimT, EndT, CategoryT> self_t; 0105 typedef CategoryT parser_category_t; 0106 0107 list_parser(ItemT const &item_, DelimT const &delim_, 0108 EndT const& end_ = no_list_endtoken()) 0109 : item(item_), delim(delim_), end(end_) 0110 {} 0111 0112 template <typename ScannerT> 0113 typename parser_result<self_t, ScannerT>::type 0114 parse(ScannerT const& scan) const 0115 { 0116 return impl::list_parser_type<CategoryT> 0117 ::parse(scan, *this, item, delim, end); 0118 } 0119 0120 private: 0121 typename as_parser<ItemT>::type::embed_t item; 0122 typename as_parser<DelimT>::type::embed_t delim; 0123 typename as_parser<EndT>::type::embed_t end; 0124 }; 0125 0126 /////////////////////////////////////////////////////////////////////////////// 0127 // 0128 // List parser generator template 0129 // 0130 // This is a helper for generating a correct list_parser<> from 0131 // auxiliary parameters. There are the following types supported as 0132 // parameters yet: parsers, single characters and strings (see 0133 // as_parser<> in meta/as_parser.hpp). 0134 // 0135 // The list_parser_gen by itself can be used for parsing comma separated 0136 // lists without item formatting: 0137 // 0138 // list_p.parse(...) 0139 // matches any comma separated list. 0140 // 0141 // If list_p is used with one parameter, this parameter is used to match 0142 // the delimiter: 0143 // 0144 // list_p(';').parse(...) 0145 // matches any semicolon separated list. 0146 // 0147 // If list_p is used with two parameters, the first parameter is used to 0148 // match the items and the second parameter matches the delimiters: 0149 // 0150 // list_p(uint_p, ',').parse(...) 0151 // matches comma separated unsigned integers. 0152 // 0153 // If list_p is used with three parameters, the first parameter is used 0154 // to match the items, the second one is used to match the delimiters and 0155 // the third one is used to match an optional ending token sequence: 0156 // 0157 // list_p(real_p, ';', eol_p).parse(...) 0158 // matches a semicolon separated list of real numbers optionally 0159 // followed by an end of line. 0160 // 0161 // The list_p in the previous examples denotes the predefined parser 0162 // generator, which should be used to define list parsers (see below). 0163 // 0164 /////////////////////////////////////////////////////////////////////////////// 0165 0166 template <typename CharT = char> 0167 struct list_parser_gen : 0168 public list_parser<kleene_star<anychar_parser>, chlit<CharT> > 0169 { 0170 typedef list_parser_gen<CharT> self_t; 0171 0172 // construct the list_parser_gen object as an list parser for comma separated 0173 // lists without item formatting. 0174 list_parser_gen() 0175 : list_parser<kleene_star<anychar_parser>, chlit<CharT> > 0176 (*anychar_p, chlit<CharT>(',')) 0177 {} 0178 0179 // The following generator functions should be used under normal circumstances. 0180 // (the operator()(...) functions) 0181 0182 // Generic generator functions for creation of concrete list parsers, which 0183 // support 'normal' syntax: 0184 // 0185 // item >> *(delim >> item) 0186 // 0187 // If item isn't given, everything between two delimiters is matched. 0188 0189 template<typename DelimT> 0190 list_parser< 0191 kleene_star<anychar_parser>, 0192 typename as_parser<DelimT>::type, 0193 no_list_endtoken, 0194 unary_parser_category // there is no action to re-attach 0195 > 0196 operator()(DelimT const &delim_) const 0197 { 0198 typedef kleene_star<anychar_parser> item_t; 0199 typedef typename as_parser<DelimT>::type delim_t; 0200 0201 typedef 0202 list_parser<item_t, delim_t, no_list_endtoken, unary_parser_category> 0203 return_t; 0204 0205 return return_t(*anychar_p, as_parser<DelimT>::convert(delim_)); 0206 } 0207 0208 template<typename ItemT, typename DelimT> 0209 list_parser< 0210 typename as_parser<ItemT>::type, 0211 typename as_parser<DelimT>::type, 0212 no_list_endtoken, 0213 typename as_parser<ItemT>::type::parser_category_t 0214 > 0215 operator()(ItemT const &item_, DelimT const &delim_) const 0216 { 0217 typedef typename as_parser<ItemT>::type item_t; 0218 typedef typename as_parser<DelimT>::type delim_t; 0219 typedef list_parser<item_t, delim_t, no_list_endtoken, 0220 BOOST_DEDUCED_TYPENAME item_t::parser_category_t> 0221 return_t; 0222 0223 return return_t( 0224 as_parser<ItemT>::convert(item_), 0225 as_parser<DelimT>::convert(delim_) 0226 ); 0227 } 0228 0229 // Generic generator function for creation of concrete list parsers, which 0230 // support 'extended' syntax: 0231 // 0232 // item >> *(delim >> item) >> !end 0233 0234 template<typename ItemT, typename DelimT, typename EndT> 0235 list_parser< 0236 typename as_parser<ItemT>::type, 0237 typename as_parser<DelimT>::type, 0238 typename as_parser<EndT>::type, 0239 typename as_parser<ItemT>::type::parser_category_t 0240 > 0241 operator()( 0242 ItemT const &item_, DelimT const &delim_, EndT const &end_) const 0243 { 0244 typedef typename as_parser<ItemT>::type item_t; 0245 typedef typename as_parser<DelimT>::type delim_t; 0246 typedef typename as_parser<EndT>::type end_t; 0247 0248 typedef list_parser<item_t, delim_t, end_t, 0249 BOOST_DEDUCED_TYPENAME item_t::parser_category_t> 0250 return_t; 0251 0252 return return_t( 0253 as_parser<ItemT>::convert(item_), 0254 as_parser<DelimT>::convert(delim_), 0255 as_parser<EndT>::convert(end_) 0256 ); 0257 } 0258 0259 // The following functions should be used, if the 'item' parser has an attached 0260 // semantic action or is a unary_parser_category type parser and the structure 0261 // of the resulting list parser should _not_ be refactored during parser 0262 // construction (see comment above). 0263 0264 // Generic generator function for creation of concrete list parsers, which 0265 // support 'normal' syntax: 0266 // 0267 // item >> *(delim >> item) 0268 0269 template<typename ItemT, typename DelimT> 0270 list_parser< 0271 typename as_parser<ItemT>::type, 0272 typename as_parser<DelimT>::type, 0273 no_list_endtoken, 0274 plain_parser_category // inhibit action re-attachment 0275 > 0276 direct(ItemT const &item_, DelimT const &delim_) const 0277 { 0278 typedef typename as_parser<ItemT>::type item_t; 0279 typedef typename as_parser<DelimT>::type delim_t; 0280 typedef list_parser<item_t, delim_t, no_list_endtoken, 0281 plain_parser_category> 0282 return_t; 0283 0284 return return_t( 0285 as_parser<ItemT>::convert(item_), 0286 as_parser<DelimT>::convert(delim_) 0287 ); 0288 } 0289 0290 // Generic generator function for creation of concrete list parsers, which 0291 // support 'extended' syntax: 0292 // 0293 // item >> *(delim >> item) >> !end 0294 0295 template<typename ItemT, typename DelimT, typename EndT> 0296 list_parser< 0297 typename as_parser<ItemT>::type, 0298 typename as_parser<DelimT>::type, 0299 typename as_parser<EndT>::type, 0300 plain_parser_category // inhibit action re-attachment 0301 > 0302 direct( 0303 ItemT const &item_, DelimT const &delim_, EndT const &end_) const 0304 { 0305 typedef typename as_parser<ItemT>::type item_t; 0306 typedef typename as_parser<DelimT>::type delim_t; 0307 typedef typename as_parser<EndT>::type end_t; 0308 0309 typedef 0310 list_parser<item_t, delim_t, end_t, plain_parser_category> 0311 return_t; 0312 0313 return return_t( 0314 as_parser<ItemT>::convert(item_), 0315 as_parser<DelimT>::convert(delim_), 0316 as_parser<EndT>::convert(end_) 0317 ); 0318 } 0319 }; 0320 0321 /////////////////////////////////////////////////////////////////////////////// 0322 // 0323 // Predefined list parser generator 0324 // 0325 // The list_p parser generator can be used 0326 // - by itself for parsing comma separated lists without item formatting 0327 // or 0328 // - for generating list parsers with auxiliary parser parameters 0329 // for the 'item', 'delim' and 'end' subsequences. 0330 // (see comment above) 0331 // 0332 /////////////////////////////////////////////////////////////////////////////// 0333 const list_parser_gen<> list_p = list_parser_gen<>(); 0334 0335 /////////////////////////////////////////////////////////////////////////////// 0336 BOOST_SPIRIT_CLASSIC_NAMESPACE_END 0337 0338 }} // namespace BOOST_SPIRIT_CLASSIC_NS 0339 0340 #endif
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |