123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100 |
- /*=============================================================================
- Copyright (c) 2014 Joel de Guzman
- Distributed under the Boost Software License, Version 1.0. (See accompanying
- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
- ==============================================================================*/
- #if !defined(BOOST_SPIRIT_X3_POSITION_TAGGED_MAY_01_2014_0321PM)
- #define BOOST_SPIRIT_X3_POSITION_TAGGED_MAY_01_2014_0321PM
- #include <boost/range.hpp>
- #include <boost/type_traits/is_base_of.hpp>
- #include <boost/core/enable_if.hpp>
- namespace boost { namespace spirit { namespace x3
- {
- struct position_tagged
- {
- // Use this to annotate an AST with the iterator position.
- // These ids are used as a key to the position_cache (below)
- // and marks the start and end of an AST node.
- int id_first = -1;
- int id_last = -1;
- };
- template <typename Container>
- class position_cache
- {
- public:
- typedef typename Container::value_type iterator_type;
- position_cache(
- iterator_type first
- , iterator_type last)
- : first_(first), last_(last) {}
- // This will catch all nodes inheriting from position_tagged
- boost::iterator_range<iterator_type>
- position_of(position_tagged const& ast) const
- {
- return
- boost::iterator_range<iterator_type>(
- positions.at(ast.id_first) // throws if out of range
- , positions.at(ast.id_last) // throws if out of range
- );
- }
- // This will catch all nodes except those inheriting from position_tagged
- template <typename AST>
- typename boost::enable_if_c<
- (!is_base_of<position_tagged, AST>::value)
- , boost::iterator_range<iterator_type>
- >::type
- position_of(AST const& /* ast */) const
- {
- // returns an empty position
- return boost::iterator_range<iterator_type>();
- }
- // This will catch all nodes except those inheriting from position_tagged
- template <typename AST>
- void annotate(AST& /* ast */, iterator_type /* first */, iterator_type /* last */, mpl::false_)
- {
- // (no-op) no need for tags
- }
- // This will catch all nodes inheriting from position_tagged
- void annotate(position_tagged& ast, iterator_type first, iterator_type last, mpl::true_)
- {
- ast.id_first = int(positions.size());
- positions.push_back(first);
- ast.id_last = int(positions.size());
- positions.push_back(last);
- }
- template <typename AST>
- void annotate(AST& ast, iterator_type first, iterator_type last)
- {
- annotate(ast, first, last, is_base_of<position_tagged, AST>());
- }
- Container const&
- get_positions() const
- {
- return positions;
- }
- iterator_type first() const { return first_; }
- iterator_type last() const { return last_; }
- private:
- Container positions;
- iterator_type first_;
- iterator_type last_;
- };
- }}}
- #endif
|