#pragma once #include #include #include #include #include namespace ovdl { template struct BasicDiagnosticLogger; } namespace ovdl::error { enum class [[nodiscard]] ErrorKind : std::uint64_t { Root, BufferError, // Parse Error // ExpectedLiteral, ExpectedKeyword, ExpectedCharClass, GenericParseError, FirstParseError = ExpectedLiteral, LastParseError = GenericParseError, // Semantic Diagnostic // SemanticError, SemanticWarning, SemanticInfo, SemanticDebug, SemanticFixit, SemanticHelp, FirstSemantic = SemanticError, LastSemantic = SemanticHelp, // Annotated Error // FirstAnnotatedError = FirstParseError, LastAnnotatedError = LastSemantic, PrimaryAnnotation, SecondaryAnnotation, FirstAnnotation = PrimaryAnnotation, LastAnnotation = SecondaryAnnotation, }; static constexpr std::string_view get_kind_name(ErrorKind kind) { switch (kind) { using enum ErrorKind; case ExpectedLiteral: return "expected literal"; case ExpectedKeyword: return "expected keyword"; case ExpectedCharClass: return "expected char class"; case GenericParseError: return "generic"; default: detail::unreachable(); } } struct Error : dryad::abstract_node_all { const char* message() const { return _message; } protected: DRYAD_ABSTRACT_NODE_CTOR(Error); void _set_message(const char* message) { _message = message; } const char* _message = ""; template friend struct ovdl::BasicDiagnosticLogger; }; using ErrorList = dryad::unlinked_node_list; struct Annotation; using AnnotationList = dryad::unlinked_node_list; struct Root : dryad::basic_node> { explicit Root(dryad::node_ctor ctor) : node_base(ctor) {} DRYAD_CHILD_NODE_RANGE_GETTER(Error, errors, nullptr, this->node_after(_last)); void insert_back(Error* error) { insert_child_after(_last, error); _last = error; } private: Error* _last = nullptr; }; struct BufferError : dryad::basic_node { explicit BufferError(dryad::node_ctor ctor, const char* message) : node_base(ctor) { _set_message(message); } explicit BufferError(dryad::node_ctor ctor) : node_base(ctor) {} }; struct Annotation : dryad::abstract_node_range { protected: explicit Annotation(dryad::node_ctor ctor, ErrorKind kind, const char* message) : node_base(ctor, kind) { _set_message(message); } }; struct AnnotatedError : dryad::abstract_node_range, ErrorKind::FirstAnnotatedError, ErrorKind::LastAnnotatedError> { DRYAD_CHILD_NODE_RANGE_GETTER(Annotation, annotations, nullptr, this->node_after(_last_annotation)); void push_back(Annotation* annotation); void push_back(AnnotationList p_annotations); protected: explicit AnnotatedError(dryad::node_ctor ctor, ErrorKind kind) : node_base(ctor, kind) { insert_child_list_after(nullptr, AnnotationList {}); _last_annotation = nullptr; } private: Annotation* _last_annotation; }; struct ParseError : dryad::abstract_node_range { std::string_view production_name() const { return _production_name; } protected: explicit ParseError(dryad::node_ctor ctor, ErrorKind kind, const char* message, const char* production_name) : node_base(ctor, kind), _production_name(production_name) { _set_message(message); }; const char* _production_name; }; template struct _ParseError_t : dryad::basic_node { using base_node = dryad::basic_node; explicit _ParseError_t(dryad::node_ctor ctor, const char* message, const char* production_name) : base_node(ctor, message, production_name) {} }; using ExpectedLiteral = _ParseError_t; using ExpectedKeyword = _ParseError_t; using ExpectedCharClass = _ParseError_t; using GenericParseError = _ParseError_t; struct Semantic : dryad::abstract_node_range { protected: explicit Semantic(dryad::node_ctor ctor, ErrorKind kind) : node_base(ctor, kind) {}; explicit Semantic(dryad::node_ctor ctor, ErrorKind kind, const char* message) : node_base(ctor, kind) { _set_message(message); }; explicit Semantic(dryad::node_ctor ctor, ErrorKind kind, const char* message, AnnotationList annotations) : node_base(ctor, kind) { push_back(annotations); _set_message(message); }; }; template struct _SemanticError_t : dryad::basic_node { using base_node = dryad::basic_node; explicit _SemanticError_t(dryad::node_ctor ctor) : base_node(ctor) {} explicit _SemanticError_t(dryad::node_ctor ctor, const char* message) : base_node(ctor, message) {} explicit _SemanticError_t(dryad::node_ctor ctor, const char* message, AnnotationList annotations) : base_node(ctor, message, annotations) {} }; using SemanticError = _SemanticError_t; using SemanticWarning = _SemanticError_t; using SemanticInfo = _SemanticError_t; using SemanticDebug = _SemanticError_t; using SemanticFixit = _SemanticError_t; using SemanticHelp = _SemanticError_t; template struct _Annotation_t : dryad::basic_node { explicit _Annotation_t(dryad::node_ctor ctor, const char* message) : dryad::basic_node(ctor, message) {} }; using PrimaryAnnotation = _Annotation_t; using SecondaryAnnotation = _Annotation_t; inline void AnnotatedError::push_back(Annotation* annotation) { insert_child_after(_last_annotation, annotation); _last_annotation = annotation; } inline void AnnotatedError::push_back(AnnotationList p_annotations) { if (p_annotations.empty()) return; insert_child_list_after(annotations().end().deref(), p_annotations); _last_annotation = *p_annotations.end(); } }