/src/Fast-DDS/thirdparty/taocpp-pegtl/pegtl/analysis/analyze_cycles.hpp
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright (c) 2014-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_ANALYSIS_ANALYZE_CYCLES_HPP |
5 | | #define TAO_PEGTL_ANALYSIS_ANALYZE_CYCLES_HPP |
6 | | |
7 | | #include <cassert> |
8 | | |
9 | | #include <map> |
10 | | #include <set> |
11 | | #include <stdexcept> |
12 | | |
13 | | #include <iostream> |
14 | | #include <utility> |
15 | | |
16 | | #include "../config.hpp" |
17 | | |
18 | | #include "grammar_info.hpp" |
19 | | #include "insert_guard.hpp" |
20 | | |
21 | | namespace tao |
22 | | { |
23 | | namespace TAO_PEGTL_NAMESPACE |
24 | | { |
25 | | namespace analysis |
26 | | { |
27 | | class analyze_cycles_impl |
28 | | { |
29 | | protected: |
30 | | explicit analyze_cycles_impl( const bool verbose ) noexcept |
31 | 0 | : m_verbose( verbose ), |
32 | 0 | m_problems( 0 ) |
33 | 0 | { |
34 | 0 | } |
35 | | |
36 | | const bool m_verbose; |
37 | | unsigned m_problems; |
38 | | grammar_info m_info; |
39 | | std::set< std::string > m_stack; |
40 | | std::map< std::string, bool > m_cache; |
41 | | std::map< std::string, bool > m_results; |
42 | | |
43 | | std::map< std::string, rule_info >::const_iterator find( const std::string& name ) const noexcept |
44 | 0 | { |
45 | 0 | const auto iter = m_info.map.find( name ); |
46 | 0 | assert( iter != m_info.map.end() ); |
47 | 0 | return iter; |
48 | 0 | } |
49 | | |
50 | | bool work( const std::map< std::string, rule_info >::const_iterator& start, const bool accum ) |
51 | 0 | { |
52 | 0 | const auto j = m_cache.find( start->first ); |
53 | |
|
54 | 0 | if( j != m_cache.end() ) { |
55 | 0 | return j->second; |
56 | 0 | } |
57 | 0 | if( const auto g = make_insert_guard( m_stack, start->first ) ) { |
58 | 0 | switch( start->second.type ) { |
59 | 0 | case rule_type::any: { |
60 | 0 | bool a = false; |
61 | 0 | for( const auto& r : start->second.rules ) { |
62 | 0 | a = a || work( find( r ), accum || a ); |
63 | 0 | } |
64 | 0 | return m_cache[ start->first ] = true; |
65 | 0 | } |
66 | 0 | case rule_type::opt: { |
67 | 0 | bool a = false; |
68 | 0 | for( const auto& r : start->second.rules ) { |
69 | 0 | a = a || work( find( r ), accum || a ); |
70 | 0 | } |
71 | 0 | return m_cache[ start->first ] = false; |
72 | 0 | } |
73 | 0 | case rule_type::seq: { |
74 | 0 | bool a = false; |
75 | 0 | for( const auto& r : start->second.rules ) { |
76 | 0 | a = a || work( find( r ), accum || a ); |
77 | 0 | } |
78 | 0 | return m_cache[ start->first ] = a; |
79 | 0 | } |
80 | 0 | case rule_type::sor: { |
81 | 0 | bool a = true; |
82 | 0 | for( const auto& r : start->second.rules ) { |
83 | 0 | a = a && work( find( r ), accum ); |
84 | 0 | } |
85 | 0 | return m_cache[ start->first ] = a; |
86 | 0 | } |
87 | 0 | } |
88 | 0 | throw std::logic_error( "code should be unreachable: invalid rule_type value" ); // NOLINT, LCOV_EXCL_LINE |
89 | 0 | } |
90 | 0 | if( !accum ) { |
91 | 0 | ++m_problems; |
92 | 0 | if( m_verbose ) { |
93 | 0 | std::cout << "problem: cycle without progress detected at rule class " << start->first << std::endl; // LCOV_EXCL_LINE |
94 | 0 | } |
95 | 0 | } |
96 | 0 | return m_cache[ start->first ] = accum; |
97 | 0 | } |
98 | | }; |
99 | | |
100 | | template< typename Grammar > |
101 | | class analyze_cycles |
102 | | : private analyze_cycles_impl |
103 | | { |
104 | | public: |
105 | | explicit analyze_cycles( const bool verbose ) |
106 | 0 | : analyze_cycles_impl( verbose ) |
107 | 0 | { |
108 | 0 | Grammar::analyze_t::template insert< Grammar >( m_info ); |
109 | 0 | } |
110 | | |
111 | | std::size_t problems() |
112 | 0 | { |
113 | 0 | for( auto i = m_info.map.begin(); i != m_info.map.end(); ++i ) { |
114 | 0 | m_results[ i->first ] = work( i, false ); |
115 | 0 | m_cache.clear(); |
116 | 0 | } |
117 | 0 | return m_problems; |
118 | 0 | } |
119 | | |
120 | | template< typename Rule > |
121 | | bool consumes() const noexcept |
122 | | { |
123 | | const auto i = m_results.find( internal::demangle< Rule >() ); |
124 | | assert( i != m_results.end() ); |
125 | | return i->second; |
126 | | } |
127 | | }; |
128 | | |
129 | | } // namespace analysis |
130 | | |
131 | | } // namespace TAO_PEGTL_NAMESPACE |
132 | | |
133 | | } // namespace tao |
134 | | |
135 | | #endif |