#pragma once #include #include #include #include #include #include #include #include #include #include namespace ovdl::detail { template struct _ReportError { OutputIterator _iter; lexy::visualization_options _opts; const char* _path; struct _sink { OutputIterator _iter; lexy::visualization_options _opts; const char* _path; std::size_t _count; std::vector _errors; using return_type = std::vector; template void operator()(const lexy::error_context& context, const lexy::error& error) { _iter = lexy_ext::_detail::write_error(_iter, context, error, _opts, _path); ++_count; // Convert the context location and error location into line/column information. auto context_location = lexy::get_input_location(context.input(), context.position()); auto location = lexy::get_input_location(context.input(), error.position(), context_location.anchor()); std::basic_stringstream message; // Write the main annotation. if constexpr (std::is_same_v) { auto string = lexy::_detail::make_literal_lexeme(error.string(), error.length()); message << "expected '" << string.data() << '\''; } else if constexpr (std::is_same_v) { auto string = lexy::_detail::make_literal_lexeme(error.string(), error.length()); message << "expected keyword '" << string.data() << '\''; } else if constexpr (std::is_same_v) { message << "expected " << error.name(); } else { message << error.message(); } _errors.push_back( ParseError { ParseError::Type::Fatal, // TODO: distinguish recoverable errors from fatal errors std::move(message.str()), 0, // TODO: implement proper error codes ParseData { context.production(), context_location.line_nr(), context_location.column_nr(), }, location.line_nr(), location.column_nr(), }); } return_type finish() && { if (_count != 0) *_iter++ = '\n'; return _errors; } }; constexpr auto sink() const { return _sink { _iter, _opts, _path, 0 }; } /// Specifies a path that will be printed alongside the diagnostic. constexpr _ReportError path(const char* path) const { return { _iter, _opts, path }; } /// Specifies an output iterator where the errors are written to. template constexpr _ReportError to(OI out) const { return { out, _opts, _path }; } /// Overrides visualization options. constexpr _ReportError opts(lexy::visualization_options opts) const { return { _iter, opts, _path }; } }; constexpr auto ReporError = _ReportError {}; }