// Copyright (c) 2014-2018 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ #ifndef TAO_PEGTL_INTERNAL_DUSELTRONIK_HPP #define TAO_PEGTL_INTERNAL_DUSELTRONIK_HPP #include "../apply_mode.hpp" #include "../config.hpp" #include "../rewind_mode.hpp" #include "dusel_mode.hpp" namespace tao { namespace TAO_PEGTL_NAMESPACE { namespace internal { template< typename Rule, apply_mode A, rewind_mode M, template< typename... > class Action, template< typename... > class Control, dusel_mode = dusel_mode::NOTHING > struct duseltronik; template< typename Rule, apply_mode A, rewind_mode M, template< typename... > class Action, template< typename... > class Control > struct duseltronik< Rule, A, M, Action, Control, dusel_mode::NOTHING > { template< typename Input, typename... States > static auto match( Input& in, States&&... st ) -> decltype( Rule::template match< A, M, Action, Control >( in, st... ), true ) { return Rule::template match< A, M, Action, Control >( in, st... ); } // NOTE: The additional "int = 0" is a work-around for missing expression SFINAE in VS2015. template< typename Input, typename... States, int = 0 > static auto match( Input& in, States&&... /*unused*/ ) -> decltype( Rule::match( in ), true ) { return Rule::match( in ); } }; template< typename Rule, apply_mode A, rewind_mode M, template< typename... > class Action, template< typename... > class Control > struct duseltronik< Rule, A, M, Action, Control, dusel_mode::CONTROL > { template< typename Input, typename... States > static bool match( Input& in, States&&... st ) { Control< Rule >::start( static_cast< const Input& >( in ), st... ); if( duseltronik< Rule, A, M, Action, Control, dusel_mode::NOTHING >::match( in, st... ) ) { Control< Rule >::success( static_cast< const Input& >( in ), st... ); return true; } Control< Rule >::failure( static_cast< const Input& >( in ), st... ); return false; } }; template< typename Rule, apply_mode A, rewind_mode M, template< typename... > class Action, template< typename... > class Control > struct duseltronik< Rule, A, M, Action, Control, dusel_mode::CONTROL_AND_APPLY_VOID > { template< typename Input, typename... States > static bool match( Input& in, States&&... st ) { auto m = in.template mark< rewind_mode::REQUIRED >(); Control< Rule >::start( static_cast< const Input& >( in ), st... ); if( duseltronik< Rule, A, rewind_mode::ACTIVE, Action, Control, dusel_mode::NOTHING >::match( in, st... ) ) { Control< Rule >::template apply< Action >( m.iterator(), static_cast< const Input& >( in ), st... ); Control< Rule >::success( static_cast< const Input& >( in ), st... ); return m( true ); } Control< Rule >::failure( static_cast< const Input& >( in ), st... ); return false; } }; template< typename Rule, apply_mode A, rewind_mode M, template< typename... > class Action, template< typename... > class Control > struct duseltronik< Rule, A, M, Action, Control, dusel_mode::CONTROL_AND_APPLY_BOOL > { template< typename Input, typename... States > static bool match( Input& in, States&&... st ) { auto m = in.template mark< rewind_mode::REQUIRED >(); Control< Rule >::start( static_cast< const Input& >( in ), st... ); if( duseltronik< Rule, A, rewind_mode::ACTIVE, Action, Control, dusel_mode::NOTHING >::match( in, st... ) ) { if( Control< Rule >::template apply< Action >( m.iterator(), static_cast< const Input& >( in ), st... ) ) { Control< Rule >::success( static_cast< const Input& >( in ), st... ); return m( true ); } } Control< Rule >::failure( static_cast< const Input& >( in ), st... ); return false; } }; template< typename Rule, apply_mode A, rewind_mode M, template< typename... > class Action, template< typename... > class Control > struct duseltronik< Rule, A, M, Action, Control, dusel_mode::CONTROL_AND_APPLY0_VOID > { template< typename Input, typename... States > static bool match( Input& in, States&&... st ) { Control< Rule >::start( static_cast< const Input& >( in ), st... ); if( duseltronik< Rule, A, M, Action, Control, dusel_mode::NOTHING >::match( in, st... ) ) { Control< Rule >::template apply0< Action >( static_cast< const Input& >( in ), st... ); Control< Rule >::success( static_cast< const Input& >( in ), st... ); return true; } Control< Rule >::failure( static_cast< const Input& >( in ), st... ); return false; } }; template< typename Rule, apply_mode A, rewind_mode M, template< typename... > class Action, template< typename... > class Control > struct duseltronik< Rule, A, M, Action, Control, dusel_mode::CONTROL_AND_APPLY0_BOOL > { template< typename Input, typename... States > static bool match( Input& in, States&&... st ) { auto m = in.template mark< rewind_mode::REQUIRED >(); Control< Rule >::start( static_cast< const Input& >( in ), st... ); if( duseltronik< Rule, A, rewind_mode::ACTIVE, Action, Control, dusel_mode::NOTHING >::match( in, st... ) ) { if( Control< Rule >::template apply0< Action >( static_cast< const Input& >( in ), st... ) ) { Control< Rule >::success( static_cast< const Input& >( in ), st... ); return m( true ); } } Control< Rule >::failure( static_cast< const Input& >( in ), st... ); return false; } }; } // namespace internal } // namespace TAO_PEGTL_NAMESPACE } // namespace tao #endif