/* * Copyright (c) 2022, Ali Mohammad Pur * Copyright (c) 2026, the Ladybird developers. * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include #include #include #include #include #include #include #include #include #include #include #include namespace XML { struct Expectation { StringView expected; }; struct ParseError { LineTrackingLexer::Position position {}; Variant error; }; struct Listener { virtual ~Listener() { } virtual ErrorOr set_source(ByteString) { return {}; } virtual void set_doctype(XML::Doctype) { } virtual void document_start() { } virtual void document_end() { } virtual void element_start(Name const&, OrderedHashMap const&) { } virtual void element_end(Name const&) { } virtual void text(StringView) { } virtual void cdata_section(StringView) { } virtual void processing_instruction(StringView, StringView) { } virtual void comment(StringView) { } virtual void error(ParseError const&) { } }; class XML_API Parser { public: struct Options { bool preserve_cdata { true }; bool preserve_comments { false }; bool treat_errors_as_fatal { true }; Function(StringView)> resolve_named_html_entity {}; }; Parser(StringView source, Options options) : m_source(source) , m_options(move(options)) { } explicit Parser(StringView source) : m_source(source) { } ErrorOr parse(); ErrorOr parse_with_listener(Listener&); Vector const& parse_error_causes() const { return m_parse_errors; } private: StringView m_source; Options m_options; Vector m_parse_errors; }; } template<> struct AK::Formatter : public AK::Formatter { ErrorOr format(FormatBuilder& builder, XML::ParseError const& error) { auto error_string = error.error.visit( [](ByteString const& error) -> ByteString { return error; }, [](XML::Expectation const& expectation) -> ByteString { return ByteString::formatted("Expected {}", expectation.expected); }); return Formatter::format(builder, "{} at line: {}, col: {} (offset {})"sv, error_string, error.position.line, error.position.column, error.position.offset); } };