os/ossrv/ossrv_pub/boost_apis/boost/spirit/tree/ast.hpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     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