1 /*=============================================================================
2 Copyright (c) 2001-2003 Daniel Nuffer
3 Copyright (c) 2001-2007 Hartmut Kaiser
4 http://spirit.sourceforge.net/
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 #ifndef BOOST_SPIRIT_TREE_AST_HPP
10 #define BOOST_SPIRIT_TREE_AST_HPP
12 #include <boost/spirit/home/classic/namespace.hpp>
13 #include <boost/spirit/home/classic/tree/common.hpp>
14 #include <boost/spirit/home/classic/core/scanner/scanner.hpp>
16 #include <boost/spirit/home/classic/tree/ast_fwd.hpp>
18 ///////////////////////////////////////////////////////////////////////////////
19 namespace boost { namespace spirit {
21 BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
23 //////////////////////////////////
24 // ast_match_policy is simply an id so the correct specialization of
25 // tree_policy can be found.
28 typename NodeFactoryT,
31 struct ast_match_policy :
32 public common_tree_match_policy<
33 ast_match_policy<IteratorT, NodeFactoryT, T>,
37 ast_match_policy<IteratorT, NodeFactoryT, T>,
45 common_tree_match_policy<
46 ast_match_policy<IteratorT, NodeFactoryT, T>,
50 ast_match_policy<IteratorT, NodeFactoryT, T>,
56 common_tree_match_policy_;
62 template <typename PolicyT>
63 ast_match_policy(PolicyT const & policies)
64 : common_tree_match_policy_(policies)
69 //////////////////////////////////
70 template <typename MatchPolicyT, typename NodeFactoryT, typename T>
71 struct ast_tree_policy :
72 public common_tree_tree_policy<MatchPolicyT, NodeFactoryT>
74 typedef typename MatchPolicyT::match_t match_t;
75 typedef typename MatchPolicyT::iterator_t iterator_t;
77 template<typename MatchAT, typename MatchBT>
78 static void concat(MatchAT& a, MatchBT const& b)
80 BOOST_SPIRIT_ASSERT(a && b);
82 #if defined(BOOST_SPIRIT_DEBUG) && \
83 (BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES)
84 BOOST_SPIRIT_DEBUG_OUT << "\n>>>AST concat. a = " << a <<
85 "\n\tb = " << b << "<<<\n";
87 typedef typename tree_match<iterator_t, NodeFactoryT, T>::container_t
90 // test for size() is nessecary, because no_tree_gen_node leaves a.trees
91 // and/or b.trees empty
92 if (0 != b.trees.size() && b.trees.begin()->value.is_root())
94 BOOST_SPIRIT_ASSERT(b.trees.size() == 1);
97 std::swap(a.trees, tmp); // save a into tmp
98 std::swap(b.trees, a.trees); // make b.trees[0] be new root (a.trees[0])
99 container_t* pnon_root_trees = &a.trees;
100 while (pnon_root_trees->size() > 0 &&
101 pnon_root_trees->begin()->value.is_root())
103 pnon_root_trees = & pnon_root_trees->begin()->children;
105 pnon_root_trees->insert(pnon_root_trees->begin(),
106 tmp.begin(), tmp.end());
108 else if (0 != a.trees.size() && a.trees.begin()->value.is_root())
110 BOOST_SPIRIT_ASSERT(a.trees.size() == 1);
112 #if !defined(BOOST_SPIRIT_USE_LIST_FOR_TREES)
113 a.trees.begin()->children.reserve(a.trees.begin()->children.size() + b.trees.size());
115 std::copy(b.trees.begin(),
117 std::back_insert_iterator<container_t>(
118 a.trees.begin()->children));
122 #if !defined(BOOST_SPIRIT_USE_LIST_FOR_TREES)
123 a.trees.reserve(a.trees.size() + b.trees.size());
125 std::copy(b.trees.begin(),
127 std::back_insert_iterator<container_t>(a.trees));
130 #if defined(BOOST_SPIRIT_DEBUG) && \
131 (BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES)
132 BOOST_SPIRIT_DEBUG_OUT << ">>>after AST concat. a = " << a << "<<<\n\n";
138 template <typename MatchT, typename Iterator1T, typename Iterator2T>
139 static void group_match(MatchT& m, parser_id const& id,
140 Iterator1T const& first, Iterator2T const& last)
145 typedef typename tree_match<iterator_t, NodeFactoryT, T>::container_t
147 typedef typename container_t::iterator cont_iterator_t;
148 typedef typename NodeFactoryT::template factory<iterator_t> factory_t;
150 if (m.trees.size() == 1
151 #ifdef BOOST_SPIRIT_NO_TREE_NODE_COLLAPSING
152 && !(id.to_long() && m.trees.begin()->value.id().to_long())
156 // set rule_id's. There may have been multiple nodes created.
157 // Because of root_node[] they may be left-most children of the top
159 container_t* punset_id = &m.trees;
160 while (punset_id->size() > 0 &&
161 punset_id->begin()->value.id() == 0)
163 punset_id->begin()->value.id(id);
164 punset_id = &punset_id->begin()->children;
167 m.trees.begin()->value.is_root(false);
171 match_t newmatch(m.length(),
173 factory_t::empty_node() :
174 factory_t::create_node(first, last, false));
176 std::swap(newmatch.trees.begin()->children, m.trees);
177 // set this node and all it's unset children's rule_id
178 newmatch.trees.begin()->value.id(id);
179 for (cont_iterator_t i = newmatch.trees.begin();
180 i != newmatch.trees.end();
183 if (i->value.id() == 0)
190 template <typename FunctorT, typename MatchT>
191 static void apply_op_to_match(FunctorT const& op, MatchT& m)
199 template <typename IteratorT, typename NodeFactoryT, typename T>
200 struct tree_policy_selector<ast_match_policy<IteratorT, NodeFactoryT, T> >
202 typedef ast_tree_policy<
203 ast_match_policy<IteratorT, NodeFactoryT, T>,
212 //////////////////////////////////
213 struct gen_ast_node_parser_gen;
215 template <typename T>
216 struct gen_ast_node_parser
217 : public unary<T, parser<gen_ast_node_parser<T> > >
219 typedef gen_ast_node_parser<T> self_t;
220 typedef gen_ast_node_parser_gen parser_generator_t;
221 typedef unary_parser_category parser_category_t;
223 gen_ast_node_parser(T const& a)
224 : unary<T, parser<gen_ast_node_parser<T> > >(a) {}
226 template <typename ScannerT>
227 typename parser_result<self_t, ScannerT>::type
228 parse(ScannerT const& scan) const
230 typedef typename ScannerT::iteration_policy_t iteration_policy_t;
231 typedef typename ScannerT::match_policy_t::iterator_t iterator_t;
232 typedef typename ScannerT::match_policy_t::factory_t factory_t;
233 typedef ast_match_policy<iterator_t, factory_t> match_policy_t;
234 typedef typename ScannerT::action_policy_t action_policy_t;
235 typedef scanner_policies<
241 return this->subject().parse(scan.change_policies(policies_t(scan)));
245 //////////////////////////////////
246 struct gen_ast_node_parser_gen
248 template <typename T>
251 typedef gen_ast_node_parser<T> type;
254 template <typename T>
255 static gen_ast_node_parser<T>
256 generate(parser<T> const& s)
258 return gen_ast_node_parser<T>(s.derived());
261 template <typename T>
262 gen_ast_node_parser<T>
263 operator[](parser<T> const& s) const
265 return gen_ast_node_parser<T>(s.derived());
269 //////////////////////////////////
270 const gen_ast_node_parser_gen gen_ast_node_d = gen_ast_node_parser_gen();
273 //////////////////////////////////
276 template <typename MatchT>
277 void operator()(MatchT& m) const
279 BOOST_SPIRIT_ASSERT(m.trees.size() > 0);
280 m.trees.begin()->value.is_root(true);
284 const node_parser_gen<root_node_op> root_node_d =
285 node_parser_gen<root_node_op>();
287 ///////////////////////////////////////////////////////////////////////////////
289 // Parse functions for ASTs
291 ///////////////////////////////////////////////////////////////////////////////
293 typename AstFactoryT, typename IteratorT, typename ParserT,
296 inline tree_parse_info<IteratorT, AstFactoryT>
298 IteratorT const& first_,
299 IteratorT const& last_,
300 parser<ParserT> const& parser,
302 AstFactoryT const & /*dummy_*/ = AstFactoryT())
304 typedef skip_parser_iteration_policy<SkipT> iter_policy_t;
305 typedef ast_match_policy<IteratorT, AstFactoryT> ast_match_policy_t;
307 scanner_policies<iter_policy_t, ast_match_policy_t>
309 typedef scanner<IteratorT, scanner_policies_t> scanner_t;
311 iter_policy_t iter_policy(skip_);
312 scanner_policies_t policies(iter_policy);
313 IteratorT first = first_;
314 scanner_t scan(first, last_, policies);
315 tree_match<IteratorT, AstFactoryT> hit = parser.derived().parse(scan);
316 return tree_parse_info<IteratorT, AstFactoryT>(
317 first, hit, hit && (first == last_), hit.length(), hit.trees);
320 //////////////////////////////////
321 template <typename IteratorT, typename ParserT, typename SkipT>
322 inline tree_parse_info<IteratorT>
324 IteratorT const& first_,
325 IteratorT const& last_,
326 parser<ParserT> const& parser,
329 typedef node_val_data_factory<nil_t> default_factory_t;
330 return ast_parse(first_, last_, parser, skip_, default_factory_t());
333 //////////////////////////////////
334 template <typename IteratorT, typename ParserT>
335 inline tree_parse_info<IteratorT>
337 IteratorT const& first_,
338 IteratorT const& last,
339 parser<ParserT> const& parser)
341 typedef ast_match_policy<IteratorT> ast_match_policy_t;
342 IteratorT first = first_;
345 scanner_policies<iteration_policy, ast_match_policy_t>
347 tree_match<IteratorT> hit = parser.derived().parse(scan);
348 return tree_parse_info<IteratorT>(
349 first, hit, hit && (first == last), hit.length(), hit.trees);
352 //////////////////////////////////
353 template <typename CharT, typename ParserT, typename SkipT>
354 inline tree_parse_info<CharT const*>
357 parser<ParserT> const& parser,
360 CharT const* last = str;
363 return ast_parse(str, last, parser, skip);
366 //////////////////////////////////
367 template <typename CharT, typename ParserT>
368 inline tree_parse_info<CharT const*>
371 parser<ParserT> const& parser)
373 CharT const* last = str;
378 return ast_parse(str, last, parser);
381 ///////////////////////////////////////////////////////////////////////////////
382 BOOST_SPIRIT_CLASSIC_NAMESPACE_END
384 }} // namespace BOOST_SPIRIT_CLASSIC_NS