From 7440a5d1433eec4bf87e3723022db187e7f61b1a Mon Sep 17 00:00:00 2001 From: Spartan322 Date: Fri, 28 Jul 2023 00:52:00 -0400 Subject: Rework Grammar and Parser Add proper headless binary construction: Includes basic validation Add Error and Warning structs to Parser Add FileNode pointer getter to Parser Change all `char8_t*` and `const char8_t` to `const char*` in Parser Add Parser move operators and Parser deconstructor Add BufferHandler PIMPL object to Parser Add UTF-8 file Warning to v2script Add proper Grammar value retrieval Add AbstractSyntaxTree for v2script data parser: Has compile-time embedded type information accessible at compile-time and runtime Has Tab-based print functionality Fix wrong environment reference for headless construction in SConstruct Add error retrieval Add BasicCallbackOStreamBuffer for callback streaming Add CallbackStreamBuffer for char Add CallbackWStreamBuffer for wchar_t Add BasicCallbackStream Add CallbackStream for char Add CallbackWStream for wchar_t Add grammar for events and decisions Add event_parse to Parser Add decision_parse to Parser Add .clang-format Ignore dirty lexy module Add CSV parser and grammar: Creates std::vector for a list of lines Add BasicParser and BasicBufferHandler to reduce code reduplication --- include/openvic-dataloader/ParseData.hpp | 11 + include/openvic-dataloader/ParseError.hpp | 20 ++ include/openvic-dataloader/ParseWarning.hpp | 10 + include/openvic-dataloader/csv/LineObject.hpp | 84 ++++++++ include/openvic-dataloader/csv/Parser.hpp | 42 ++++ include/openvic-dataloader/detail/BasicParser.hpp | 37 ++++ .../openvic-dataloader/detail/CallbackOStream.hpp | 100 +++++++++ include/openvic-dataloader/detail/Concepts.hpp | 22 ++ include/openvic-dataloader/detail/SelfType.hpp | 28 +++ include/openvic-dataloader/detail/TypeName.hpp | 52 +++++ .../v2script/AbstractSyntaxTree.hpp | 224 +++++++++++++++++++++ include/openvic-dataloader/v2script/Parser.hpp | 58 ++++-- 12 files changed, 675 insertions(+), 13 deletions(-) create mode 100644 include/openvic-dataloader/ParseData.hpp create mode 100644 include/openvic-dataloader/ParseError.hpp create mode 100644 include/openvic-dataloader/ParseWarning.hpp create mode 100644 include/openvic-dataloader/csv/LineObject.hpp create mode 100644 include/openvic-dataloader/csv/Parser.hpp create mode 100644 include/openvic-dataloader/detail/BasicParser.hpp create mode 100644 include/openvic-dataloader/detail/CallbackOStream.hpp create mode 100644 include/openvic-dataloader/detail/Concepts.hpp create mode 100644 include/openvic-dataloader/detail/SelfType.hpp create mode 100644 include/openvic-dataloader/detail/TypeName.hpp create mode 100644 include/openvic-dataloader/v2script/AbstractSyntaxTree.hpp (limited to 'include/openvic-dataloader') diff --git a/include/openvic-dataloader/ParseData.hpp b/include/openvic-dataloader/ParseData.hpp new file mode 100644 index 0000000..8bec7d2 --- /dev/null +++ b/include/openvic-dataloader/ParseData.hpp @@ -0,0 +1,11 @@ +#pragma once + +#include + +namespace ovdl { + struct ParseData { + const std::string production_name; + const unsigned int context_start_line; + const unsigned int context_start_column; + }; +} \ No newline at end of file diff --git a/include/openvic-dataloader/ParseError.hpp b/include/openvic-dataloader/ParseError.hpp new file mode 100644 index 0000000..9e4541e --- /dev/null +++ b/include/openvic-dataloader/ParseError.hpp @@ -0,0 +1,20 @@ +#pragma once + +#include + +#include + +namespace ovdl { + struct ParseError { + const enum class Type : unsigned char { + Recoverable, + Fatal + } type; + const std::string message; + const int error_value; + const ParseData parse_data; + const unsigned int start_line; + const unsigned int start_column; + }; + +} \ No newline at end of file diff --git a/include/openvic-dataloader/ParseWarning.hpp b/include/openvic-dataloader/ParseWarning.hpp new file mode 100644 index 0000000..307599f --- /dev/null +++ b/include/openvic-dataloader/ParseWarning.hpp @@ -0,0 +1,10 @@ +#pragma once + +#include + +namespace ovdl { + struct ParseWarning { + const std::string message; + const int warning_value; + }; +} \ No newline at end of file diff --git a/include/openvic-dataloader/csv/LineObject.hpp b/include/openvic-dataloader/csv/LineObject.hpp new file mode 100644 index 0000000..0494ffb --- /dev/null +++ b/include/openvic-dataloader/csv/LineObject.hpp @@ -0,0 +1,84 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace ovdl::csv { + /// LineObject should be able to recognize the differences between: + /// Input -> Indexes == "" + /// ;;a;b;c;; -> 0,1,5,6+ == "" + /// a;b;c -> 3+ == "" + /// a;;b;c;; -> 1,4,5+ == "" + /// a;b;;c; -> 2,4+ == "" + /// a;b;c;; -> 3,4+ == "" + /// a;b;c; -> 3+ == "" + /// ;a;b;c -> 0,4+ == "" + /// + /// If this is incorrect, please report an issue. + class LineObject final : public std::vector> { + public: + // Stored position of value + using position_type = std::uint32_t; + // Value + using inner_value_type = std::string; + using container_type = std::vector>; + + constexpr LineObject() = default; + constexpr LineObject(LineObject&) = default; + constexpr LineObject(LineObject&&) = default; + constexpr LineObject(const LineObject&) = default; + + constexpr LineObject& operator=(const LineObject& other) = default; + constexpr LineObject& operator=(LineObject&& other) = default; + + constexpr ~LineObject() = default; + + constexpr LineObject(std::initializer_list pos_and_val) : container_type(pos_and_val) { + } + + constexpr LineObject(position_type prefix_end, std::initializer_list pos_and_val, position_type suffix_end = 0) + : container_type(pos_and_val), + _prefix_end(prefix_end), + _suffix_end(suffix_end) { + } + + /// Special Functionality + /// Retrieves value, produces "" for empty values + constexpr std::string_view get_value_for(std::size_t position) const { + if (position <= _prefix_end || position >= _suffix_end) return ""; + for (const auto& [pos, val] : *this) { + if (pos == position) return val; + } + return ""; + } + /// Tries to retrieve reference, produces nullopt for empty values + constexpr std::optional> try_get_string_at(std::size_t position) const { + if (position <= _prefix_end || position > _suffix_end) return std::nullopt; + for (const auto& [pos, val] : *this) { + if (pos == position) return std::cref(val); + } + return std::nullopt; + } + + constexpr position_type prefix_end() const { return _prefix_end; } + constexpr void set_prefix_end(position_type value) { _prefix_end = value; } + + constexpr position_type suffix_end() const { return _suffix_end; } + constexpr void set_suffix_end(position_type value) { _suffix_end = value; } + + constexpr std::size_t value_count() const { return _suffix_end; } + + private: + // Should be position of first valid value on line + position_type _prefix_end; + // Should be position after last value or position after last seperator + position_type _suffix_end; + }; +} \ No newline at end of file diff --git a/include/openvic-dataloader/csv/Parser.hpp b/include/openvic-dataloader/csv/Parser.hpp new file mode 100644 index 0000000..3497864 --- /dev/null +++ b/include/openvic-dataloader/csv/Parser.hpp @@ -0,0 +1,42 @@ +#pragma once + +#include +#include + +namespace ovdl::csv { + class Parser final : public detail::BasicParser { + public: + Parser(); + + static Parser from_buffer(const char* data, std::size_t size); + static Parser from_buffer(const char* start, const char* end); + static Parser from_string(const std::string_view string); + static Parser from_file(const char* path); + static Parser from_file(const std::filesystem::path& path); + + constexpr Parser& load_from_buffer(const char* data, std::size_t size); + constexpr Parser& load_from_buffer(const char* start, const char* end); + constexpr Parser& load_from_string(const std::string_view string); + constexpr Parser& load_from_file(const char* path); + Parser& load_from_file(const std::filesystem::path& path); + + constexpr Parser& load_from_file(const detail::Has_c_str auto& path); + + bool parse_csv(); + + const std::vector get_lines() const; + + Parser(Parser&&); + Parser& operator=(Parser&&); + + ~Parser(); + + private: + class BufferHandler; + std::unique_ptr _buffer_handler; + std::vector _lines; + + template + constexpr void _run_load_func(detail::LoadCallback auto func, Args... args); + }; +} \ No newline at end of file diff --git a/include/openvic-dataloader/detail/BasicParser.hpp b/include/openvic-dataloader/detail/BasicParser.hpp new file mode 100644 index 0000000..5493804 --- /dev/null +++ b/include/openvic-dataloader/detail/BasicParser.hpp @@ -0,0 +1,37 @@ +#pragma once + +#include +#include +#include +#include + +#include +#include +#include + +namespace ovdl::detail { + class BasicParser { + public: + BasicParser(); + + void set_error_log_to_null(); + void set_error_log_to_stderr(); + void set_error_log_to_stdout(); + void set_error_log_to(std::basic_ostream& stream); + + bool has_error() const; + bool has_fatal_error() const; + bool has_warning() const; + + const std::vector& get_errors() const; + const std::vector& get_warnings() const; + + protected: + std::vector _errors; + std::vector _warnings; + + std::reference_wrapper _error_stream; + const char* _file_path; + bool _has_fatal_error = false; + }; +} \ No newline at end of file diff --git a/include/openvic-dataloader/detail/CallbackOStream.hpp b/include/openvic-dataloader/detail/CallbackOStream.hpp new file mode 100644 index 0000000..641d53f --- /dev/null +++ b/include/openvic-dataloader/detail/CallbackOStream.hpp @@ -0,0 +1,100 @@ +#pragma once + +#include +#include +#include +#include + +namespace ovdl::detail { + template> + class BasicCallbackStreamBuffer : public std::basic_streambuf { + public: + using base_type = std::basic_streambuf; + using callback_type = Callback; + using char_type = typename base_type::char_type; + using int_type = typename base_type::int_type; + + BasicCallbackStreamBuffer(Callback cb, void* user_data = nullptr) + : _callback(cb), + _user_data(user_data) {} + + protected: + std::streamsize xsputn(const char_type* s, std::streamsize n) override { + if constexpr (std::is_same_v) { + _callback(s, n, _user_data); + return n; + } else { + return _callback(s, n, _user_data); // returns the number of characters successfully written. + } + }; + + int_type overflow(int_type ch) override { + if constexpr (std::is_same_v) { + _callback(&ch, 1, _user_data); + return 1; + } else { + return _callback(&ch, 1, _user_data); // returns the number of characters successfully written. + } + } + + private: + Callback _callback; + void* _user_data; + }; + + template + class CallbackStreamBuffer : public BasicCallbackStreamBuffer { + public: + using base_type = BasicCallbackStreamBuffer; + using callback_type = Callback; + using char_type = typename base_type::char_type; + using int_type = typename base_type::int_type; + + CallbackStreamBuffer(Callback cb, void* user_data = nullptr) : base_type(cb, user_data) {} + }; + + template + class CallbackWStreamBuffer : public BasicCallbackStreamBuffer { + public: + using base_type = BasicCallbackStreamBuffer; + using callback_type = Callback; + using char_type = typename base_type::char_type; + using int_type = typename base_type::int_type; + + CallbackWStreamBuffer(Callback cb, void* user_data = nullptr) : base_type(cb, user_data) {} + }; + + template> + class BasicCallbackStream : public std::basic_ostream { + public: + using base_type = std::basic_ostream; + + BasicCallbackStream(Callback cb, void* user_data = nullptr) + : m_sbuf(cb, user_data), + std::basic_ios(&m_sbuf), + std::basic_ostream(&m_sbuf) { + std::basic_ios::init(&m_sbuf); + } + + private: + BasicCallbackStreamBuffer m_sbuf; + }; + + template + class CallbackStream : public BasicCallbackStream { + public: + using base_type = BasicCallbackStream; + + CallbackStream(Callback cb, void* user_data = nullptr) : base_type(cb, user_data) { + } + }; + + template + class CallbackWStream : public BasicCallbackStream { + public: + using base_type = BasicCallbackStream; + + CallbackWStream(Callback cb, void* user_data = nullptr) : base_type(cb, user_data) { + } + }; +} \ No newline at end of file diff --git a/include/openvic-dataloader/detail/Concepts.hpp b/include/openvic-dataloader/detail/Concepts.hpp new file mode 100644 index 0000000..3e1c785 --- /dev/null +++ b/include/openvic-dataloader/detail/Concepts.hpp @@ -0,0 +1,22 @@ +#pragma once + +#include +#include +#include +#include + +#include + +namespace ovdl::detail { + template + concept LoadCallback = + requires(T t, Self* self, Args... args) { + { t(self, std::forward(args)...) } -> std::same_as>; + }; + + template + concept Has_c_str = + requires(T t) { + { t.c_str() } -> std::same_as; + }; +} \ No newline at end of file diff --git a/include/openvic-dataloader/detail/SelfType.hpp b/include/openvic-dataloader/detail/SelfType.hpp new file mode 100644 index 0000000..5209700 --- /dev/null +++ b/include/openvic-dataloader/detail/SelfType.hpp @@ -0,0 +1,28 @@ +#pragma once + +#include + +namespace ovdl::detail { +#if !defined(_MSC_VER) +#pragma GCC diagnostic push +#pragma clang diagnostic ignored "-Wunknown-warning-option" +#pragma GCC diagnostic ignored "-Wnon-template-friend" +#endif + template + struct Reader { + friend auto adl_GetSelfType(Reader); + }; + + template + struct Writer { + friend auto adl_GetSelfType(Reader) { return U {}; } + }; +#if !defined(_MSC_VER) +#pragma GCC diagnostic pop +#endif + + inline void adl_GetSelfType() {} + + template + using Read = std::remove_pointer_t {}))>; +} diff --git a/include/openvic-dataloader/detail/TypeName.hpp b/include/openvic-dataloader/detail/TypeName.hpp new file mode 100644 index 0000000..1a34a0f --- /dev/null +++ b/include/openvic-dataloader/detail/TypeName.hpp @@ -0,0 +1,52 @@ +#pragma once + +#include +#include +#include +#include + +namespace ovdl::detail { + + template + constexpr auto substring_as_array(std::string_view str, std::index_sequence) { + return std::array { str[Idxs]... }; + } + + template + constexpr auto type_name_array() { +#if defined(__clang__) + constexpr auto prefix = std::string_view { "[T = " }; + constexpr auto suffix = std::string_view { "]" }; + constexpr auto function = std::string_view { __PRETTY_FUNCTION__ }; +#elif defined(__GNUC__) + constexpr auto prefix = std::string_view { "with T = " }; + constexpr auto suffix = std::string_view { "]" }; + constexpr auto function = std::string_view { __PRETTY_FUNCTION__ }; +#elif defined(_MSC_VER) + constexpr auto prefix = std::string_view { "type_name_array<" }; + constexpr auto suffix = std::string_view { ">(void)" }; + constexpr auto function = std::string_view { __FUNCSIG__ }; +#else +#error Unsupported compiler +#endif + + constexpr auto start = function.find(prefix) + prefix.size(); + constexpr auto end = function.rfind(suffix); + + static_assert(start < end); + + constexpr auto name = function.substr(start, (end - start)); + return substring_as_array(name, std::make_index_sequence {}); + } + + template + struct type_name_holder { + static inline constexpr auto value = type_name_array(); + }; + + template + constexpr auto type_name() -> std::string_view { + constexpr auto& value = type_name_holder::value; + return std::string_view { value.data(), value.size() }; + } +} \ No newline at end of file diff --git a/include/openvic-dataloader/v2script/AbstractSyntaxTree.hpp b/include/openvic-dataloader/v2script/AbstractSyntaxTree.hpp new file mode 100644 index 0000000..7b382fd --- /dev/null +++ b/include/openvic-dataloader/v2script/AbstractSyntaxTree.hpp @@ -0,0 +1,224 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define OVDL_PRINT_FUNC_DEF std::ostream& print(std::ostream& stream, size_t indent) const override + +// defines get_type_static and get_type for string type naming +#define OVDL_RT_TYPE_DEF \ + static constexpr std::string_view get_type_static() { return ::ovdl::detail::type_name(); } \ + constexpr std::string_view get_type() const override { return ::ovdl::detail::type_name>(); } + +// defines type for self-class referencing +#define OVDL_TYPE_DEFINE_SELF \ + struct _self_type_tag {}; \ + constexpr auto _self_type_helper()->decltype(::ovdl::detail::Writer<_self_type_tag, decltype(this)> {}); \ + using type = ::ovdl::detail::Read<_self_type_tag>; + +namespace ovdl::v2script::ast { + + struct Node; + using NodePtr = Node*; + using NodeCPtr = const Node*; + using NodeUPtr = std::unique_ptr; + + struct Node { + Node(const Node&) = delete; + Node& operator=(const Node&) = delete; + Node() = default; + Node(Node&&) = default; + Node& operator=(Node&&) = default; + virtual ~Node() = default; + + virtual std::ostream& print(std::ostream& stream, size_t indent) const = 0; + static std::ostream& print_ptr(std::ostream& stream, NodeCPtr node, size_t indent); + explicit operator std::string() const; + + static constexpr std::string_view get_type_static() { return detail::type_name(); } + constexpr virtual std::string_view get_type() const = 0; + + template + constexpr bool is_type() const { + return get_type().compare(detail::type_name()) == 0; + } + + template + constexpr std::optional cast_to() { + if (is_type()) return static_cast(*this); + return std::nullopt; + } + }; + + inline std::ostream& operator<<(std::ostream& stream, Node const& node) { + return node.print(stream, 0); + } + inline std::ostream& operator<<(std::ostream& stream, NodeCPtr node) { + return Node::print_ptr(stream, node, 0); + } + + template + NodePtr make_node_ptr(Args&&... args) { + if constexpr (std::is_pointer_v) { + return new T(std::forward(args)...); + } else { + return NodePtr(new T(std::forward(args)...)); + } + } + + template + To& cast_node_ptr(const From& from) { + if constexpr (std::is_pointer_v) { + return *static_cast(from); + } else { + return *static_cast(from.get()); + } + } + + template + const To& cast_node_cptr(const From& from) { + if constexpr (std::is_pointer_v) { + return *static_cast(from); + } else { + return *static_cast(from.get()); + } + } + + void copy_into_node_ptr_vector(const std::vector& source, std::vector& dest); + + struct AbstractStringNode : public Node { + std::string _name; + explicit AbstractStringNode(std::string&& name); + OVDL_TYPE_DEFINE_SELF; + OVDL_RT_TYPE_DEF; + OVDL_PRINT_FUNC_DEF; + }; + +#define OVDL_AST_STRING_NODE(NAME) \ + struct NAME final : public AbstractStringNode { \ + explicit NAME(std::string&& name); \ + OVDL_TYPE_DEFINE_SELF; \ + OVDL_RT_TYPE_DEF; \ + OVDL_PRINT_FUNC_DEF; \ + } + + // Value Expression Nodes + OVDL_AST_STRING_NODE(IdentifierNode); + OVDL_AST_STRING_NODE(StringNode); + + // Assignment Nodes + OVDL_AST_STRING_NODE(FactorNode); + OVDL_AST_STRING_NODE(MonthNode); + OVDL_AST_STRING_NODE(NameNode); + OVDL_AST_STRING_NODE(FireOnlyNode); + OVDL_AST_STRING_NODE(IdNode); + OVDL_AST_STRING_NODE(TitleNode); + OVDL_AST_STRING_NODE(DescNode); + OVDL_AST_STRING_NODE(PictureNode); + OVDL_AST_STRING_NODE(IsTriggeredNode); + +#undef OVDL_AST_STRING_NODE + + struct AssignNode final : public Node { + std::string _name; + NodeUPtr _initializer; + explicit AssignNode(NodeCPtr name, NodePtr init); + OVDL_TYPE_DEFINE_SELF; + OVDL_RT_TYPE_DEF; + OVDL_PRINT_FUNC_DEF; + }; + + struct AbstractListNode : public Node { + std::vector _statements; + AbstractListNode(const std::vector& statements = std::vector {}); + OVDL_TYPE_DEFINE_SELF; + OVDL_RT_TYPE_DEF; + OVDL_PRINT_FUNC_DEF; + }; + +#define OVDL_AST_LIST_NODE(NAME) \ + struct NAME final : public AbstractListNode { \ + explicit NAME(const std::vector& statements = std::vector {}); \ + OVDL_TYPE_DEFINE_SELF; \ + OVDL_RT_TYPE_DEF; \ + OVDL_PRINT_FUNC_DEF; \ + } + + OVDL_AST_LIST_NODE(FileNode); + OVDL_AST_LIST_NODE(ListNode); + + OVDL_AST_LIST_NODE(ModifierNode); + OVDL_AST_LIST_NODE(MtthNode); + OVDL_AST_LIST_NODE(EventOptionNode); + OVDL_AST_LIST_NODE(BehaviorListNode); + OVDL_AST_LIST_NODE(DecisionListNode); + +#undef OVDL_AST_LIST_NODE + + struct EventNode final : public Node { + enum class Type { + Country, + Province + } _type; + std::vector _statements; + explicit EventNode(Type type, const std::vector& statements = {}); + OVDL_TYPE_DEFINE_SELF; + OVDL_RT_TYPE_DEF; + OVDL_PRINT_FUNC_DEF; + }; + + struct DecisionNode final : public Node { + NodeUPtr _name; + std::vector _statements; + explicit DecisionNode(NodePtr name, const std::vector& statements = {}); + OVDL_TYPE_DEFINE_SELF; + OVDL_RT_TYPE_DEF; + OVDL_PRINT_FUNC_DEF; + }; + + struct EventMtthModifierNode final : public Node { + NodeUPtr _factor_value; + std::vector _statements; + EventMtthModifierNode() {} + OVDL_TYPE_DEFINE_SELF; + OVDL_RT_TYPE_DEF; + OVDL_PRINT_FUNC_DEF; + }; + + // Packed single case + struct ExecutionNode final : public Node { + enum class Type { + Effect, + Trigger + } _type; + NodeUPtr _name; + NodeUPtr _initializer; + explicit ExecutionNode(Type type, NodePtr name, NodePtr init); + OVDL_TYPE_DEFINE_SELF; + OVDL_RT_TYPE_DEF; + OVDL_PRINT_FUNC_DEF; + }; + + struct ExecutionListNode final : public Node { + ExecutionNode::Type _type; + std::vector _statements; + explicit ExecutionListNode(ExecutionNode::Type type, const std::vector& statements); + OVDL_TYPE_DEFINE_SELF; + OVDL_RT_TYPE_DEF; + OVDL_PRINT_FUNC_DEF; + }; + +} + +#undef OVDL_PRINT_FUNC_DECL +#undef OVDL_PRINT_FUNC_DEF +#undef OVDL_TYPE_DEFINE_SELF \ No newline at end of file diff --git a/include/openvic-dataloader/v2script/Parser.hpp b/include/openvic-dataloader/v2script/Parser.hpp index 53aab90..1c524b2 100644 --- a/include/openvic-dataloader/v2script/Parser.hpp +++ b/include/openvic-dataloader/v2script/Parser.hpp @@ -1,27 +1,59 @@ #pragma once #include -#include +#include +#include +#include +#include #include +#include +#include + +#include +#include +#include +#include +#include namespace ovdl::v2script { - class Parser { + + using FileNode = ast::FileNode; + + class Parser final : public detail::BasicParser { public: - static Parser from_buffer(char8_t* data, std::size_t size); - static Parser from_buffer(char8_t* start, char8_t* end); - static Parser from_file(const char8_t* path); + Parser(); + + static Parser from_buffer(const char* data, std::size_t size); + static Parser from_buffer(const char* start, const char* end); + static Parser from_string(const std::string_view string); + static Parser from_file(const char* path); + static Parser from_file(const std::filesystem::path& path); - void set_error_log_to_stderr(); - void set_error_log_path(const char8_t* path); - void set_error_log_to(std::basic_ostream stream); - void set_error_log_to(std::FILE* file); + constexpr Parser& load_from_buffer(const char* data, std::size_t size); + constexpr Parser& load_from_buffer(const char* start, const char* end); + constexpr Parser& load_from_string(const std::string_view string); + constexpr Parser& load_from_file(const char* path); + Parser& load_from_file(const std::filesystem::path& path); - bool parse(); + constexpr Parser& load_from_file(const detail::Has_c_str auto& path); - bool has_error(); - bool has_warning(); + bool simple_parse(); + bool event_parse(); + bool decision_parse(); + + const FileNode* get_file_node() const; + + Parser(Parser&&); + Parser& operator=(Parser&&); + + ~Parser(); private: - Parser(); + class BufferHandler; + std::unique_ptr _buffer_handler; + std::unique_ptr _file_node; + + template + constexpr void _run_load_func(detail::LoadCallback auto func, Args... args); }; } \ No newline at end of file -- cgit v1.2.3-56-ga3b1