1 /*============================================================================= 2 Copyright (c) 2002-2003 Joel de Guzman 3 Copyright (c) 2002-2003 Hartmut Kaiser 4 http://spirit.sourceforge.net/ 5 6 Distributed under the Boost Software License, Version 1.0. (See accompanying 7 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 8 =============================================================================*/ 9 #if !defined(BOOST_SPIRIT_SUBRULE_HPP) 10 #define BOOST_SPIRIT_SUBRULE_HPP 11 12 #include <boost/config.hpp> 13 #include <boost/static_assert.hpp> 14 15 #include <boost/spirit/home/classic/namespace.hpp> 16 #include <boost/spirit/home/classic/core/parser.hpp> 17 #include <boost/spirit/home/classic/core/non_terminal/parser_context.hpp> 18 19 #include <boost/spirit/home/classic/core/non_terminal/subrule_fwd.hpp> 20 #include <boost/spirit/home/classic/core/non_terminal/impl/subrule.ipp> 21 22 namespace boost { namespace spirit { 23 24 BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN 25 26 /////////////////////////////////////////////////////////////////////////// 27 // 28 // subrules_scanner class 29 // 30 /////////////////////////////////////////////////////////////////////////// 31 template <typename ScannerT, typename ListT> 32 struct subrules_scanner : public ScannerT 33 { 34 typedef ScannerT scanner_t; 35 typedef ListT list_t; 36 typedef subrules_scanner<ScannerT, ListT> self_t; 37 subrules_scannerboost::spirit::subrules_scanner38 subrules_scanner(ScannerT const& scan, ListT const& list_) 39 : ScannerT(scan), list(list_) {} 40 41 template <typename PoliciesT> 42 struct rebind_policies 43 { 44 typedef typename rebind_scanner_policies<ScannerT, PoliciesT>::type 45 rebind_scanner; 46 typedef subrules_scanner<rebind_scanner, ListT> type; 47 }; 48 49 template <typename PoliciesT> 50 subrules_scanner< 51 typename rebind_scanner_policies<ScannerT, PoliciesT>::type, 52 ListT> change_policiesboost::spirit::subrules_scanner53 change_policies(PoliciesT const& policies) const 54 { 55 typedef subrules_scanner< 56 BOOST_DEDUCED_TYPENAME 57 rebind_scanner_policies<ScannerT, PoliciesT>::type, 58 ListT> 59 subrules_scanner_t; 60 61 return subrules_scanner_t( 62 ScannerT::change_policies(policies), 63 list); 64 } 65 66 template <typename IteratorT> 67 struct rebind_iterator 68 { 69 typedef typename rebind_scanner_iterator<ScannerT, IteratorT>::type 70 rebind_scanner; 71 typedef subrules_scanner<rebind_scanner, ListT> type; 72 }; 73 74 template <typename IteratorT> 75 subrules_scanner< 76 typename rebind_scanner_iterator<ScannerT, IteratorT>::type, 77 ListT> change_iteratorboost::spirit::subrules_scanner78 change_iterator(IteratorT const& first, IteratorT const &last) const 79 { 80 typedef subrules_scanner< 81 BOOST_DEDUCED_TYPENAME 82 rebind_scanner_iterator<ScannerT, IteratorT>::type, 83 ListT> 84 subrules_scanner_t; 85 86 return subrules_scanner_t( 87 ScannerT::change_iterator(first, last), 88 list); 89 } 90 91 ListT const& list; 92 }; 93 94 /////////////////////////////////////////////////////////////////////////// 95 // 96 // subrule_scanner type computer class 97 // 98 // This computer ensures that the scanner will not be recursively 99 // instantiated if it's not needed. 100 // 101 /////////////////////////////////////////////////////////////////////////// 102 template <typename ScannerT, typename ListT> 103 struct subrules_scanner_finder 104 { 105 typedef subrules_scanner<ScannerT, ListT> type; 106 }; 107 108 template <typename ScannerT, typename ListT> 109 struct subrules_scanner_finder<subrules_scanner<ScannerT, ListT>, ListT> 110 { 111 typedef subrules_scanner<ScannerT, ListT> type; 112 }; 113 114 /////////////////////////////////////////////////////////////////////////// 115 // 116 // subrule_list class 117 // 118 /////////////////////////////////////////////////////////////////////////// 119 template <typename FirstT, typename RestT> 120 struct subrule_list : public parser<subrule_list<FirstT, RestT> > 121 { 122 typedef subrule_list<FirstT, RestT> self_t; 123 typedef FirstT first_t; 124 typedef RestT rest_t; 125 subrule_listboost::spirit::subrule_list126 subrule_list(FirstT const& first_, RestT const& rest_) 127 : first(first_), rest(rest_) {} 128 129 template <typename ScannerT> 130 struct result 131 { 132 typedef typename parser_result<FirstT, ScannerT>::type type; 133 }; 134 135 template <typename ScannerT> 136 typename parser_result<self_t, ScannerT>::type parseboost::spirit::subrule_list137 parse(ScannerT const& scan) const 138 { 139 typedef typename subrules_scanner_finder<ScannerT, self_t>::type 140 subrules_scanner_t; 141 subrules_scanner_t g_arg(scan, *this); 142 return first.start.parse(g_arg); 143 } 144 145 template <int ID, typename DefT, typename ContextT> 146 subrule_list< 147 FirstT, 148 subrule_list< 149 subrule_parser<ID, DefT, ContextT>, 150 RestT> > operator ,boost::spirit::subrule_list151 operator,(subrule_parser<ID, DefT, ContextT> const& rhs_) 152 { 153 return subrule_list< 154 FirstT, 155 subrule_list< 156 subrule_parser<ID, DefT, ContextT>, 157 RestT> >( 158 first, 159 subrule_list< 160 subrule_parser<ID, DefT, ContextT>, 161 RestT>(rhs_, rest)); 162 } 163 164 FirstT first; 165 RestT rest; 166 }; 167 168 /////////////////////////////////////////////////////////////////////////// 169 // 170 // subrule_parser class 171 // 172 /////////////////////////////////////////////////////////////////////////// 173 template <int ID, typename DefT, typename ContextT> 174 struct subrule_parser 175 : public parser<subrule_parser<ID, DefT, ContextT> > 176 { 177 typedef subrule_parser<ID, DefT, ContextT> self_t; 178 typedef subrule<ID, ContextT> subrule_t; 179 typedef DefT def_t; 180 181 BOOST_STATIC_CONSTANT(int, id = ID); 182 183 template <typename ScannerT> 184 struct result 185 { 186 typedef typename 187 impl::get_subrule_parser_result< 188 DefT, ScannerT, typename subrule_t::attr_t>::type type; 189 }; 190 subrule_parserboost::spirit::subrule_parser191 subrule_parser(subrule_t const& start_, DefT const& rhs_) 192 : rhs(rhs_), start(start_) {} 193 194 template <typename ScannerT> 195 typename parser_result<self_t, ScannerT>::type parseboost::spirit::subrule_parser196 parse(ScannerT const& scan) const 197 { 198 // This will only be called when parsing single subrules. 199 typedef subrule_list<self_t, nil_t> list_t; 200 typedef subrules_scanner<ScannerT, list_t> scanner_t; 201 202 list_t list(*this, nil_t()); 203 scanner_t g_arg(scan, list); 204 return start.parse(g_arg); 205 } 206 207 template <int ID2, typename DefT2, typename ContextT2> 208 inline subrule_list< 209 self_t, 210 subrule_list< 211 subrule_parser<ID2, DefT2, ContextT2>, 212 nil_t> > operator ,boost::spirit::subrule_parser213 operator,(subrule_parser<ID2, DefT2, ContextT2> const& rhs) const 214 { 215 return subrule_list< 216 self_t, 217 subrule_list< 218 subrule_parser<ID2, DefT2, ContextT2>, 219 nil_t> >( 220 *this, 221 subrule_list< 222 subrule_parser<ID2, DefT2, ContextT2>, nil_t>( 223 rhs, nil_t())); 224 } 225 226 typename DefT::embed_t rhs; 227 subrule_t const& start; 228 }; 229 230 /////////////////////////////////////////////////////////////////////////// 231 // 232 // subrule class 233 // 234 /////////////////////////////////////////////////////////////////////////// 235 template <int ID, typename ContextT> 236 struct subrule 237 : public parser<subrule<ID, ContextT> > 238 , public ContextT::base_t 239 , public context_aux<ContextT, subrule<ID, ContextT> > 240 { 241 typedef subrule<ID, ContextT> self_t; 242 typedef subrule<ID, ContextT> const& embed_t; 243 244 typedef typename ContextT::context_linker_t context_t; 245 typedef typename context_t::attr_t attr_t; 246 247 BOOST_STATIC_CONSTANT(int, id = ID); 248 249 template <typename ScannerT> 250 struct result 251 { 252 typedef typename 253 impl::get_subrule_result<ID, ScannerT, attr_t>::type type; 254 }; 255 256 template <typename ScannerT> 257 typename parser_result<self_t, ScannerT>::type parse_mainboost::spirit::subrule258 parse_main(ScannerT const& scan) const 259 { 260 typedef typename parser_result<self_t, ScannerT>::type result_t; 261 result_t result_; 262 impl::parse_subrule<result_t, ScannerT, ID>:: 263 do_(result_, scan); 264 return result_; 265 } 266 267 template <typename ScannerT> 268 typename parser_result<self_t, ScannerT>::type parseboost::spirit::subrule269 parse(ScannerT const& scan) const 270 { 271 typedef typename parser_result<self_t, ScannerT>::type result_t; 272 typedef parser_scanner_linker<ScannerT> scanner_t; 273 BOOST_SPIRIT_CONTEXT_PARSE( 274 scan, *this, scanner_t, context_t, result_t); 275 } 276 277 template <typename DefT> 278 subrule_parser<ID, DefT, ContextT> operator =boost::spirit::subrule279 operator=(parser<DefT> const& rhs) const 280 { 281 return subrule_parser<ID, DefT, ContextT>(*this, rhs.derived()); 282 } 283 284 private: 285 286 // assignment of subrules is not allowed. Use subrules 287 // with identical IDs if you want to have aliases. 288 289 subrule& operator=(subrule const&); 290 291 template <int ID2, typename ContextT2> 292 subrule& operator=(subrule<ID2, ContextT2> const&); 293 }; 294 295 BOOST_SPIRIT_CLASSIC_NAMESPACE_END 296 297 }} // namespace BOOST_SPIRIT_CLASSIC_NS 298 299 #endif 300 301