1 // Copyright (c) 2014-2018 Dr. Colin Hirsch and Daniel Frey
2 // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/
3 
4 #ifndef TAO_PEGTL_INTERNAL_DUSELTRONIK_HPP
5 #define TAO_PEGTL_INTERNAL_DUSELTRONIK_HPP
6 
7 #include "../apply_mode.hpp"
8 #include "../config.hpp"
9 #include "../rewind_mode.hpp"
10 
11 #include "dusel_mode.hpp"
12 
13 namespace tao
14 {
15    namespace TAO_PEGTL_NAMESPACE
16    {
17       namespace internal
18       {
19          template< typename Rule,
20                    apply_mode A,
21                    rewind_mode M,
22                    template< typename... > class Action,
23                    template< typename... > class Control,
24                    dusel_mode = dusel_mode::NOTHING >
25          struct duseltronik;
26 
27          template< typename Rule,
28                    apply_mode A,
29                    rewind_mode M,
30                    template< typename... > class Action,
31                    template< typename... > class Control >
32          struct duseltronik< Rule, A, M, Action, Control, dusel_mode::NOTHING >
33          {
34             template< typename Input, typename... States >
matchtao::TAO_PEGTL_NAMESPACE::internal::duseltronik35             static auto match( Input& in, States&&... st )
36                -> decltype( Rule::template match< A, M, Action, Control >( in, st... ), true )
37             {
38                return Rule::template match< A, M, Action, Control >( in, st... );
39             }
40 
41             // NOTE: The additional "int = 0" is a work-around for missing expression SFINAE in VS2015.
42 
43             template< typename Input, typename... States, int = 0 >
matchtao::TAO_PEGTL_NAMESPACE::internal::duseltronik44             static auto match( Input& in, States&&... /*unused*/ )
45                -> decltype( Rule::match( in ), true )
46             {
47                return Rule::match( in );
48             }
49          };
50 
51          template< typename Rule,
52                    apply_mode A,
53                    rewind_mode M,
54                    template< typename... > class Action,
55                    template< typename... > class Control >
56          struct duseltronik< Rule, A, M, Action, Control, dusel_mode::CONTROL >
57          {
58             template< typename Input, typename... States >
matchtao::TAO_PEGTL_NAMESPACE::internal::duseltronik59             static bool match( Input& in, States&&... st )
60             {
61                Control< Rule >::start( static_cast< const Input& >( in ), st... );
62 
63                if( duseltronik< Rule, A, M, Action, Control, dusel_mode::NOTHING >::match( in, st... ) ) {
64                   Control< Rule >::success( static_cast< const Input& >( in ), st... );
65                   return true;
66                }
67                Control< Rule >::failure( static_cast< const Input& >( in ), st... );
68                return false;
69             }
70          };
71 
72          template< typename Rule,
73                    apply_mode A,
74                    rewind_mode M,
75                    template< typename... > class Action,
76                    template< typename... > class Control >
77          struct duseltronik< Rule, A, M, Action, Control, dusel_mode::CONTROL_AND_APPLY_VOID >
78          {
79             template< typename Input, typename... States >
matchtao::TAO_PEGTL_NAMESPACE::internal::duseltronik80             static bool match( Input& in, States&&... st )
81             {
82                auto m = in.template mark< rewind_mode::REQUIRED >();
83 
84                Control< Rule >::start( static_cast< const Input& >( in ), st... );
85 
86                if( duseltronik< Rule, A, rewind_mode::ACTIVE, Action, Control, dusel_mode::NOTHING >::match( in, st... ) ) {
87                   Control< Rule >::template apply< Action >( m.iterator(), static_cast< const Input& >( in ), st... );
88                   Control< Rule >::success( static_cast< const Input& >( in ), st... );
89                   return m( true );
90                }
91                Control< Rule >::failure( static_cast< const Input& >( in ), st... );
92                return false;
93             }
94          };
95 
96          template< typename Rule,
97                    apply_mode A,
98                    rewind_mode M,
99                    template< typename... > class Action,
100                    template< typename... > class Control >
101          struct duseltronik< Rule, A, M, Action, Control, dusel_mode::CONTROL_AND_APPLY_BOOL >
102          {
103             template< typename Input, typename... States >
matchtao::TAO_PEGTL_NAMESPACE::internal::duseltronik104             static bool match( Input& in, States&&... st )
105             {
106                auto m = in.template mark< rewind_mode::REQUIRED >();
107 
108                Control< Rule >::start( static_cast< const Input& >( in ), st... );
109 
110                if( duseltronik< Rule, A, rewind_mode::ACTIVE, Action, Control, dusel_mode::NOTHING >::match( in, st... ) ) {
111                   if( Control< Rule >::template apply< Action >( m.iterator(), static_cast< const Input& >( in ), st... ) ) {
112                      Control< Rule >::success( static_cast< const Input& >( in ), st... );
113                      return m( true );
114                   }
115                }
116                Control< Rule >::failure( static_cast< const Input& >( in ), st... );
117                return false;
118             }
119          };
120 
121          template< typename Rule,
122                    apply_mode A,
123                    rewind_mode M,
124                    template< typename... > class Action,
125                    template< typename... > class Control >
126          struct duseltronik< Rule, A, M, Action, Control, dusel_mode::CONTROL_AND_APPLY0_VOID >
127          {
128             template< typename Input, typename... States >
matchtao::TAO_PEGTL_NAMESPACE::internal::duseltronik129             static bool match( Input& in, States&&... st )
130             {
131                Control< Rule >::start( static_cast< const Input& >( in ), st... );
132 
133                if( duseltronik< Rule, A, M, Action, Control, dusel_mode::NOTHING >::match( in, st... ) ) {
134                   Control< Rule >::template apply0< Action >( static_cast< const Input& >( in ), st... );
135                   Control< Rule >::success( static_cast< const Input& >( in ), st... );
136                   return true;
137                }
138                Control< Rule >::failure( static_cast< const Input& >( in ), st... );
139                return false;
140             }
141          };
142 
143          template< typename Rule,
144                    apply_mode A,
145                    rewind_mode M,
146                    template< typename... > class Action,
147                    template< typename... > class Control >
148          struct duseltronik< Rule, A, M, Action, Control, dusel_mode::CONTROL_AND_APPLY0_BOOL >
149          {
150             template< typename Input, typename... States >
matchtao::TAO_PEGTL_NAMESPACE::internal::duseltronik151             static bool match( Input& in, States&&... st )
152             {
153                auto m = in.template mark< rewind_mode::REQUIRED >();
154 
155                Control< Rule >::start( static_cast< const Input& >( in ), st... );
156 
157                if( duseltronik< Rule, A, rewind_mode::ACTIVE, Action, Control, dusel_mode::NOTHING >::match( in, st... ) ) {
158                   if( Control< Rule >::template apply0< Action >( static_cast< const Input& >( in ), st... ) ) {
159                      Control< Rule >::success( static_cast< const Input& >( in ), st... );
160                      return m( true );
161                   }
162                }
163                Control< Rule >::failure( static_cast< const Input& >( in ), st... );
164                return false;
165             }
166          };
167 
168       }  // namespace internal
169 
170    }  // namespace TAO_PEGTL_NAMESPACE
171 
172 }  // namespace tao
173 
174 #endif
175