/*============================================================================= 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 #include #include 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 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 position_of(position_tagged const& ast) const { return boost::iterator_range( 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 boost::enable_if_c< (!is_base_of::value) , boost::iterator_range >::type position_of(AST const& /* ast */) const { // returns an empty position return boost::iterator_range(); } // This will catch all nodes except those inheriting from position_tagged template 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 void annotate(AST& ast, iterator_type first, iterator_type last) { annotate(ast, first, last, is_base_of()); } 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