1 // Copyright (c) 2019-2020 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_REMATCH_HPP
5 #define TAO_PEGTL_INTERNAL_REMATCH_HPP
6 
7 #include "../config.hpp"
8 
9 #include "skip_control.hpp"
10 
11 #include "../apply_mode.hpp"
12 #include "../memory_input.hpp"
13 #include "../rewind_mode.hpp"
14 
15 namespace tao
16 {
17    namespace TAO_PEGTL_NAMESPACE
18    {
19       namespace internal
20       {
21          template< typename Head, typename... Rules >
22          struct rematch;
23 
24          template< typename Head >
25          struct rematch< Head >
26          {
27             using analyze_t = typename Head::analyze_t;
28 
29             template< apply_mode A,
30                       rewind_mode M,
31                       template< typename... >
32                       class Action,
33                       template< typename... >
34                       class Control,
35                       typename Input,
36                       typename... States >
matchtao::TAO_PEGTL_NAMESPACE::internal::rematch37             static bool match( Input& in, States&&... st )
38             {
39                return Control< Head >::template match< A, M, Action, Control >( in, st... );
40             }
41          };
42 
43          template< typename Head, typename Rule, typename... Rules >
44          struct rematch< Head, Rule, Rules... >
45          {
46             using analyze_t = typename Head::analyze_t;  // NOTE: Rule and Rules are ignored for analyze().
47 
48             template< apply_mode A,
49                       rewind_mode,
50                       template< typename... >
51                       class Action,
52                       template< typename... >
53                       class Control,
54                       typename Input,
55                       typename... States >
matchtao::TAO_PEGTL_NAMESPACE::internal::rematch56             static bool match( Input& in, States&&... st )
57             {
58                auto m = in.template mark< rewind_mode::required >();
59 
60                if( Control< Head >::template match< A, rewind_mode::active, Action, Control >( in, st... ) ) {
61                   memory_input< Input::tracking_mode_v, typename Input::eol_t, typename Input::source_t > i2( m.iterator(), in.current(), in.source() );
62 #ifdef __cpp_fold_expressions
63                   return m( ( Control< Rule >::template match< A, rewind_mode::active, Action, Control >( i2, st... ) && ... && ( i2.restart( m ), Control< Rules >::template match< A, rewind_mode::active, Action, Control >( i2, st... ) ) ) );
64 #else
65                   bool result = Control< Rule >::template match< A, rewind_mode::active, Action, Control >( i2, st... );
66                   using swallow = bool[];
67                   (void)swallow{ result = result && ( i2.restart( m ), Control< Rules >::template match< A, rewind_mode::active, Action, Control >( i2, st... ) )..., true };
68                   return m( result );
69 #endif
70                }
71                return false;
72             }
73          };
74 
75          template< typename Head, typename... Rules >
76          struct skip_control< rematch< Head, Rules... > > : std::true_type
77          {
78          };
79 
80       }  // namespace internal
81 
82    }  // namespace TAO_PEGTL_NAMESPACE
83 
84 }  // namespace tao
85 
86 #endif
87