1/*=============================================================================
2 Copyright (c) 2014 Joel de Guzman
3
4 Distributed under the Boost Software License, Version 1.0. (See accompanying
5 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6==============================================================================*/
7#if !defined(BOOST_SPIRIT_X3_POSITION_TAGGED_MAY_01_2014_0321PM)
8#define BOOST_SPIRIT_X3_POSITION_TAGGED_MAY_01_2014_0321PM
9
10#include <boost/range/iterator_range_core.hpp>
11#include <boost/type_traits/is_base_of.hpp>
12#include <boost/core/enable_if.hpp>
13
14namespace boost { namespace spirit { namespace x3
15{
16 struct position_tagged
17 {
18 // Use this to annotate an AST with the iterator position.
19 // These ids are used as a key to the position_cache (below)
20 // and marks the start and end of an AST node.
21 int id_first = -1;
22 int id_last = -1;
23 };
24
25 template <typename Container>
26 class position_cache
27 {
28 public:
29
30 typedef typename Container::value_type iterator_type;
31
32 position_cache(
33 iterator_type first
34 , iterator_type last)
35 : first_(first), last_(last) {}
36
37 // This will catch all nodes inheriting from position_tagged
38 boost::iterator_range<iterator_type>
39 position_of(position_tagged const& ast) const
40 {
41 return
42 boost::iterator_range<iterator_type>(
43 positions.at(ast.id_first) // throws if out of range
44 , positions.at(ast.id_last) // throws if out of range
45 );
46 }
47
48 // This will catch all nodes except those inheriting from position_tagged
49 template <typename AST>
50 typename boost::enable_if_c<
51 (!is_base_of<position_tagged, AST>::value)
52 , boost::iterator_range<iterator_type>
53 >::type
54 position_of(AST const& /* ast */) const
55 {
56 // returns an empty position
57 return boost::iterator_range<iterator_type>();
58 }
59
60 // This will catch all nodes except those inheriting from position_tagged
61 template <typename AST>
62 void annotate(AST& /* ast */, iterator_type /* first */, iterator_type /* last */, mpl::false_)
63 {
64 // (no-op) no need for tags
65 }
66
67 // This will catch all nodes inheriting from position_tagged
68 void annotate(position_tagged& ast, iterator_type first, iterator_type last, mpl::true_)
69 {
70 ast.id_first = int(positions.size());
71 positions.push_back(first);
72 ast.id_last = int(positions.size());
73 positions.push_back(last);
74 }
75
76 template <typename AST>
77 void annotate(AST& ast, iterator_type first, iterator_type last)
78 {
79 annotate(ast, first, last, is_base_of<position_tagged, AST>());
80 }
81
82 Container const&
83 get_positions() const
84 {
85 return positions;
86 }
87
88 iterator_type first() const { return first_; }
89 iterator_type last() const { return last_; }
90
91 private:
92
93 Container positions;
94 iterator_type first_;
95 iterator_type last_;
96 };
97
98}}}
99
100#endif
101

source code of boost/libs/spirit/include/boost/spirit/home/x3/support/ast/position_tagged.hpp