| 1 | /*============================================================================= | 
|---|
| 2 |     Copyright (c) 2001-2003 Daniel Nuffer | 
|---|
| 3 |     http://spirit.sourceforge.net/ | 
|---|
| 4 |  | 
|---|
| 5 |     Use, modification and distribution is subject to the Boost Software | 
|---|
| 6 |     License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at | 
|---|
| 7 |     http://www.boost.org/LICENSE_1_0.txt) | 
|---|
| 8 | =============================================================================*/ | 
|---|
| 9 | #ifndef BOOST_SPIRIT_TREE_AST_HPP | 
|---|
| 10 | #define BOOST_SPIRIT_TREE_AST_HPP | 
|---|
| 11 |  | 
|---|
| 12 | #include <boost/spirit/tree/common.hpp> | 
|---|
| 13 | #include <boost/spirit/core/scanner/scanner.hpp> | 
|---|
| 14 |  | 
|---|
| 15 | #include <boost/spirit/tree/ast_fwd.hpp> | 
|---|
| 16 |  | 
|---|
| 17 | /////////////////////////////////////////////////////////////////////////////// | 
|---|
| 18 | namespace boost { namespace spirit { | 
|---|
| 19 |  | 
|---|
| 20 |  | 
|---|
| 21 | ////////////////////////////////// | 
|---|
| 22 | //  ast_match_policy is simply an id so the correct specialization of | 
|---|
| 23 | //  tree_policy can be found. | 
|---|
| 24 | template < | 
|---|
| 25 |     typename IteratorT, | 
|---|
| 26 |     typename NodeFactoryT | 
|---|
| 27 | > | 
|---|
| 28 | struct ast_match_policy : | 
|---|
| 29 |     public common_tree_match_policy< | 
|---|
| 30 |         ast_match_policy<IteratorT, NodeFactoryT>, | 
|---|
| 31 |         IteratorT, | 
|---|
| 32 |         NodeFactoryT, | 
|---|
| 33 |         ast_tree_policy< | 
|---|
| 34 |             ast_match_policy<IteratorT, NodeFactoryT>, | 
|---|
| 35 |             NodeFactoryT | 
|---|
| 36 |         > | 
|---|
| 37 |     > | 
|---|
| 38 | { | 
|---|
| 39 |     typedef | 
|---|
| 40 |         common_tree_match_policy< | 
|---|
| 41 |             ast_match_policy<IteratorT, NodeFactoryT>, | 
|---|
| 42 |             IteratorT, | 
|---|
| 43 |             NodeFactoryT, | 
|---|
| 44 |             ast_tree_policy< | 
|---|
| 45 |                 ast_match_policy<IteratorT, NodeFactoryT>, | 
|---|
| 46 |                 NodeFactoryT | 
|---|
| 47 |             > | 
|---|
| 48 |         > | 
|---|
| 49 |     common_tree_match_policy_; | 
|---|
| 50 |  | 
|---|
| 51 |     ast_match_policy() | 
|---|
| 52 |     { | 
|---|
| 53 |     } | 
|---|
| 54 |  | 
|---|
| 55 |     template <typename PolicyT> | 
|---|
| 56 |     ast_match_policy(PolicyT const & policies) | 
|---|
| 57 |         : common_tree_match_policy_(policies) | 
|---|
| 58 |     { | 
|---|
| 59 |     } | 
|---|
| 60 | }; | 
|---|
| 61 |  | 
|---|
| 62 | ////////////////////////////////// | 
|---|
| 63 | template <typename MatchPolicyT, typename NodeFactoryT> | 
|---|
| 64 | struct ast_tree_policy : | 
|---|
| 65 |     public common_tree_tree_policy<MatchPolicyT, NodeFactoryT> | 
|---|
| 66 | { | 
|---|
| 67 |     typedef | 
|---|
| 68 |         typename common_tree_tree_policy<MatchPolicyT, NodeFactoryT>::match_t | 
|---|
| 69 |         match_t; | 
|---|
| 70 |     typedef typename MatchPolicyT::iterator_t iterator_t; | 
|---|
| 71 |  | 
|---|
| 72 |     static void concat(match_t& a, match_t const& b) | 
|---|
| 73 |     { | 
|---|
| 74 |         BOOST_SPIRIT_ASSERT(a && b); | 
|---|
| 75 |  | 
|---|
| 76 | #if defined(BOOST_SPIRIT_DEBUG) && \ | 
|---|
| 77 |     (BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES) | 
|---|
| 78 |         BOOST_SPIRIT_DEBUG_OUT << "\n>>>AST concat. a = " << a << | 
|---|
| 79 |             "\n\tb = " << b << "<<<\n"; | 
|---|
| 80 | #endif | 
|---|
| 81 |         typedef typename tree_match<iterator_t, NodeFactoryT>::container_t | 
|---|
| 82 |             container_t; | 
|---|
| 83 |  | 
|---|
| 84 |         // test for size() is nessecary, because no_tree_gen_node leaves a.trees | 
|---|
| 85 |         // and/or b.trees empty | 
|---|
| 86 |         if (0 != b.trees.size() && b.trees.begin()->value.is_root()) | 
|---|
| 87 |         { | 
|---|
| 88 |             BOOST_SPIRIT_ASSERT(b.trees.size() == 1); | 
|---|
| 89 |  | 
|---|
| 90 |             container_t tmp; | 
|---|
| 91 |             std::swap(a.trees, tmp); // save a into tmp | 
|---|
| 92 |             std::swap(b.trees, a.trees); // make b.trees[0] be new root (a.trees[0]) | 
|---|
| 93 |             container_t* pnon_root_trees = &a.trees; | 
|---|
| 94 |             while (pnon_root_trees->size() > 0 && | 
|---|
| 95 |                     pnon_root_trees->begin()->value.is_root()) | 
|---|
| 96 |             { | 
|---|
| 97 |                 pnon_root_trees = & pnon_root_trees->begin()->children; | 
|---|
| 98 |             } | 
|---|
| 99 |             pnon_root_trees->insert(pnon_root_trees->begin(), | 
|---|
| 100 |                     tmp.begin(), tmp.end()); | 
|---|
| 101 |         } | 
|---|
| 102 |         else if (0 != a.trees.size() && a.trees.begin()->value.is_root()) | 
|---|
| 103 |         { | 
|---|
| 104 |             BOOST_SPIRIT_ASSERT(a.trees.size() == 1); | 
|---|
| 105 |  | 
|---|
| 106 | #if !defined(BOOST_SPIRIT_USE_LIST_FOR_TREES) | 
|---|
| 107 |             a.trees.begin()->children.reserve(a.trees.begin()->children.size() + b.trees.size()); | 
|---|
| 108 | #endif | 
|---|
| 109 |             std::copy(b.trees.begin(), | 
|---|
| 110 |                  b.trees.end(), | 
|---|
| 111 |                  std::back_insert_iterator<container_t>( | 
|---|
| 112 |                      a.trees.begin()->children)); | 
|---|
| 113 |         } | 
|---|
| 114 |         else | 
|---|
| 115 |         { | 
|---|
| 116 | #if !defined(BOOST_SPIRIT_USE_LIST_FOR_TREES) | 
|---|
| 117 |             a.trees.reserve(a.trees.size() + b.trees.size()); | 
|---|
| 118 | #endif | 
|---|
| 119 |             std::copy(b.trees.begin(), | 
|---|
| 120 |                  b.trees.end(), | 
|---|
| 121 |                  std::back_insert_iterator<container_t>(a.trees)); | 
|---|
| 122 |         } | 
|---|
| 123 |  | 
|---|
| 124 | #if defined(BOOST_SPIRIT_DEBUG) && \ | 
|---|
| 125 |     (BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES) | 
|---|
| 126 |         BOOST_SPIRIT_DEBUG_OUT << ">>>after AST concat. a = " << a << "<<<\n\n"; | 
|---|
| 127 | #endif | 
|---|
| 128 |  | 
|---|
| 129 |         return; | 
|---|
| 130 |     } | 
|---|
| 131 |  | 
|---|
| 132 |     template <typename MatchT, typename Iterator1T, typename Iterator2T> | 
|---|
| 133 |     static void group_match(MatchT& m, parser_id const& id, | 
|---|
| 134 |             Iterator1T const& first, Iterator2T const& last) | 
|---|
| 135 |     { | 
|---|
| 136 |         if (!m) | 
|---|
| 137 |             return; | 
|---|
| 138 |  | 
|---|
| 139 |         typedef typename tree_match<iterator_t, NodeFactoryT>::container_t | 
|---|
| 140 |             container_t; | 
|---|
| 141 |         typedef typename container_t::iterator cont_iterator_t; | 
|---|
| 142 |         typedef typename NodeFactoryT::template factory<iterator_t> factory_t; | 
|---|
| 143 |  | 
|---|
| 144 |         if (m.trees.size() == 1 | 
|---|
| 145 | #ifdef BOOST_SPIRIT_NO_TREE_NODE_COLLAPSING | 
|---|
| 146 |             && !(id.to_long() && m.trees.begin()->value.id().to_long()) | 
|---|
| 147 | #endif | 
|---|
| 148 |             ) | 
|---|
| 149 |         { | 
|---|
| 150 |             // set rule_id's.  There may have been multiple nodes created. | 
|---|
| 151 |             // Because of root_node[] they may be left-most children of the top | 
|---|
| 152 |             // node. | 
|---|
| 153 |             container_t* punset_id = &m.trees; | 
|---|
| 154 |             while (punset_id->size() > 0 && | 
|---|
| 155 |                     punset_id->begin()->value.id() == 0) | 
|---|
| 156 |             { | 
|---|
| 157 |                 punset_id->begin()->value.id(id); | 
|---|
| 158 |                 punset_id = &punset_id->begin()->children; | 
|---|
| 159 |             } | 
|---|
| 160 |  | 
|---|
| 161 |             m.trees.begin()->value.is_root(false); | 
|---|
| 162 |         } | 
|---|
| 163 |         else | 
|---|
| 164 |         { | 
|---|
| 165 |             match_t newmatch(m.length(), | 
|---|
| 166 |                 m.trees.empty() ?  | 
|---|
| 167 |                     factory_t::empty_node() :  | 
|---|
| 168 |                     factory_t::create_node(first, last, false)); | 
|---|
| 169 |  | 
|---|
| 170 |             std::swap(newmatch.trees.begin()->children, m.trees); | 
|---|
| 171 |             // set this node and all it's unset children's rule_id | 
|---|
| 172 |             newmatch.trees.begin()->value.id(id); | 
|---|
| 173 |             for (cont_iterator_t i = newmatch.trees.begin(); | 
|---|
| 174 |                  i != newmatch.trees.end(); | 
|---|
| 175 |                  ++i) | 
|---|
| 176 |             { | 
|---|
| 177 |                 if (i->value.id() == 0) | 
|---|
| 178 |                     i->value.id(id); | 
|---|
| 179 |             } | 
|---|
| 180 |             m = newmatch; | 
|---|
| 181 |         } | 
|---|
| 182 |     } | 
|---|
| 183 |  | 
|---|
| 184 |     template <typename FunctorT> | 
|---|
| 185 |     static void apply_op_to_match(FunctorT const& op, match_t& m) | 
|---|
| 186 |     { | 
|---|
| 187 |         op(m); | 
|---|
| 188 |     } | 
|---|
| 189 | }; | 
|---|
| 190 |  | 
|---|
| 191 | namespace impl { | 
|---|
| 192 |  | 
|---|
| 193 |     template <typename IteratorT, typename NodeFactoryT> | 
|---|
| 194 |     struct tree_policy_selector<ast_match_policy<IteratorT, NodeFactoryT> > | 
|---|
| 195 |     { | 
|---|
| 196 |         typedef ast_tree_policy< | 
|---|
| 197 |             ast_match_policy<IteratorT, NodeFactoryT>, NodeFactoryT> type; | 
|---|
| 198 |     }; | 
|---|
| 199 |  | 
|---|
| 200 | } // namespace impl | 
|---|
| 201 |  | 
|---|
| 202 |  | 
|---|
| 203 | ////////////////////////////////// | 
|---|
| 204 | struct gen_ast_node_parser_gen; | 
|---|
| 205 |  | 
|---|
| 206 | template <typename T> | 
|---|
| 207 | struct gen_ast_node_parser | 
|---|
| 208 | :   public unary<T, parser<gen_ast_node_parser<T> > > | 
|---|
| 209 | { | 
|---|
| 210 |     typedef gen_ast_node_parser<T> self_t; | 
|---|
| 211 |     typedef gen_ast_node_parser_gen parser_generator_t; | 
|---|
| 212 |     typedef unary_parser_category parser_category_t; | 
|---|
| 213 | //    typedef gen_ast_node_parser<T> const &embed_t; | 
|---|
| 214 |  | 
|---|
| 215 |     gen_ast_node_parser(T const& a) | 
|---|
| 216 |     : unary<T, parser<gen_ast_node_parser<T> > >(a) {} | 
|---|
| 217 |  | 
|---|
| 218 |     template <typename ScannerT> | 
|---|
| 219 |     typename parser_result<self_t, ScannerT>::type | 
|---|
| 220 |     parse(ScannerT const& scan) const | 
|---|
| 221 |     { | 
|---|
| 222 |         typedef typename ScannerT::iteration_policy_t iteration_policy_t; | 
|---|
| 223 |         typedef typename ScannerT::match_policy_t::iterator_t iterator_t; | 
|---|
| 224 |         typedef typename ScannerT::match_policy_t::factory_t factory_t; | 
|---|
| 225 |         typedef ast_match_policy<iterator_t, factory_t> match_policy_t; | 
|---|
| 226 |         typedef typename ScannerT::action_policy_t action_policy_t; | 
|---|
| 227 |         typedef scanner_policies< | 
|---|
| 228 |             iteration_policy_t, | 
|---|
| 229 |             match_policy_t, | 
|---|
| 230 |             action_policy_t | 
|---|
| 231 |         > policies_t; | 
|---|
| 232 |  | 
|---|
| 233 |         return this->subject().parse(scan.change_policies(policies_t(scan))); | 
|---|
| 234 |     } | 
|---|
| 235 | }; | 
|---|
| 236 |  | 
|---|
| 237 | ////////////////////////////////// | 
|---|
| 238 | struct gen_ast_node_parser_gen | 
|---|
| 239 | { | 
|---|
| 240 |     template <typename T> | 
|---|
| 241 |     struct result { | 
|---|
| 242 |  | 
|---|
| 243 |         typedef gen_ast_node_parser<T> type; | 
|---|
| 244 |     }; | 
|---|
| 245 |  | 
|---|
| 246 |     template <typename T> | 
|---|
| 247 |     static gen_ast_node_parser<T> | 
|---|
| 248 |     generate(parser<T> const& s) | 
|---|
| 249 |     { | 
|---|
| 250 |         return gen_ast_node_parser<T>(s.derived()); | 
|---|
| 251 |     } | 
|---|
| 252 |  | 
|---|
| 253 |     template <typename T> | 
|---|
| 254 |     gen_ast_node_parser<T> | 
|---|
| 255 |     operator[](parser<T> const& s) const | 
|---|
| 256 |     { | 
|---|
| 257 |         return gen_ast_node_parser<T>(s.derived()); | 
|---|
| 258 |     } | 
|---|
| 259 | }; | 
|---|
| 260 |  | 
|---|
| 261 | ////////////////////////////////// | 
|---|
| 262 | const gen_ast_node_parser_gen gen_ast_node_d = gen_ast_node_parser_gen(); | 
|---|
| 263 |  | 
|---|
| 264 |  | 
|---|
| 265 | ////////////////////////////////// | 
|---|
| 266 | struct root_node_op | 
|---|
| 267 | { | 
|---|
| 268 |     template <typename MatchT> | 
|---|
| 269 |     void operator()(MatchT& m) const | 
|---|
| 270 |     { | 
|---|
| 271 |         BOOST_SPIRIT_ASSERT(m.trees.size() > 0); | 
|---|
| 272 |         m.trees.begin()->value.is_root(true); | 
|---|
| 273 |     } | 
|---|
| 274 | }; | 
|---|
| 275 |  | 
|---|
| 276 | const node_parser_gen<root_node_op> root_node_d = | 
|---|
| 277 |     node_parser_gen<root_node_op>(); | 
|---|
| 278 |  | 
|---|
| 279 | /////////////////////////////////////////////////////////////////////////////// | 
|---|
| 280 | // | 
|---|
| 281 | //  Parse functions for ASTs | 
|---|
| 282 | // | 
|---|
| 283 | /////////////////////////////////////////////////////////////////////////////// | 
|---|
| 284 | template < | 
|---|
| 285 |     typename AstFactoryT, typename IteratorT, typename ParserT,  | 
|---|
| 286 |     typename SkipT | 
|---|
| 287 | > | 
|---|
| 288 | inline tree_parse_info<IteratorT, AstFactoryT> | 
|---|
| 289 | ast_parse( | 
|---|
| 290 |     IteratorT const&        first_, | 
|---|
| 291 |     IteratorT const&        last_, | 
|---|
| 292 |     parser<ParserT> const&  parser, | 
|---|
| 293 |     SkipT const&            skip_, | 
|---|
| 294 |     AstFactoryT const &   /*dummy_*/ = AstFactoryT()) | 
|---|
| 295 | { | 
|---|
| 296 |     typedef skip_parser_iteration_policy<SkipT> iter_policy_t; | 
|---|
| 297 |     typedef ast_match_policy<IteratorT, AstFactoryT> ast_match_policy_t; | 
|---|
| 298 |     typedef | 
|---|
| 299 |         scanner_policies<iter_policy_t, ast_match_policy_t> | 
|---|
| 300 |         scanner_policies_t; | 
|---|
| 301 |     typedef scanner<IteratorT, scanner_policies_t> scanner_t; | 
|---|
| 302 |  | 
|---|
| 303 |     iter_policy_t iter_policy(skip_); | 
|---|
| 304 |     scanner_policies_t policies(iter_policy); | 
|---|
| 305 |     IteratorT first = first_; | 
|---|
| 306 |     scanner_t scan(first, last_, policies); | 
|---|
| 307 |     tree_match<IteratorT, AstFactoryT> hit = parser.derived().parse(scan); | 
|---|
| 308 |     scan.skip(scan); | 
|---|
| 309 |     return tree_parse_info<IteratorT, AstFactoryT>( | 
|---|
| 310 |         first, hit, hit && (first == last_), hit.length(), hit.trees); | 
|---|
| 311 | } | 
|---|
| 312 |  | 
|---|
| 313 | ////////////////////////////////// | 
|---|
| 314 | template <typename IteratorT, typename ParserT, typename SkipT> | 
|---|
| 315 | inline tree_parse_info<IteratorT> | 
|---|
| 316 | ast_parse( | 
|---|
| 317 |     IteratorT const&        first_, | 
|---|
| 318 |     IteratorT const&        last_, | 
|---|
| 319 |     parser<ParserT> const&  parser, | 
|---|
| 320 |     SkipT const&            skip_) | 
|---|
| 321 | { | 
|---|
| 322 |     typedef node_val_data_factory<nil_t> default_factory_t; | 
|---|
| 323 |     return ast_parse(first_, last_, parser, skip_, default_factory_t()); | 
|---|
| 324 | } | 
|---|
| 325 |    | 
|---|
| 326 | ////////////////////////////////// | 
|---|
| 327 | template <typename IteratorT, typename ParserT> | 
|---|
| 328 | inline tree_parse_info<IteratorT> | 
|---|
| 329 | ast_parse( | 
|---|
| 330 |     IteratorT const&        first_, | 
|---|
| 331 |     IteratorT const&        last, | 
|---|
| 332 |     parser<ParserT> const&  parser) | 
|---|
| 333 | { | 
|---|
| 334 |     typedef ast_match_policy<IteratorT> ast_match_policy_t; | 
|---|
| 335 |     IteratorT first = first_; | 
|---|
| 336 |     scanner< | 
|---|
| 337 |         IteratorT, | 
|---|
| 338 |         scanner_policies<iteration_policy, ast_match_policy_t> | 
|---|
| 339 |     > scan(first, last); | 
|---|
| 340 |     tree_match<IteratorT> hit = parser.derived().parse(scan); | 
|---|
| 341 |     return tree_parse_info<IteratorT>( | 
|---|
| 342 |         first, hit, hit && (first == last), hit.length(), hit.trees); | 
|---|
| 343 | } | 
|---|
| 344 |  | 
|---|
| 345 | ////////////////////////////////// | 
|---|
| 346 | template <typename CharT, typename ParserT, typename SkipT> | 
|---|
| 347 | inline tree_parse_info<CharT const*> | 
|---|
| 348 | ast_parse( | 
|---|
| 349 |     CharT const*            str, | 
|---|
| 350 |     parser<ParserT> const&  parser, | 
|---|
| 351 |     SkipT const&            skip) | 
|---|
| 352 | { | 
|---|
| 353 |     CharT const* last = str; | 
|---|
| 354 |     while (*last) | 
|---|
| 355 |         last++; | 
|---|
| 356 |     return ast_parse(str, last, parser, skip); | 
|---|
| 357 | } | 
|---|
| 358 |  | 
|---|
| 359 | ////////////////////////////////// | 
|---|
| 360 | template <typename CharT, typename ParserT> | 
|---|
| 361 | inline tree_parse_info<CharT const*> | 
|---|
| 362 | ast_parse( | 
|---|
| 363 |     CharT const*            str, | 
|---|
| 364 |     parser<ParserT> const&  parser) | 
|---|
| 365 | { | 
|---|
| 366 |     CharT const* last = str; | 
|---|
| 367 |     while (*last) | 
|---|
| 368 |     { | 
|---|
| 369 |         last++; | 
|---|
| 370 |     } | 
|---|
| 371 |     return ast_parse(str, last, parser); | 
|---|
| 372 | } | 
|---|
| 373 |  | 
|---|
| 374 | /////////////////////////////////////////////////////////////////////////////// | 
|---|
| 375 | }} // namespace boost::spirit | 
|---|
| 376 |  | 
|---|
| 377 | #endif | 
|---|
| 378 |  | 
|---|