diff --git a/include/boost/parser/error_handling.hpp b/include/boost/parser/error_handling.hpp index 8528cbdc..00b77db0 100644 --- a/include/boost/parser/error_handling.hpp +++ b/include/boost/parser/error_handling.hpp @@ -153,15 +153,30 @@ namespace boost { namespace parser { return error_handler_result::fail; } - template - void - warn(Iter first, Iter it, Iter last, std::string_view message) const + template + void diagnose( + diagnostic_kind kind, + std::string_view message, + Context const & context, + Iter it) const { - if (!warning_) + callback_type const & cb = + kind == diagnostic_kind::error ? error_ : warning_; + if (!cb) return; std::stringstream ss; - write_formatted_message(ss, filename_, first, it, last, message); - warning_(ss.str()); + parser::write_formatted_message( + ss, filename_, _begin(context), it, _end(context), message); + cb(ss.str()); + } + + template + void diagnose( + diagnostic_kind kind, + std::string_view message, + Context const & context) const + { + diagnose(kind, message, context, _where(context).begin()); } callback_type error_; diff --git a/include/boost/parser/error_handling_fwd.hpp b/include/boost/parser/error_handling_fwd.hpp index f8ec93a9..064063ea 100644 --- a/include/boost/parser/error_handling_fwd.hpp +++ b/include/boost/parser/error_handling_fwd.hpp @@ -50,6 +50,9 @@ namespace boost { namespace parser { int64_t preferred_max_line_length = 80, int64_t max_after_caret = 40); + // TODO: Add info kind as well? + enum class diagnostic_kind { error, warning }; + struct default_error_handler { constexpr default_error_handler() : os_(nullptr) {} @@ -68,11 +71,32 @@ namespace boost { namespace parser { operator()(Iter first, Iter last, parse_error const & e) const { std::ostream & os = os_ ? *os_ : std::cout; - write_formatted_expectation_failure_error_message( + parser::write_formatted_expectation_failure_error_message( os, filename_, first, last, e); return error_handler_result::fail; } + template + void diagnose( + diagnostic_kind kind, + std::string_view message, + Context const & context, + Iter it) const + { + std::ostream & os = os_ ? *os_ : std::cout; + parser::write_formatted_message( + os, filename_, _begin(context), it, _end(context), message); + } + + template + void diagnose( + diagnostic_kind kind, + std::string_view message, + Context const & context) const + { + diagnose(kind, message, context, _where(context).begin()); + } + std::string_view filename_; std::ostream * os_; }; diff --git a/include/boost/parser/parser.hpp b/include/boost/parser/parser.hpp index 79e94d4e..81d48b62 100644 --- a/include/boost/parser/parser.hpp +++ b/include/boost/parser/parser.hpp @@ -95,8 +95,10 @@ namespace boost { namespace parser { using symbol_table_tries_t = std::map>; - template + template inline auto make_context( + Iter first, + Iter last, bool & success, int & indent, ErrorHandler const & error_handler, @@ -104,6 +106,8 @@ namespace boost { namespace parser { symbol_table_tries_t & symbol_table_tries) noexcept { return hana::make_map( + hana::make_pair(hana::type_c, first), + hana::make_pair(hana::type_c, last), hana::make_pair(hana::type_c, &success), hana::make_pair(hana::type_c, global_nope), hana::make_pair(hana::type_c, global_nope), @@ -118,8 +122,10 @@ namespace boost { namespace parser { hana::type_c, &symbol_table_tries)); } - template + template inline auto make_context( + Iter first, + Iter last, bool & success, int & indent, ErrorHandler const & error_handler, @@ -127,6 +133,8 @@ namespace boost { namespace parser { symbol_table_tries_t & symbol_table_tries) noexcept { return hana::make_map( + hana::make_pair(hana::type_c, first), + hana::make_pair(hana::type_c, last), hana::make_pair(hana::type_c, &success), hana::make_pair(hana::type_c, global_nope), hana::make_pair(hana::type_c, global_nope), @@ -141,8 +149,10 @@ namespace boost { namespace parser { hana::type_c, &symbol_table_tries)); } - template + template inline auto make_context( + Iter first, + Iter last, bool & success, int & indent, ErrorHandler const & error_handler, @@ -151,6 +161,8 @@ namespace boost { namespace parser { symbol_table_tries_t & symbol_table_tries) noexcept { return hana::make_map( + hana::make_pair(hana::type_c, first), + hana::make_pair(hana::type_c, last), hana::make_pair(hana::type_c, &success), hana::make_pair(hana::type_c, global_nope), hana::make_pair(hana::type_c, global_nope), @@ -166,10 +178,13 @@ namespace boost { namespace parser { } template< + typename Iter, typename ErrorHandler, typename Callbacks, typename GlobalState> inline auto make_context( + Iter first, + Iter last, bool & success, int & indent, ErrorHandler const & error_handler, @@ -178,6 +193,8 @@ namespace boost { namespace parser { symbol_table_tries_t & symbol_table_tries) noexcept { return hana::make_map( + hana::make_pair(hana::type_c, first), + hana::make_pair(hana::type_c, last), hana::make_pair(hana::type_c, &success), hana::make_pair(hana::type_c, global_nope), hana::make_pair(hana::type_c, global_nope), @@ -859,8 +876,8 @@ namespace boost { namespace parser { rethrow_error_handler eh; nope n; symbol_table_tries_t symbol_table_tries; - auto const context = - make_context(success, indent, eh, n, symbol_table_tries); + auto const context = make_context( + first, last, success, indent, eh, n, symbol_table_tries); while (success) { skip_( hana::false_c, @@ -1370,6 +1387,8 @@ namespace boost { namespace parser { int trace_indent = 0; detail::symbol_table_tries_t symbol_table_tries; auto context = detail::make_context( + first, + last, success, trace_indent, error_handler, @@ -1415,6 +1434,8 @@ namespace boost { namespace parser { int trace_indent = 0; detail::symbol_table_tries_t symbol_table_tries; auto context = detail::make_context( + first, + last, success, trace_indent, error_handler, @@ -1470,6 +1491,8 @@ namespace boost { namespace parser { int trace_indent = 0; detail::symbol_table_tries_t symbol_table_tries; auto context = detail::make_context( + first, + last, success, trace_indent, error_handler, @@ -1519,6 +1542,8 @@ namespace boost { namespace parser { int trace_indent = 0; detail::symbol_table_tries_t symbol_table_tries; auto context = detail::make_context( + first, + last, success, trace_indent, error_handler, @@ -1568,6 +1593,8 @@ namespace boost { namespace parser { int trace_indent = 0; detail::symbol_table_tries_t symbol_table_tries; auto context = detail::make_context( + first, + last, success, trace_indent, error_handler, @@ -1615,6 +1642,8 @@ namespace boost { namespace parser { int trace_indent = 0; detail::symbol_table_tries_t symbol_table_tries; auto context = detail::make_context( + first, + last, success, trace_indent, error_handler, @@ -1649,6 +1678,8 @@ namespace boost { namespace parser { inline constexpr auto val_ = tag; inline constexpr auto attr_ = tag; inline constexpr auto where_ = tag; + inline constexpr auto begin_ = tag; + inline constexpr auto end_ = tag; inline constexpr auto pass_ = tag; inline constexpr auto locals_ = tag; inline constexpr auto params_ = tag; @@ -1670,6 +1701,17 @@ namespace boost { namespace parser { { return *context[where_]; } + // TODO: Document that this is a lie within a skipper. + template + inline decltype(auto) _begin(Context const & context) + { + return context[begin_]; + } + template + inline decltype(auto) _end(Context const & context) + { + return context[end_]; + } template inline decltype(auto) _pass(Context const & context) { @@ -1696,6 +1738,42 @@ namespace boost { namespace parser { return *context[error_handler_]; } + /** Report that the error described in `message` occurred at `location`, + using the context's error handler. */ + template + inline void _report_error( + Context const & context, std::string_view message, Iter location) + { + return context[error_handler_]->diagnose( + diagnostic_kind::error, message, context, location); + } + /** Report that the error described in `message` occurred at + `_where(context).begin()`, using the context's error handler. */ + template + inline void _report_error(Context const & context, std::string_view message) + { + return context[error_handler_]->diagnose( + diagnostic_kind::error, message, context); + } + /** Report that the warning described in `message` occurred at `location`, + using the context's error handler. */ + template + inline void _report_warning( + Context const & context, std::string_view message, Iter location) + { + return context[error_handler_]->diagnose( + diagnostic_kind::warning, message, context, location); + } + /** Report that the warning described in `message` occurred at + `_where(context).begin()`, using the context's error handler. */ + template + inline void + _report_warning(Context const & context, std::string_view message) + { + return context[error_handler_]->diagnose( + diagnostic_kind::warning, message, context); + } + /** TODO */ template inline constexpr detail::param_t _p = {}; diff --git a/include/boost/parser/parser_fwd.hpp b/include/boost/parser/parser_fwd.hpp index 543ddc66..df073508 100644 --- a/include/boost/parser/parser_fwd.hpp +++ b/include/boost/parser/parser_fwd.hpp @@ -23,6 +23,8 @@ namespace boost { namespace parser { struct val_tag; struct attr_tag; struct where_tag; + struct begin_tag; + struct end_tag; struct pass_tag; struct locals_tag; struct rule_params_tag; diff --git a/src/yaml.cpp b/src/yaml.cpp index 04b1fbeb..595e27a1 100644 --- a/src/yaml.cpp +++ b/src/yaml.cpp @@ -110,24 +110,7 @@ namespace boost { namespace yaml { max_recursive_open_count_(max_recursion) {} - void clear_document_state() - { -#if 0 // TODO - stream.block_styles_.flow_styles_.anchors.clear(); - - auto & tags = - stream.block_styles_.flow_styles_.basic_structures_.tags; - tags.clear(); - tags.add( - "!!", - basic_structures_t::tag_t{ - "tag:yaml.org,2002:", iterator_t(), true}); - tags.add("!", basic_structures_t::tag_t{"!", iterator_t(), true}); - - stream.block_styles_.flow_styles_.basic_structures_ - .yaml_directive_seen_ = false; -#endif - } + void clear_document_state() { yaml_directive_seen_ = false; } iterator const first_; int recursive_open_count_ = 0; @@ -1065,15 +1048,12 @@ namespace boost { namespace yaml { // 6.8 Directives auto reserved_directive_warning = [](auto & ctx) { - auto const & error_handler = _error_handler(ctx); - auto const where = _where(ctx); std::string const & directive = _attr(ctx); std::ostringstream oss; oss << "All directives except %YAML and %TAG are " << "reserved for future use. The directive '%" << directive << "' will be ignored"; - error_handler.warn( - _globals(ctx).first_, where.begin(), where.end(), oss.str()); + _report_warning(ctx, oss.str()); }; // [82] @@ -1093,7 +1073,6 @@ namespace boost { namespace yaml { auto check_yaml_version = [](auto & ctx) { auto & globals = _globals(ctx); - auto const & error_handler = _error_handler(ctx); if (globals.yaml_directive_seen_) { #if 0 // TODO @@ -1135,9 +1114,7 @@ namespace boost { namespace yaml { << " directive. This parser recognizes " "YAML 1.2, and so might not work. " "Trying anyway..."; - auto const where = _where(ctx); - error_handler.warn( - globals.first_, where.begin(), where.end(), oss.str()); + _report_warning(ctx, oss.str()); } globals.yaml_directive_seen_ = true; }