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_PARSE_ERROR_HPP 5 #define TAO_PEGTL_PARSE_ERROR_HPP 6 7 #include <cstddef> 8 #include <memory> 9 #include <stdexcept> 10 #include <string> 11 #include <string_view> 12 #include <utility> 13 #include <vector> 14 15 #include "config.hpp" 16 #include "position.hpp" 17 18 namespace TAO_PEGTL_NAMESPACE 19 { 20 namespace internal 21 { 22 class parse_error 23 { 24 private: 25 std::string m_msg; 26 std::size_t m_prefix = 0; 27 std::vector< position > m_positions; 28 29 public: parse_error(const char * msg)30 explicit parse_error( const char* msg ) 31 : m_msg( msg ) 32 {} 33 what() const34 [[nodiscard]] const char* what() const noexcept 35 { 36 return m_msg.c_str(); 37 } 38 message() const39 [[nodiscard]] std::string_view message() const noexcept 40 { 41 return { m_msg.data() + m_prefix, m_msg.size() - m_prefix }; 42 } 43 positions() const44 [[nodiscard]] const std::vector< position >& positions() const noexcept 45 { 46 return m_positions; 47 } 48 add_position(position && p)49 void add_position( position&& p ) 50 { 51 const auto prefix = to_string( p ); 52 m_msg = prefix + ": " + m_msg; 53 m_prefix += prefix.size() + 2; 54 m_positions.emplace_back( std::move( p ) ); 55 } 56 }; 57 58 } // namespace internal 59 60 class parse_error 61 : public std::runtime_error 62 { 63 private: 64 std::shared_ptr< internal::parse_error > m_impl; 65 66 public: parse_error(const char * msg,position p)67 parse_error( const char* msg, position p ) 68 : std::runtime_error( msg ), 69 m_impl( std::make_shared< internal::parse_error >( msg ) ) 70 { 71 m_impl->add_position( std::move( p ) ); 72 } 73 parse_error(const std::string & msg,position p)74 parse_error( const std::string& msg, position p ) 75 : parse_error( msg.c_str(), std::move( p ) ) 76 {} 77 78 template< typename ParseInput > parse_error(const char * msg,const ParseInput & in)79 parse_error( const char* msg, const ParseInput& in ) 80 : parse_error( msg, in.position() ) 81 {} 82 83 template< typename ParseInput > parse_error(const std::string & msg,const ParseInput & in)84 parse_error( const std::string& msg, const ParseInput& in ) 85 : parse_error( msg.c_str(), in.position() ) 86 {} 87 what() const88 [[nodiscard]] const char* what() const noexcept override 89 { 90 return m_impl->what(); 91 } 92 message() const93 [[nodiscard]] std::string_view message() const noexcept 94 { 95 return m_impl->message(); 96 } 97 positions() const98 [[nodiscard]] const std::vector< position >& positions() const noexcept 99 { 100 return m_impl->positions(); 101 } 102 add_position(position && p)103 void add_position( position&& p ) 104 { 105 if( m_impl.use_count() > 1 ) { 106 m_impl = std::make_shared< internal::parse_error >( *m_impl ); 107 } 108 m_impl->add_position( std::move( p ) ); 109 } 110 }; 111 112 } // namespace TAO_PEGTL_NAMESPACE 113 114 #endif 115