diff options
author | George L. Albany <Megacake1234@gmail.com> | 2023-09-05 21:38:13 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-09-05 21:38:13 +0200 |
commit | 870068cf33057348000b1422d4bf40772aaf0b87 (patch) | |
tree | f7569029f45ec019b0387e63aa7b94d1da7cc03a /src/openvic-dataloader | |
parent | 238ab9dfaa8ec7a48142154d227605ae367d53d1 (diff) | |
parent | 1d2c5ce39d12adcb584d586952a59e15f2495f67 (diff) |
Merge pull request #9 from OpenVicProject/node-line-column
Diffstat (limited to 'src/openvic-dataloader')
-rw-r--r-- | src/openvic-dataloader/detail/BasicBufferHandler.hpp | 4 | ||||
-rw-r--r-- | src/openvic-dataloader/detail/Errors.hpp | 2 | ||||
-rw-r--r-- | src/openvic-dataloader/v2script/AbstractSyntaxTree.cpp | 48 | ||||
-rw-r--r-- | src/openvic-dataloader/v2script/ModifierGrammar.hpp | 2 | ||||
-rw-r--r-- | src/openvic-dataloader/v2script/Parser.cpp | 63 | ||||
-rw-r--r-- | src/openvic-dataloader/v2script/SimpleGrammar.hpp | 56 | ||||
-rw-r--r-- | src/openvic-dataloader/v2script/TriggerGrammar.hpp | 2 |
7 files changed, 141 insertions, 36 deletions
diff --git a/src/openvic-dataloader/detail/BasicBufferHandler.hpp b/src/openvic-dataloader/detail/BasicBufferHandler.hpp index 5f4f82d..72b85d3 100644 --- a/src/openvic-dataloader/detail/BasicBufferHandler.hpp +++ b/src/openvic-dataloader/detail/BasicBufferHandler.hpp @@ -41,6 +41,10 @@ namespace ovdl::detail { return std::nullopt; } + const auto& get_buffer() const { + return _buffer; + } + protected: lexy::buffer<Encoding, MemoryResource> _buffer; }; diff --git a/src/openvic-dataloader/detail/Errors.hpp b/src/openvic-dataloader/detail/Errors.hpp index f53bedc..bf7c831 100644 --- a/src/openvic-dataloader/detail/Errors.hpp +++ b/src/openvic-dataloader/detail/Errors.hpp @@ -1,6 +1,6 @@ #pragma once -#include "openvic-dataloader/v2script/Parser.hpp" +#include <openvic-dataloader/ParseError.hpp> namespace ovdl::errors { inline const ParseError make_no_file_error(const char* file_path) { diff --git a/src/openvic-dataloader/v2script/AbstractSyntaxTree.cpp b/src/openvic-dataloader/v2script/AbstractSyntaxTree.cpp index f9fb716..8dc1800 100644 --- a/src/openvic-dataloader/v2script/AbstractSyntaxTree.cpp +++ b/src/openvic-dataloader/v2script/AbstractSyntaxTree.cpp @@ -1,3 +1,4 @@ +#include <concepts> #include <iomanip> #include <sstream> #include <string> @@ -8,6 +9,8 @@ #include <openvic-dataloader/v2script/AbstractSyntaxTree.hpp> +#include <lexy/input_location.hpp> + using namespace ovdl::v2script::ast; void ovdl::v2script::ast::copy_into_node_ptr_vector(const std::vector<NodePtr>& source, std::vector<NodeUPtr>& dest) { @@ -18,13 +21,17 @@ void ovdl::v2script::ast::copy_into_node_ptr_vector(const std::vector<NodePtr>& } } -AbstractStringNode::AbstractStringNode(std::string&& name) : _name(std::move(name)) {} +AbstractStringNode::AbstractStringNode(NodeLocation location, std::string&& name) : Node(location), + _name(std::move(name)) {} +AbstractStringNode::AbstractStringNode(std::string&& name) : AbstractStringNode({}, std::move(name)) {} + std::ostream& AbstractStringNode::print(std::ostream& stream, size_t indent) const { return stream << _name; } -#define OVDL_AST_STRING_NODE_DEF(NAME, ...) \ - NAME::NAME(std::string&& name) : AbstractStringNode(std::move(name)) {} \ +#define OVDL_AST_STRING_NODE_DEF(NAME, ...) \ + NAME::NAME(std::string&& name) : AbstractStringNode(std::move(name)) {} \ + NAME::NAME(NodeLocation location, std::string&& name) : AbstractStringNode(location, std::move(name)) {} \ std::ostream& NAME::print(std::ostream& stream, size_t indent) const __VA_ARGS__ OVDL_AST_STRING_NODE_DEF(IdentifierNode, { @@ -73,8 +80,9 @@ OVDL_AST_STRING_NODE_DEF(IsTriggeredNode, { #undef OVDL_AST_STRING_NODE_DEF -AssignNode::AssignNode(NodeCPtr name, NodePtr init) - : _initializer(std::move(init)) { +AssignNode::AssignNode(NodeLocation location, NodeCPtr name, NodePtr init) + : Node(location), + _initializer(std::move(init)) { if (name->is_type<IdentifierNode>()) { _name = cast_node_cptr<IdentifierNode>(name)._name; } @@ -101,9 +109,10 @@ static std::ostream& print_nodeuptr_vector(const std::vector<NodeUPtr>& nodes, return stream; } -AbstractListNode::AbstractListNode(const std::vector<NodePtr>& statements) { +AbstractListNode::AbstractListNode(NodeLocation location, const std::vector<NodePtr>& statements) : Node(location) { copy_into_node_ptr_vector(statements, _statements); } +AbstractListNode::AbstractListNode(const std::vector<NodePtr>& statements) : AbstractListNode({}, statements) {} std::ostream& AbstractListNode::print(std::ostream& stream, size_t indent) const { stream << '{'; if (!_statements.empty()) { @@ -113,8 +122,9 @@ std::ostream& AbstractListNode::print(std::ostream& stream, size_t indent) const return stream << "}"; } -#define OVDL_AST_LIST_NODE_DEF(NAME, ...) \ - NAME::NAME(const std::vector<NodePtr>& statements) : AbstractListNode(statements) {} \ +#define OVDL_AST_LIST_NODE_DEF(NAME, ...) \ + NAME::NAME(const std::vector<NodePtr>& statements) : AbstractListNode(statements) {} \ + NAME::NAME(NodeLocation location, const std::vector<NodePtr>& statements) : AbstractListNode(location, statements) {} \ std::ostream& NAME::print(std::ostream& stream, size_t indent) const __VA_ARGS__ OVDL_AST_LIST_NODE_DEF(FileNode, { @@ -178,9 +188,11 @@ OVDL_AST_LIST_NODE_DEF(DecisionListNode, { #undef OVDL_AST_LIST_NODE_DEF -EventNode::EventNode(Type type, const std::vector<NodePtr>& statements) : _type(type) { +EventNode::EventNode(NodeLocation location, Type type, const std::vector<NodePtr>& statements) : Node(location), + _type(type) { copy_into_node_ptr_vector(statements, _statements); } +EventNode::EventNode(Type type, const std::vector<NodePtr>& statements) : EventNode({}, type, statements) {} std::ostream& EventNode::print(std::ostream& stream, size_t indent) const { switch (_type) { case Type::Country: stream << "country_event = "; break; @@ -194,9 +206,11 @@ std::ostream& EventNode::print(std::ostream& stream, size_t indent) const { return stream << '}'; } -DecisionNode::DecisionNode(NodePtr name, const std::vector<NodePtr>& statements) : _name(std::move(name)) { +DecisionNode::DecisionNode(NodeLocation location, NodePtr name, const std::vector<NodePtr>& statements) : Node(location), + _name(std::move(name)) { copy_into_node_ptr_vector(statements, _statements); } +DecisionNode::DecisionNode(NodePtr name, const std::vector<NodePtr>& statements) : DecisionNode({}, name, statements) {} std::ostream& DecisionNode::print(std::ostream& stream, size_t indent) const { print_ptr(stream, _name.get(), indent) << " = {"; if (!_statements.empty()) { @@ -206,10 +220,12 @@ std::ostream& DecisionNode::print(std::ostream& stream, size_t indent) const { return stream << '}'; } -ExecutionNode::ExecutionNode(Type type, NodePtr name, NodePtr init) : _type(type), - _name(std::move(name)), - _initializer(std::move(init)) { +ExecutionNode::ExecutionNode(NodeLocation location, Type type, NodePtr name, NodePtr init) : Node(location), + _type(type), + _name(std::move(name)), + _initializer(std::move(init)) { } +ExecutionNode::ExecutionNode(Type type, NodePtr name, NodePtr init) : ExecutionNode({}, type, name, init) {} std::ostream& ExecutionNode::print(std::ostream& stream, size_t indent) const { print_ptr(stream, _name.get(), indent) << " = "; if (_initializer) { @@ -218,9 +234,11 @@ std::ostream& ExecutionNode::print(std::ostream& stream, size_t indent) const { return stream; } -ExecutionListNode::ExecutionListNode(ExecutionNode::Type type, const std::vector<NodePtr>& statements) : _type(type) { +ExecutionListNode::ExecutionListNode(NodeLocation location, ExecutionNode::Type type, const std::vector<NodePtr>& statements) : Node(location), + _type(type) { copy_into_node_ptr_vector(statements, _statements); } +ExecutionListNode::ExecutionListNode(ExecutionNode::Type type, const std::vector<NodePtr>& statements) : ExecutionListNode({}, type, statements) {} std::ostream& ExecutionListNode::print(std::ostream& stream, size_t indent) const { // Only way to make a valid declared parsable file stream << "{ "; @@ -244,4 +262,4 @@ Node::operator std::string() const { std::ostream& AssignNode::print(std::ostream& stream, size_t indent) const { stream << _name << " = "; return Node::print_ptr(stream, _initializer.get(), indent); -} +}
\ No newline at end of file diff --git a/src/openvic-dataloader/v2script/ModifierGrammar.hpp b/src/openvic-dataloader/v2script/ModifierGrammar.hpp index ad0704a..632cfd5 100644 --- a/src/openvic-dataloader/v2script/ModifierGrammar.hpp +++ b/src/openvic-dataloader/v2script/ModifierGrammar.hpp @@ -27,7 +27,7 @@ namespace ovdl::v2script::grammar { lexy::as_list<std::vector<ast::NodePtr>> >> lexy::callback<ast::NodePtr>( [](auto&& list) { - return make_node_ptr<ast::ModifierNode>(LEXY_MOV(list)); + return ast::make_node_ptr<ast::ModifierNode>(LEXY_MOV(list)); }); }; }
\ No newline at end of file diff --git a/src/openvic-dataloader/v2script/Parser.cpp b/src/openvic-dataloader/v2script/Parser.cpp index 07d6455..1258bca 100644 --- a/src/openvic-dataloader/v2script/Parser.cpp +++ b/src/openvic-dataloader/v2script/Parser.cpp @@ -12,6 +12,7 @@ #include <openvic-dataloader/ParseWarning.hpp> #include <openvic-dataloader/detail/Concepts.hpp> #include <openvic-dataloader/v2script/AbstractSyntaxTree.hpp> +#include <openvic-dataloader/v2script/NodeLocationMap.hpp> #include <lexy/action/parse.hpp> #include <lexy/encoding.hpp> @@ -57,8 +58,14 @@ public: return _root; } + ast::NodeLocationMap<decltype(_buffer)>& get_location_map() { + return _location_map; + } + private: + friend class ::ovdl::v2script::ast::Node; std::unique_ptr<ast::Node> _root; + ast::NodeLocationMap<decltype(_buffer)> _location_map; }; /// BufferHandler /// @@ -221,4 +228,60 @@ bool Parser::decision_parse() { const FileNode* Parser::get_file_node() const { return _file_node.get(); +} + +void Parser::generate_node_location_map() { + _buffer_handler->get_location_map().clear(); + _buffer_handler->get_location_map().generate_location_map(_buffer_handler->get_buffer(), get_file_node()); +} + +const ast::Node::line_col Parser::get_node_begin(const ast::NodeCPtr node) const { + if (!node) return { 0, 0 }; + return node->get_begin_line_col(*this); +} + +const ast::Node::line_col Parser::get_node_end(const ast::NodeCPtr node) const { + if (!node) return { 0, 0 }; + return node->get_end_line_col(*this); +} + +const ast::Node::line_col ast::Node::get_begin_line_col(const Parser& parser) const { + if (!parser._buffer_handler->is_valid() || parser._buffer_handler->_location_map.empty()) return {}; + line_col result; + auto [itr, range_end] = parser._buffer_handler->_location_map.equal_range(this); + if (itr != range_end) { + result.line = itr->second.line_nr(); + result.column = itr->second.column_nr(); + } + // Standard doesn't really guarantee the direction of the range's sequence, but only GCC goes backwards + // TODO: DON'T USE STANDARD UNORDERED_MULTIMAP +#if defined(__GNUC__) && !defined(__clang__) + itr++; + if (itr != range_end) { + result.line = itr->second.line_nr(); + result.column = itr->second.column_nr(); + } +#endif + return result; +} + +const ast::Node::line_col ast::Node::get_end_line_col(const Parser& parser) const { + if (!parser._buffer_handler->is_valid() || parser._buffer_handler->_location_map.empty()) return {}; + line_col result; + auto [itr, range_end] = parser._buffer_handler->_location_map.equal_range(this); + if (itr != range_end) { + result.line = itr->second.line_nr(); + result.column = itr->second.column_nr(); + } + // Standard doesn't really guarantee the direction of the range's sequence, but only GCC goes backwards + // TODO: DON'T USE STANDARD UNORDERED_MULTIMAP +#if defined(__GNUC__) && !defined(__clang__) + return result; +#endif + itr++; + if (itr != range_end) { + result.line = itr->second.line_nr(); + result.column = itr->second.column_nr(); + } + return result; }
\ No newline at end of file diff --git a/src/openvic-dataloader/v2script/SimpleGrammar.hpp b/src/openvic-dataloader/v2script/SimpleGrammar.hpp index c91935e..3e9a96e 100644 --- a/src/openvic-dataloader/v2script/SimpleGrammar.hpp +++ b/src/openvic-dataloader/v2script/SimpleGrammar.hpp @@ -32,7 +32,11 @@ namespace ovdl::v2script::grammar { struct Identifier { static constexpr auto rule = lexy::dsl::identifier(data_char_class); - static constexpr auto value = lexy::as_string<std::string> | lexy::new_<ast::IdentifierNode, ast::NodePtr>; + static constexpr auto value = lexy::callback<ast::NodePtr>( + [](auto lexeme) { + std::string str(lexeme.data(), lexeme.size()); + return ast::make_node_ptr<ast::IdentifierNode>(ast::NodeLocation { lexeme.begin(), lexeme.end() }, LEXY_MOV(str)); + }); }; struct StringExpression { @@ -55,57 +59,73 @@ namespace ovdl::v2script::grammar { // or a Unicode code point of the form uXXXX. auto escape = lexy::dsl::backslash_escape // .symbol<escaped_symbols>(); - return lexy::dsl::quoted(c, escape); + return lexy::dsl::delimited(lexy::dsl::position(lexy::dsl::lit_b<'"'>))(c, escape); }(); - static constexpr auto value = lexy::as_string<std::string> >> lexy::new_<ast::StringNode, ast::NodePtr>; + static constexpr auto value = + lexy::as_string<std::string> >> + lexy::callback<ast::NodePtr>( + [](const char* begin, auto&& str, const char* end) { + return ast::make_node_ptr<ast::StringNode>(ast::NodeLocation::make_from(begin, end), LEXY_MOV(str)); + }); }; struct SimpleAssignmentStatement { static constexpr auto rule = - lexy::dsl::p<Identifier> >> + lexy::dsl::position(lexy::dsl::p<Identifier>) >> lexy::dsl::equal_sign + (lexy::dsl::p<Identifier> | lexy::dsl::p<StringExpression> | lexy::dsl::recurse_branch<StatementListBlock>); static constexpr auto value = lexy::callback<ast::NodePtr>( - [](auto name, auto&& initalizer) { - return make_node_ptr<ast::AssignNode>(LEXY_MOV(name), LEXY_MOV(initalizer)); + [](const char* pos, auto name, auto&& initalizer) { + return ast::make_node_ptr<ast::AssignNode>(pos, LEXY_MOV(name), LEXY_MOV(initalizer)); }); }; struct AssignmentStatement { static constexpr auto rule = - lexy::dsl::p<Identifier> >> + lexy::dsl::position(lexy::dsl::p<Identifier>) >> (lexy::dsl::equal_sign >> (lexy::dsl::p<Identifier> | lexy::dsl::p<StringExpression> | lexy::dsl::recurse_branch<StatementListBlock>) | lexy::dsl::else_ >> lexy::dsl::return_) | lexy::dsl::p<StringExpression>; static constexpr auto value = lexy::callback<ast::NodePtr>( + [](const char* pos, auto name, lexy::nullopt = {}) { + return LEXY_MOV(name); + }, [](auto name, lexy::nullopt = {}) { return LEXY_MOV(name); }, - [](auto name, auto&& initalizer) { - return make_node_ptr<ast::AssignNode>(LEXY_MOV(name), LEXY_MOV(initalizer)); + [](const char* pos, auto name, auto&& initalizer) { + return ast::make_node_ptr<ast::AssignNode>(pos, LEXY_MOV(name), LEXY_MOV(initalizer)); }); }; struct StatementListBlock { static constexpr auto rule = - lexy::dsl::curly_bracketed( - lexy::dsl::opt(lexy::dsl::list(lexy::dsl::p<AssignmentStatement>)) + lexy::dsl::opt(lexy::dsl::semicolon)); + lexy::dsl::position(lexy::dsl::curly_bracketed.open()) >> + lexy::dsl::opt(lexy::dsl::list(lexy::dsl::p<AssignmentStatement>)) + + lexy::dsl::opt(lexy::dsl::semicolon) >> + lexy::dsl::position(lexy::dsl::curly_bracketed.close()); static constexpr auto value = lexy::as_list<std::vector<ast::NodePtr>> >> lexy::callback<ast::NodePtr>( - [](lexy::nullopt = {}, lexy::nullopt = {}) { - return ast::make_node_ptr<ast::ListNode>(); + [](const char* begin, lexy::nullopt, const char* end) { + return ast::make_node_ptr<ast::ListNode>(ast::NodeLocation::make_from(begin, end)); + }, + [](const char* begin, auto&& list, const char* end) { + return ast::make_node_ptr<ast::ListNode>(ast::NodeLocation::make_from(begin, end), LEXY_MOV(list)); + }, + [](const char* begin, lexy::nullopt, lexy::nullopt, const char* end) { + return ast::make_node_ptr<ast::ListNode>(ast::NodeLocation::make_from(begin, end)); }, - [](auto&& list, lexy::nullopt = {}) { - return make_node_ptr<ast::ListNode>(LEXY_MOV(list)); + [](const char* begin, auto&& list, lexy::nullopt, const char* end) { + return ast::make_node_ptr<ast::ListNode>(ast::NodeLocation::make_from(begin, end), LEXY_MOV(list)); }, - [](auto& list) { - return make_node_ptr<ast::ListNode>(list); + [](const char* begin, auto& list, const char* end) { + return ast::make_node_ptr<ast::ListNode>(ast::NodeLocation::make_from(begin, end), list); }); }; @@ -113,7 +133,7 @@ namespace ovdl::v2script::grammar { // Allow arbitrary spaces between individual tokens. static constexpr auto whitespace = whitespace_specifier | comment_specifier; - static constexpr auto rule = lexy::dsl::terminator(lexy::dsl::eof).list(lexy::dsl::p<AssignmentStatement>); + static constexpr auto rule = lexy::dsl::position + lexy::dsl::terminator(lexy::dsl::eof).list(lexy::dsl::p<AssignmentStatement>); static constexpr auto value = lexy::as_list<std::vector<ast::NodePtr>> >> lexy::new_<ast::FileNode, ast::NodePtr>; }; diff --git a/src/openvic-dataloader/v2script/TriggerGrammar.hpp b/src/openvic-dataloader/v2script/TriggerGrammar.hpp index 290fb70..6d964db 100644 --- a/src/openvic-dataloader/v2script/TriggerGrammar.hpp +++ b/src/openvic-dataloader/v2script/TriggerGrammar.hpp @@ -13,7 +13,7 @@ namespace ovdl::v2script::grammar { static constexpr auto value = lexy::callback<ast::NodePtr>( [](auto name, auto&& initalizer) { - return ast::make_node_ptr<ast::ExecutionNode>(ast::ExecutionNode::Type::Trigger, LEXY_MOV(name), LEXY_MOV(initalizer)); + return ast::make_node_ptr<ast::ExecutionNode>({}, ast::ExecutionNode::Type::Trigger, LEXY_MOV(name), LEXY_MOV(initalizer)); }); }; |