From 1d2c5ce39d12adcb584d586952a59e15f2495f67 Mon Sep 17 00:00:00 2001 From: Spartan322 Date: Sat, 2 Sep 2023 23:56:26 -0400 Subject: Add Node Line/Column Generator Fix Errors.hpp dependency on v2script/Parser.hpp Add node location print to headless/main.cpp Add Node::line_col << operator Add Node::cast_to WARNING: Takes advantage of non-standard behavior in unordered_multimap THIS IS A HACK FOR NOW Only GCC unordered_multimap::equal_range sees elements backwards Prefer moving off of unordered_multimap to something like EASTL hash_multimap --- .../v2script/NodeLocationMap.hpp | 91 ++++++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 include/openvic-dataloader/v2script/NodeLocationMap.hpp (limited to 'include/openvic-dataloader/v2script/NodeLocationMap.hpp') diff --git a/include/openvic-dataloader/v2script/NodeLocationMap.hpp b/include/openvic-dataloader/v2script/NodeLocationMap.hpp new file mode 100644 index 0000000..aa88d62 --- /dev/null +++ b/include/openvic-dataloader/v2script/NodeLocationMap.hpp @@ -0,0 +1,91 @@ +#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 -- cgit v1.2.3-56-ga3b1