/usr/include/pegtl/analysis/analyze_cycles.hh is in pegtl-dev 1.3.1-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 | // Copyright (c) 2014-2015 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/ColinH/PEGTL/
#ifndef PEGTL_ANALYSIS_ANALYZE_CYCLES_HH
#define PEGTL_ANALYSIS_ANALYZE_CYCLES_HH
#include <cassert>
#include <map>
#include <set>
#include <utility>
#include <iostream>
#include "grammar_info.hh"
#include "insert_guard.hh"
namespace pegtl
{
namespace analysis
{
class analyze_cycles_impl
{
protected:
explicit
analyze_cycles_impl( const bool verbose )
: m_verbose( verbose ),
m_problems( 0 )
{ }
const bool m_verbose;
unsigned m_problems;
grammar_info m_info;
std::set< std::string > m_stack;
std::map< std::string, bool > m_cache;
std::map< std::string, bool > m_results;
const std::map< std::string, rule_info >::const_iterator find( const std::string & name ) const
{
const auto iter = m_info.map.find( name );
assert( iter != m_info.map.end() );
return iter;
}
bool work( const std::map< std::string, rule_info >::const_iterator & start, const bool accum )
{
const auto j = m_cache.find( start->first );
if ( j != m_cache.end() ) {
return j->second;
}
if ( const auto g = make_insert_guard( m_stack, start->first ) ) {
switch ( start->second.type ) {
case rule_type::ANY: {
bool a = false;
for ( const auto & r : start->second.rules ) {
a |= work( find( r ), accum || a );
}
return m_cache[ start->first ] = true;
}
case rule_type::OPT: {
bool a = false;
for ( const auto & r : start->second.rules ) {
a |= work( find( r ), accum || a );
}
return m_cache[ start->first ] = false;
}
case rule_type::SEQ: {
bool a = false;
for ( const auto & r : start->second.rules ) {
a |= work( find( r ), accum || a );
}
return m_cache[ start->first ] = a;
}
case rule_type::SOR: {
bool a = true;
for ( const auto & r : start->second.rules ) {
a &= work( find( r ), accum );
}
return m_cache[ start->first ] = a;
}
}
assert( false ); // LCOV_EXCL_LINE
}
if ( ! accum ) {
++m_problems;
if ( m_verbose ) {
std::cout << "problem: cycle without progress detected at rule class " << start->first << std::endl;
}
}
return m_cache[ start->first ] = accum;
}
};
template< typename Grammar >
class analyze_cycles
: private analyze_cycles_impl
{
public:
explicit
analyze_cycles( const bool verbose )
: analyze_cycles_impl( verbose )
{
Grammar::analyze_t::template insert< Grammar >( m_info );
}
std::size_t problems()
{
for ( auto i = m_info.map.begin(); i != m_info.map.end(); ++i ) {
m_results[ i->first ] = work( i, false );
m_cache.clear();
}
return m_problems;
}
template< typename Rule >
bool consumes() const
{
const auto i = m_results.find( internal::demangle< Rule >() );
assert( i != m_results.end() );
return i->second;
}
};
} // analysis
} // pegtl
#endif
|