#ifndef ALT_HPP_ #define ALT_HPP_ #include "symbol.hpp" namespace detail { template< class StaticVisitor , class ...Symbols > class apply_visitor_impl; template< class ...Symbols > class alt_impl; template<> class alt_impl<> : public symbol { public: template< class CharType > constexpr alt_impl( const_string< CharType > str , std::size_t begin = 0 , std::size_t end = invalid_index ) : symbol( end ) { } template< class StaticVisitor > constexpr typename StaticVisitor::result_type apply_visitor( StaticVisitor visitor ) { return visitor.null(); } }; template< class Head , class ...Tail > class alt_impl< Head , Tail... > : public alt_impl< Tail... > { public: template< class CharType > constexpr alt_impl( const_string< CharType > str , std::size_t begin = 0 , std::size_t end = symbol::invalid_index ) : alt_impl< Tail... > ( str , begin , end != symbol::invalid_index ? end : Head( str , begin ).valid() ? Head( str , begin ).end() : end ) , obj( Head( str , begin ) ) { } template< class StaticVisitor > constexpr typename StaticVisitor::result_type apply_visitor( StaticVisitor visitor ) { return obj.valid() ? visitor( obj ) : alt_impl< Tail... >::apply_visitor( visitor ); } private: public: Head obj; }; template< class StaticVisitor > struct apply_visitor_impl< StaticVisitor > { static constexpr typename StaticVisitor::result_type impl( StaticVisitor , alt_impl<> ) { return typename StaticVisitor::result_type(); } }; template< class StaticVisitor , class Head , class ...Tail > struct apply_visitor_impl< StaticVisitor , Head , Tail... > { static constexpr typename StaticVisitor::result_type impl( StaticVisitor visitor , alt_impl< Head , Tail... > a ) { return a.obj.valid() ? visitor( a.obj ) : apply_visitor_impl< StaticVisitor , Tail... >::impl( visitor , a ); } }; } template< class ...Symbols > class alt : public detail::alt_impl< Symbols... > { public: template< class CharType > constexpr alt( const_string< CharType > str , std::size_t begin = 0 ) : detail::alt_impl< Symbols... >( str , begin ) { } template< class StaticVisitor > constexpr typename StaticVisitor::result_type apply_visitor( StaticVisitor visitor ) { return detail::apply_visitor_impl< StaticVisitor , Symbols... >::impl( visitor , *this ); } }; template< class StaticVisitor , class ...Symbols > constexpr typename StaticVisitor::result_type apply_visitor( StaticVisitor visitor , alt< Symbols... > a ) { return detail::apply_visitor_impl< StaticVisitor , Symbols... >::impl( visitor , a ); } #endif