aboutsummaryrefslogtreecommitdiff
path: root/include/openvic-dataloader/AbstractSyntaxTree.hpp
blob: db81eebdf8bdd3746cf2e81b7229954fa965cfc4 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#pragma once

#include <concepts>
#include <cstdio>
#include <string_view>
#include <utility>

#include <openvic-dataloader/File.hpp>
#include <openvic-dataloader/NodeLocation.hpp>
#include <openvic-dataloader/detail/utility/Utility.hpp>

#include <dryad/node.hpp>
#include <dryad/node_map.hpp>
#include <dryad/symbol.hpp>
#include <dryad/tree.hpp>

#include <fmt/core.h>

namespace ovdl {
   struct AbstractSyntaxTree {
      struct SymbolId;
      using index_type = std::uint32_t;
      using symbol_type = dryad::symbol<SymbolId, index_type>;
      using symbol_interner_type = dryad::symbol_interner<SymbolId, char, index_type>;

      symbol_type intern(const char* str, std::size_t length);
      symbol_type intern(std::string_view str);
      const char* intern_cstr(const char* str, std::size_t length);
      const char* intern_cstr(std::string_view str);
      symbol_interner_type& symbol_interner();
      const symbol_interner_type& symbol_interner() const;

   protected:
      symbol_interner_type _symbol_interner;
   };

   template<typename T>
   concept IsAst =
      std::derived_from<T, AbstractSyntaxTree> &&
      requires(
         T t,
         const T ct,
         const typename T::node_type* node,
         NodeLocation loc //
      ) {
         requires IsFile<typename T::file_type>;
         typename T::root_node_type;
         typename T::node_type;
         requires std::derived_from<typename T::root_node_type, typename T::node_type>;
         { t.set_location(node, loc) } -> std::same_as<void>;
         { t.location_of(node) } -> std::same_as<NodeLocation>;
         { t.root() } -> std::same_as<typename T::root_node_type*>;
         { ct.root() } -> std::same_as<const typename T::root_node_type*>;
         { t.file() } -> std::same_as<typename T::file_type&>;
         { ct.file() } -> std::same_as<const typename T::file_type&>;
      };

   template<IsFile FileT, std::derived_from<typename FileT::node_type> RootNodeT>
   struct BasicAbstractSyntaxTree : AbstractSyntaxTree {
      using file_type = FileT;
      using root_node_type = RootNodeT;
      using node_type = typename file_type::node_type;

      explicit BasicAbstractSyntaxTree(file_type&& file) : _file(std::move(file)) {}
      explicit BasicAbstractSyntaxTree(lexy::buffer<typename file_type::encoding_type, void>&& buffer) : _file(std::move(buffer)) {}

      void set_location(const node_type* n, NodeLocation loc) {
         _file.set_location(n, loc);
      }

      NodeLocation location_of(const node_type* n) const {
         return _file.location_of(n);
      }

      root_node_type* root() {
         return _tree.root();
      }

      const root_node_type* root() const {
         return _tree.root();
      }

      file_type& file() {
         return _file;
      }

      const file_type& file() const {
         return _file;
      }

      template<typename T, typename... Args>
      T* create(NodeLocation loc, Args&&... args) {
         auto node = _tree.template create<T>(DRYAD_FWD(args)...);
         set_location(node, loc);
         return node;
      }

      template<typename T, typename... Args>
      T* create(const char* begin, const char* end, Args&&... args) {
         return create<T>(NodeLocation::make_from(begin, end), DRYAD_FWD(args)...);
      }

      void set_root(root_node_type* node) {
         _tree.set_root(node);
      }

   protected:
      dryad::tree<root_node_type> _tree;
      file_type _file;
   };
}