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_UNTIL_HPP
5 #define TAO_PEGTL_INTERNAL_UNTIL_HPP
6 
7 #include "../config.hpp"
8 
9 #include "bytes.hpp"
10 #include "eof.hpp"
11 #include "not_at.hpp"
12 #include "rule_conjunction.hpp"
13 #include "skip_control.hpp"
14 #include "star.hpp"
15 
16 #include "../apply_mode.hpp"
17 #include "../rewind_mode.hpp"
18 
19 #include "../analysis/generic.hpp"
20 
21 namespace tao
22 {
23    namespace TAO_PEGTL_NAMESPACE
24    {
25       namespace internal
26       {
27          template< typename Cond, typename... Rules >
28          struct until;
29 
30          template< typename Cond >
31          struct until< Cond >
32          {
33             using analyze_t = analysis::generic< analysis::rule_type::SEQ, star< not_at< Cond >, not_at< eof >, bytes< 1 > >, Cond >;
34 
35             template< apply_mode A,
36                       rewind_mode M,
37                       template< typename... > class Action,
38                       template< typename... > class Control,
39                       typename Input,
40                       typename... States >
matchtao::TAO_PEGTL_NAMESPACE::internal::until41             static bool match( Input& in, States&&... st )
42             {
43                auto m = in.template mark< M >();
44 
45                while( !Control< Cond >::template match< A, rewind_mode::REQUIRED, Action, Control >( in, st... ) ) {
46                   if( in.empty() ) {
47                      return false;
48                   }
49                   in.bump();
50                }
51                return m( true );
52             }
53          };
54 
55          template< typename Cond, typename... Rules >
56          struct until
57          {
58             using analyze_t = analysis::generic< analysis::rule_type::SEQ, star< not_at< Cond >, not_at< eof >, Rules... >, Cond >;
59 
60             template< apply_mode A,
61                       rewind_mode M,
62                       template< typename... > class Action,
63                       template< typename... > class Control,
64                       typename Input,
65                       typename... States >
matchtao::TAO_PEGTL_NAMESPACE::internal::until66             static bool match( Input& in, States&&... st )
67             {
68                auto m = in.template mark< M >();
69                using m_t = decltype( m );
70 
71                while( !Control< Cond >::template match< A, rewind_mode::REQUIRED, Action, Control >( in, st... ) ) {
72                   if( !rule_conjunction< Rules... >::template match< A, m_t::next_rewind_mode, Action, Control >( in, st... ) ) {
73                      return false;
74                   }
75                }
76                return m( true );
77             }
78          };
79 
80          template< typename Cond, typename... Rules >
81          struct skip_control< until< Cond, Rules... > > : std::true_type
82          {
83          };
84 
85       }  // namespace internal
86 
87    }  // namespace TAO_PEGTL_NAMESPACE
88 
89 }  // namespace tao
90 
91 #endif
92