From 757114a3c5b748567b42f273c7b78ca039ae983c Mon Sep 17 00:00:00 2001 From: Spartan322 Date: Tue, 28 Nov 2023 05:09:26 -0500 Subject: Add `deps/dryad` -> https://github.com/Spartan322/dryad Add `deps/fmt` -> https://github.com/fmtlib/fmt Add `deps/range-v3` -> https://github.com/ericniebler/range-v3 Improve parser error and warning support Update .clang-format Update `deps/SCsub` --- .../v2script/AbstractSyntaxTree.hpp | 398 ++++++++------------- .../v2script/NodeLocationMap.hpp | 91 ----- include/openvic-dataloader/v2script/Parser.hpp | 46 ++- 3 files changed, 174 insertions(+), 361 deletions(-) delete mode 100644 include/openvic-dataloader/v2script/NodeLocationMap.hpp (limited to 'include/openvic-dataloader/v2script') diff --git a/include/openvic-dataloader/v2script/AbstractSyntaxTree.hpp b/include/openvic-dataloader/v2script/AbstractSyntaxTree.hpp index 689ab6e..1e7b2c3 100644 --- a/include/openvic-dataloader/v2script/AbstractSyntaxTree.hpp +++ b/include/openvic-dataloader/v2script/AbstractSyntaxTree.hpp @@ -1,310 +1,200 @@ #pragma once -#include -#include -#include -#include -#include +#include #include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include -namespace lexy { - struct nullopt; -} +#include +#include +#include +#include +#include +#include -namespace ovdl::v2script { - class Parser; -} +namespace ovdl::v2script::ast { + enum class NodeKind { + FileTree, -#define OVDL_PRINT_FUNC_DEF std::ostream& print(std::ostream& stream, std::size_t indent) const override + // FlatValues // + IdentifierValue, // straight_identifier_value + StringValue, // "plain string value" -// 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>(); } + FirstFlatValue = IdentifierValue, + LastFlatValue = StringValue, -// 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>; + // Values // + ListValue, // { } + NullValue, -namespace ovdl::v2script::ast { + FirstValue = FirstFlatValue, + LastValue = NullValue, - struct Node; - using NodePtr = Node*; - using NodeCPtr = const Node*; - using NodeUPtr = std::unique_ptr; + // Statements // + EventStatement, // (country_event|province_event) = { id = ... } + AssignStatement, // = + ValueStatement, // - struct NodeLocation { - const char* _begin = nullptr; - const char* _end = nullptr; + FirstStatement = EventStatement, + LastStatement = ValueStatement, + }; - NodeLocation() = default; - NodeLocation(const char* pos) : _begin(pos), - _end(pos) {} - NodeLocation(const char* begin, const char* end) : _begin(begin), - _end(end) {} + constexpr std::string_view get_kind_name(NodeKind kind) { + switch (kind) { + using enum NodeKind; + case FileTree: return "file tree"; + case IdentifierValue: return "identifier value"; + case StringValue: return "string value"; + case ListValue: return "list value"; + case NullValue: return "null value"; + case EventStatement: return "event statement"; + case AssignStatement: return "assign statement"; + case ValueStatement: return "value statement"; + default: detail::unreachable(); + } + } - NodeLocation(const NodeLocation&) = default; - NodeLocation& operator=(const NodeLocation&) = default; + using Node = dryad::node; + using NodeList = dryad::unlinked_node_list; - NodeLocation(NodeLocation&&) = default; - NodeLocation& operator=(NodeLocation&&) = default; + struct Value; - const char* begin() const { return _begin; } - const char* end() const { return _end; } + struct FlatValue; + struct IdentifierValue; + struct StringValue; - static inline NodeLocation make_from(const char* begin, const char* end) { - end++; - if (begin >= end) return NodeLocation(begin); - return NodeLocation(begin, end); - } - }; + struct ListValue; - struct Node { - Node(const Node&) = delete; - Node& operator=(const Node&) = delete; - Node(NodeLocation location) : _location(location) {} - Node(Node&&) = default; - Node& operator=(Node&&) = default; - virtual ~Node() = default; + struct Statement; + using StatementList = dryad::unlinked_node_list; - virtual std::ostream& print(std::ostream& stream, std::size_t indent) const = 0; - static std::ostream& print_ptr(std::ostream& stream, NodeCPtr node, std::size_t indent); - explicit operator std::string() const; + struct EventStatement; + using EventStatementList = dryad::unlinked_node_list; - static constexpr std::string_view get_type_static() { return detail::type_name(); } - constexpr virtual std::string_view get_type() const = 0; + struct AssignStatement; + using AssignStatementList = dryad::unlinked_node_list; - static constexpr std::string_view get_base_type_static() { return detail::type_name(); } - constexpr virtual std::string_view get_base_type() const { return get_base_type_static(); } + struct Value : dryad::abstract_node_range { + DRYAD_ABSTRACT_NODE_CTOR(Value); + }; - template - constexpr bool is_type() const { - return get_type().compare(detail::type_name()) == 0; + struct FlatValue : dryad::abstract_node_range { + AbstractSyntaxTree::symbol_type value() const { + return _value; } - template - constexpr bool is_derived_from() const { - return is_type() || get_base_type().compare(detail::type_name()) == 0; + const char* value(const AbstractSyntaxTree::symbol_interner_type& symbols) const { + return _value.c_str(symbols); } - template - constexpr T* cast_to() { - if (is_derived_from() || is_type()) return (static_cast(this)); - return nullptr; - } + protected: + explicit FlatValue(dryad::node_ctor ctor, NodeKind kind, AbstractSyntaxTree::symbol_type value) + : node_base(ctor, kind), + _value(value) {} - template - constexpr const T* const cast_to() const { - if (is_derived_from() || is_type()) return (static_cast(this)); - return nullptr; - } + protected: + AbstractSyntaxTree::symbol_type _value; + }; - const NodeLocation location() const { return _location; } + struct IdentifierValue : dryad::basic_node { + explicit IdentifierValue(dryad::node_ctor ctor, AbstractSyntaxTree::symbol_type value) : node_base(ctor, value) {} + }; - struct line_col { - uint32_t line; - uint32_t column; - }; + struct StringValue : dryad::basic_node { + explicit StringValue(dryad::node_ctor ctor, AbstractSyntaxTree::symbol_type value) : node_base(ctor, value) {} + }; - private: - friend class ::ovdl::v2script::Parser; - const line_col get_begin_line_col(const Parser& parser) const; - const line_col get_end_line_col(const Parser& parser) const; + struct ListValue : dryad::basic_node> { + explicit ListValue(dryad::node_ctor ctor, StatementList statements); + explicit ListValue(dryad::node_ctor ctor, AssignStatementList statements) + : node_base(ctor) { + insert_child_list_after(nullptr, statements); + } + + explicit ListValue(dryad::node_ctor ctor) : ListValue(ctor, StatementList {}) { + } + + DRYAD_CHILD_NODE_RANGE_GETTER(Statement, statements, nullptr, this->node_after(_last_statement)); private: - NodeLocation _location; + Node* _last_statement; }; - 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); - } - inline std::ostream& operator<<(std::ostream& stream, Node::line_col const& val) { - return stream << '(' << val.line << ':' << val.column << ')'; - } + struct NullValue : dryad::basic_node { + explicit NullValue(dryad::node_ctor ctor) : node_base(ctor) {} + }; - 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)...)); + struct Statement : dryad::abstract_node_range, NodeKind::FirstStatement, NodeKind::LastStatement> { + explicit Statement(dryad::node_ctor ctor, NodeKind kind, Value* right) + : node_base(ctor, kind) { + insert_child_after(nullptr, right); } - } - template - To& cast_node_ptr(const From& from) { - if constexpr (std::is_pointer_v) { - return *static_cast(from); - } else { - return *static_cast(from.get()); + explicit Statement(dryad::node_ctor ctor, NodeKind kind, Value* left, Value* right) + : node_base(ctor, kind) { + insert_child_after(nullptr, left); + insert_child_after(left, right); } - } + }; - 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()); + struct EventStatement : dryad::basic_node { + explicit EventStatement(dryad::node_ctor ctor, bool is_province_event, ListValue* list) + : basic_node(ctor, list), + _is_province_event(is_province_event) { } - } - void copy_into_node_ptr_vector(const std::vector& source, std::vector& dest); - - struct AbstractStringNode : public Node { - std::string _name; - AbstractStringNode(); - AbstractStringNode(std::string&& name, bool allow_newline); - AbstractStringNode(NodeLocation location); - AbstractStringNode(NodeLocation location, std::string&& name, bool allow_newline); - OVDL_TYPE_DEFINE_SELF; - OVDL_RT_TYPE_DEF; - OVDL_PRINT_FUNC_DEF; - static constexpr std::string_view get_base_type_static() { return detail::type_name(); } - constexpr std::string_view get_base_type() const override { return ::ovdl::detail::type_name>(); } - }; + bool is_province_event() const { return _is_province_event; } -#define OVDL_AST_STRING_NODE(NAME) \ - struct NAME final : public AbstractStringNode { \ - NAME(); \ - NAME(std::string&& name, bool allow_newline = true); \ - NAME(lexy::nullopt); \ - NAME(NodeLocation location); \ - NAME(NodeLocation location, std::string&& name, bool allow_newline = true); \ - NAME(NodeLocation location, lexy::nullopt); \ - OVDL_TYPE_DEFINE_SELF; \ - OVDL_RT_TYPE_DEF; \ - OVDL_PRINT_FUNC_DEF; \ - } + DRYAD_CHILD_NODE_GETTER(Value, right, nullptr); - // 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; - AssignNode(NodeLocation location, NodeCPtr name, NodePtr init); - OVDL_TYPE_DEFINE_SELF; - OVDL_RT_TYPE_DEF; - OVDL_PRINT_FUNC_DEF; + private: + bool _is_province_event; }; - struct AbstractListNode : public Node { - std::vector _statements; - AbstractListNode(const std::vector& statements = std::vector {}); - AbstractListNode(NodeLocation location, const std::vector& statements = std::vector {}); - OVDL_TYPE_DEFINE_SELF; - OVDL_RT_TYPE_DEF; - OVDL_PRINT_FUNC_DEF; - static constexpr std::string_view get_base_type_static() { return detail::type_name(); } - constexpr std::string_view get_base_type() const override { return ::ovdl::detail::type_name>(); } + struct AssignStatement : dryad::basic_node { + explicit AssignStatement(dryad::node_ctor ctor, Value* left, Value* right) + : node_base(ctor, left, right) { + } + DRYAD_CHILD_NODE_GETTER(Value, left, nullptr); + DRYAD_CHILD_NODE_GETTER(Value, right, left()); }; -#define OVDL_AST_LIST_NODE(NAME) \ - struct NAME final : public AbstractListNode { \ - NAME(const std::vector& statements = std::vector {}); \ - NAME(lexy::nullopt); \ - NAME(NodeLocation location, const std::vector& statements = std::vector {}); \ - NAME(NodeLocation location, lexy::nullopt); \ - 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 - -#define OVDL_AST_LIST_EXTEND(NAME) \ - NAME(lexy::nullopt); \ - NAME(NodeLocation location, lexy::nullopt); \ - OVDL_TYPE_DEFINE_SELF; \ - OVDL_RT_TYPE_DEF; \ - OVDL_PRINT_FUNC_DEF - - struct EventNode final : public AbstractListNode { - OVDL_AST_LIST_EXTEND(EventNode); - enum class Type { - Country, - Province - } _type; - EventNode(Type type, const std::vector& statements = {}); - EventNode(NodeLocation location, Type type, const std::vector& statements = {}); + struct ValueStatement : dryad::basic_node { + explicit ValueStatement(dryad::node_ctor ctor, Value* value) + : node_base(ctor, value) { + } + DRYAD_CHILD_NODE_GETTER(Value, value, nullptr); }; - struct DecisionNode final : public AbstractListNode { - OVDL_AST_LIST_EXTEND(DecisionNode); - NodeUPtr _name; - DecisionNode(NodePtr name, const std::vector& statements = {}); - DecisionNode(NodeLocation location, NodePtr name, const std::vector& statements = {}); - }; + struct FileTree : dryad::basic_node> { + explicit FileTree(dryad::node_ctor ctor, StatementList statements); + explicit FileTree(dryad::node_ctor ctor, AssignStatementList statements) : node_base(ctor) { + insert_child_list_after(nullptr, statements); + } - struct EventMtthModifierNode final : public AbstractListNode { - OVDL_AST_LIST_EXTEND(EventMtthModifierNode); - NodeUPtr _factor_value; - EventMtthModifierNode() : AbstractListNode() {} - EventMtthModifierNode(NodeLocation location) : AbstractListNode(location) {} - }; + explicit FileTree(dryad::node_ctor ctor) : FileTree(ctor, StatementList {}) { + } - // Packed single case - struct ExecutionNode final : public Node { - enum class Type { - Effect, - Trigger - } _type; - NodeUPtr _name; - NodeUPtr _initializer; - ExecutionNode(Type type, NodePtr name, NodePtr init); - ExecutionNode(NodeLocation location, Type type, NodePtr name, NodePtr init); - OVDL_TYPE_DEFINE_SELF; - OVDL_RT_TYPE_DEF; - OVDL_PRINT_FUNC_DEF; - }; + DRYAD_CHILD_NODE_RANGE_GETTER(Statement, statements, nullptr, this->node_after(_last_node)); - struct ExecutionListNode final : public AbstractListNode { - OVDL_AST_LIST_EXTEND(ExecutionListNode); - ExecutionNode::Type _type; - ExecutionListNode(ExecutionNode::Type type, const std::vector& statements); - ExecutionListNode(NodeLocation location, ExecutionNode::Type type, const std::vector& statements); + private: + Node* _last_node; }; -#undef OVDL_AST_LIST_EXTEND + using File = ovdl::BasicFile; + struct AbstractSyntaxTree : ovdl::BasicAbstractSyntaxTree { + using BasicAbstractSyntaxTree::BasicAbstractSyntaxTree; -} + std::string make_list_visualizer() const; + std::string make_native_visualizer() const; + }; + using ParseState = ovdl::ParseState; -#undef OVDL_PRINT_FUNC_DECL -#undef OVDL_PRINT_FUNC_DEF -#undef OVDL_TYPE_DEFINE_SELF \ No newline at end of file + static_assert(IsFile, "File failed IsFile concept"); + static_assert(IsAst, "AbstractSyntaxTree failed IsAst concept"); + static_assert(IsParseState, "ParseState failed IsParseState concept"); +} \ No newline at end of file diff --git a/include/openvic-dataloader/v2script/NodeLocationMap.hpp b/include/openvic-dataloader/v2script/NodeLocationMap.hpp deleted file mode 100644 index aa88d62..0000000 --- a/include/openvic-dataloader/v2script/NodeLocationMap.hpp +++ /dev/null @@ -1,91 +0,0 @@ -#pragma once - -#include - -#include -#include - -#include - -namespace ovdl::v2script::ast { - // TODO: FOR THE LOVE OF GOD USE A DIFFERENT HASH MULTIMAP TYPE - // See src/openvic-dataloader/v2script/Parser.cpp#252 - template - struct NodeLocationMap : public std::unordered_multimap, detail::PointerHash> { - NodeLocationMap() = default; - NodeLocationMap(const Input& input, const Node& top_node) { - generate_location_map(input, top_node); - } - - NodeLocationMap(const NodeLocationMap&) = default; - NodeLocationMap(NodeLocationMap&&) = default; - - NodeLocationMap& operator=(const NodeLocationMap&) = default; - NodeLocationMap& operator=(NodeLocationMap&&) = default; - - lexy::input_location_anchor generate_location_map(const Input& input, NodeCPtr node); - lexy::input_location_anchor generate_location_map(const Input& input, NodeCPtr node, lexy::input_location_anchor anchor); - lexy::input_location_anchor generate_begin_location_for(const Input& input, NodeCPtr node, lexy::input_location_anchor anchor); - lexy::input_location_anchor generate_end_location_for(const Input& input, NodeCPtr node, lexy::input_location_anchor anchor); - }; - - template - constexpr const lexy::input_location make_begin_loc(const NodeLocation location, const Input& input, lexy::input_location_anchor anchor) { - return lexy::get_input_location(input, location.begin(), anchor); - } - - template - constexpr const lexy::input_location make_begin_loc(const NodeLocation location, const Input& input) { - return lexy::get_input_location(input, location.begin()); - } - - template - constexpr const lexy::input_location make_end_loc(const NodeLocation location, const Input& input, lexy::input_location_anchor anchor) { - return lexy::get_input_location(input, location.end(), anchor); - } - - template - constexpr const lexy::input_location make_end_loc(const NodeLocation location, const Input& input) { - return lexy::get_input_location(input, location.end()); - } -} - -namespace ovdl::v2script::ast { - template - lexy::input_location_anchor NodeLocationMap::generate_location_map(const Input& input, NodeCPtr node) { - return generate_location_map(input, node, lexy::input_location_anchor(input)); - } - - template - lexy::input_location_anchor NodeLocationMap::generate_location_map(const Input& input, NodeCPtr node, lexy::input_location_anchor anchor) { - if (!node) return anchor; - anchor = generate_begin_location_for(input, node, anchor); - if (auto list_node = node->cast_to(); list_node) { - for (auto& inner_node : list_node->_statements) { - anchor = generate_location_map(input, inner_node.get(), anchor); - } - } else if (auto assign_node = node->cast_to(); assign_node) { - anchor = generate_location_map(input, assign_node->_initializer.get(), anchor); - } - // TODO: implement for EventNode, DecisionNode, EventMtthModifierNode, ExecutionNode, ExecutionListNode - if (!node->location().end() || node->location().begin() >= node->location().end()) - return anchor; - return generate_end_location_for(input, node, anchor); - } - - template - lexy::input_location_anchor NodeLocationMap::generate_begin_location_for(const Input& input, NodeCPtr node, lexy::input_location_anchor anchor) { - if (node->location().begin() == nullptr) return anchor; - lexy::input_location next_loc = make_begin_loc(node->location(), input, anchor); - this->emplace(node, next_loc); - return next_loc.anchor(); - } - - template - lexy::input_location_anchor NodeLocationMap::generate_end_location_for(const Input& input, NodeCPtr node, lexy::input_location_anchor anchor) { - if (node->location().end() == nullptr) return anchor; - lexy::input_location next_loc = make_end_loc(node->location(), input, anchor); - this->emplace(node, next_loc); - return next_loc.anchor(); - } -} \ No newline at end of file diff --git a/include/openvic-dataloader/v2script/Parser.hpp b/include/openvic-dataloader/v2script/Parser.hpp index 885946d..cef1faf 100644 --- a/include/openvic-dataloader/v2script/Parser.hpp +++ b/include/openvic-dataloader/v2script/Parser.hpp @@ -3,21 +3,26 @@ #include #include #include +#include +#include #include -#include -#include -#include -#include +#include +#include +#include +#include #include -namespace ovdl::v2script { +#include - using FileNode = ast::FileNode; +namespace ovdl::v2script { + using FileTree = ast::FileTree; + using FilePosition = ovdl::FilePosition; class Parser final : public detail::BasicParser { public: Parser(); + Parser(std::basic_ostream& error_stream); static Parser from_buffer(const char* data, std::size_t size); static Parser from_buffer(const char* start, const char* end); @@ -31,19 +36,30 @@ namespace ovdl::v2script { 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); + constexpr Parser& load_from_file(const detail::HasCstr auto& path) { + return load_from_file(path.c_str()); + } bool simple_parse(); bool event_parse(); bool decision_parse(); bool lua_defines_parse(); - const FileNode* get_file_node() const; + const FileTree* get_file_node() const; + + std::string_view value(const ovdl::v2script::ast::FlatValue& node) const; + + std::string make_native_string() const; + std::string make_list_string() const; + + const FilePosition get_position(const ast::Node* node) const; + + using error_range = ovdl::detail::error_range; + Parser::error_range get_errors() const; - void generate_node_location_map(); + const FilePosition get_error_position(const error::Error* error) const; - const ast::Node::line_col get_node_begin(const ast::NodeCPtr node) const; - const ast::Node::line_col get_node_end(const ast::NodeCPtr node) const; + void print_errors_to(std::basic_ostream& stream) const; Parser(Parser&&); Parser& operator=(Parser&&); @@ -51,12 +67,10 @@ namespace ovdl::v2script { ~Parser(); private: - friend class ::ovdl::v2script::ast::Node; - class BufferHandler; - std::unique_ptr _buffer_handler; - std::unique_ptr _file_node; + class ParseHandler; + std::unique_ptr _parse_handler; template - constexpr void _run_load_func(detail::LoadCallback auto func, Args... args); + constexpr void _run_load_func(detail::LoadCallback auto func, Args... args); }; } \ No newline at end of file -- cgit v1.2.3-56-ga3b1