aboutsummaryrefslogtreecommitdiff
path: root/include/openvic-dataloader/v2script
diff options
context:
space:
mode:
author Spartan322 <Megacake1234@gmail.com>2023-07-28 06:52:00 +0200
committer Spartan322 <Megacake1234@gmail.com>2023-09-02 14:28:21 +0200
commit7440a5d1433eec4bf87e3723022db187e7f61b1a (patch)
tree2bb062c320fa2227b18956617b94d0e8800420d8 /include/openvic-dataloader/v2script
parente941573f47fb867ff75c8a2cf78302b754ffbeee (diff)
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<csv::LineObject> for a list of lines Add BasicParser and BasicBufferHandler to reduce code reduplication
Diffstat (limited to 'include/openvic-dataloader/v2script')
-rw-r--r--include/openvic-dataloader/v2script/AbstractSyntaxTree.hpp224
-rw-r--r--include/openvic-dataloader/v2script/Parser.hpp58
2 files changed, 269 insertions, 13 deletions
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 <iostream>
+#include <memory>
+#include <optional>
+#include <string>
+#include <string_view>
+#include <type_traits>
+#include <utility>
+#include <vector>
+
+#include <openvic-dataloader/detail/SelfType.hpp>
+#include <openvic-dataloader/detail/TypeName.hpp>
+
+#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<type>(); } \
+ constexpr std::string_view get_type() const override { return ::ovdl::detail::type_name<std::decay_t<decltype(*this)>>(); }
+
+// 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<Node>;
+
+ 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<Node>(); }
+ constexpr virtual std::string_view get_type() const = 0;
+
+ template<typename T>
+ constexpr bool is_type() const {
+ return get_type().compare(detail::type_name<T>()) == 0;
+ }
+
+ template<typename T>
+ constexpr std::optional<T&> cast_to() {
+ if (is_type<T>()) return static_cast<T>(*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<class T, class... Args>
+ NodePtr make_node_ptr(Args&&... args) {
+ if constexpr (std::is_pointer_v<NodePtr>) {
+ return new T(std::forward<Args>(args)...);
+ } else {
+ return NodePtr(new T(std::forward<Args>(args)...));
+ }
+ }
+
+ template<typename To, typename From>
+ To& cast_node_ptr(const From& from) {
+ if constexpr (std::is_pointer_v<NodePtr>) {
+ return *static_cast<To*>(from);
+ } else {
+ return *static_cast<To*>(from.get());
+ }
+ }
+
+ template<typename To, typename From>
+ const To& cast_node_cptr(const From& from) {
+ if constexpr (std::is_pointer_v<NodePtr>) {
+ return *static_cast<const To*>(from);
+ } else {
+ return *static_cast<const To*>(from.get());
+ }
+ }
+
+ void copy_into_node_ptr_vector(const std::vector<NodePtr>& source, std::vector<NodeUPtr>& 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<NodeUPtr> _statements;
+ AbstractListNode(const std::vector<NodePtr>& statements = std::vector<NodePtr> {});
+ 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<NodePtr>& statements = std::vector<NodePtr> {}); \
+ 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<NodeUPtr> _statements;
+ explicit EventNode(Type type, const std::vector<NodePtr>& statements = {});
+ OVDL_TYPE_DEFINE_SELF;
+ OVDL_RT_TYPE_DEF;
+ OVDL_PRINT_FUNC_DEF;
+ };
+
+ struct DecisionNode final : public Node {
+ NodeUPtr _name;
+ std::vector<NodeUPtr> _statements;
+ explicit DecisionNode(NodePtr name, const std::vector<NodePtr>& statements = {});
+ OVDL_TYPE_DEFINE_SELF;
+ OVDL_RT_TYPE_DEF;
+ OVDL_PRINT_FUNC_DEF;
+ };
+
+ struct EventMtthModifierNode final : public Node {
+ NodeUPtr _factor_value;
+ std::vector<NodeUPtr> _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<NodeUPtr> _statements;
+ explicit ExecutionListNode(ExecutionNode::Type type, const std::vector<NodePtr>& 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 <cstddef>
-#include <cstdio>
+#include <filesystem>
+#include <functional>
+#include <memory>
+#include <optional>
#include <ostream>
+#include <string_view>
+#include <vector>
+
+#include <openvic-dataloader/ParseError.hpp>
+#include <openvic-dataloader/ParseWarning.hpp>
+#include <openvic-dataloader/detail/BasicParser.hpp>
+#include <openvic-dataloader/detail/Concepts.hpp>
+#include <openvic-dataloader/v2script/AbstractSyntaxTree.hpp>
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<char8_t> 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<BufferHandler> _buffer_handler;
+ std::unique_ptr<FileNode> _file_node;
+
+ template<typename... Args>
+ constexpr void _run_load_func(detail::LoadCallback<BufferHandler, Args...> auto func, Args... args);
};
} \ No newline at end of file